mirror of
https://github.com/joel16/android_kernel_sony_msm8994_rework.git
synced 2024-11-27 05:40:41 +00:00
Merge tag 'v3.10.97' into lineage-15.1
66b4554 Linux 3.10.97 d67d24e binfmt_elf: Don't clobber passed executable's file header 669e0b0 FS-Cache: Increase reference of parent after registering, netfs success 471b813 crypto: user - lock crypto_alg_list on alg dump 9250afa crypto: algif_hash - wait for crypto_ahash_init() to complete 71eec87 ahci: Intel DNV device IDs SATA f6c2bfd libata: disable forced PORTS_IMPL for >= AHCI 1.3 d2b76ee AHCI: Fix softreset failed issue of Port Multiplier f77597b crypto: af_alg - Fix socket double-free when accept fails 5a707f0 crypto: af_alg - Disallow bind/setkey/... after accept(2) 766ac2a ext4: Fix handling of extended tv_sec 6f2db87 tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) 4478e22 USB: option: fix Cinterion AHxx enumeration 3bee9e6 USB: serial: option: Adding support for Telit LE922 e193199 USB: cp210x: add ID for IAI USB to RS485 adaptor 03b987c USB: serial: ftdi_sio: add support for Yaesu SCU-18 cable f1a9ca0 USB: visor: fix null-deref at probe 3b079e3 USB: serial: visor: fix crash on detecting device without write_urbs 24e1fdb USB: ti_usb_3410_502: Fix ID table size d5ce15e saa7134-alsa: Only frees registered sound cards 49911dc ALSA: timer: Fix race between stop and interrupt e063b1a ALSA: dummy: Implement timer backend switching more safely c5929da ALSA: hda - Fix speaker output from VAIO AiO machines 538d254 ALSA: timer: Fix wrong instance passed to slave callbacks 8a77871 ALSA: timer: Fix link corruption due to double start or stop 732bc47 ALSA: timer: Fix leftover link at closing 51e9bd7 ALSA: timer: Code cleanup e53ec49 ALSA: seq: Fix lockdep warnings due to double mutex locks 14bdca3 ALSA: seq: Fix race at closing in virmidi driver 4df6314 ALSA: seq: Fix yet another races among ALSA timer accesses f042b75 ASoC: dpcm: fix the BE state on hw_free aae80d6 ALSA: pcm: Fix potential deadlock in OSS emulation 264df9e ALSA: rawmidi: Fix race at copying & updating the position f6cbda7 ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check a04cbfb ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() 3e24e59 ALSA: dummy: Disable switching timer backend via sysfs 074e46b ALSA: compress: Disable GET_CODEC_CAPS ioctl for some architectures 482c4c1 ALSA: usb-audio: avoid freeing umidi object twice fc34588 ALSA: usb-audio: Fix TEAC UD-501/UD-503/NT-503 usb delay 8634750 fix sysvfs symlinks 53587d46 media: vb2 dma-contig: Fully cache synchronise buffers in prepare and finish 1b97331 v4l2-compat-ioctl32: fix alignment for ARM64 4fdefe9 parisc: Fix __ARCH_SI_PREAMBLE_SIZE fedff89 parisc: Fix syscall restarts d2bb787 parisc: Drop unused MADV_xxxK_PAGES flags from asm/mman.h 1daeb19 fix calculation of meta_bg descriptor backups 1174350 jbd2: Fix unreclaimed pages after truncate in data=journal mode 98b3bd6 mtd: mtdpart: fix add_mtd_partitions error path 2acba4b vTPM: fix memory allocation flag for rtce buffer at kernel boot c0d57f2 wlcore/wl12xx: spi: fix NULL pointer dereference (Oops) 0d20999 wlcore/wl12xx: spi: fix oops on firmware load 1dcdf54 spi: fix parent-device reference leak 092f4b7 spi: atmel: Fix DMA-setup for transfers with more than 8 bits per word 0fd9b8b Revert "dm mpath: fix stalls when handling invalid ioctls" 516932b sh64: fix __NR_fgetxattr bb169b2 ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup 854e6fc ocfs2/dlm: ignore cleaning the migration mle that is inuse fa17bfe kernel/signal.c: unexport sigsuspend() 2ed0426 remoteproc: avoid stack overflow in debugfs file e9828fd HID: usbhid: fix recursive deadlock d6671b0 dm btree: fix leak of bufio-backed block in btree_split_sibling error path daaf3fd crypto: algif_hash - Only export and import on sockets with data 12c1515 xhci: fix placement of call to usb_disabled() 4bd503f recordmcount: Fix endianness handling bug for nop_mcount Signed-off-by: Rk779 <Rahulkrishna585@gmail.com>
This commit is contained in:
parent
73f61860b9
commit
d2b0f64696
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
VERSION = 3
|
||||
PATCHLEVEL = 10
|
||||
SUBLEVEL = 96
|
||||
SUBLEVEL = 97
|
||||
EXTRAVERSION =
|
||||
NAME = TOSSUG Baby Fish
|
||||
|
||||
|
@ -46,16 +46,6 @@
|
||||
#define MADV_DONTFORK 10 /* don't inherit across fork */
|
||||
#define MADV_DOFORK 11 /* do inherit across fork */
|
||||
|
||||
/* The range 12-64 is reserved for page size specification. */
|
||||
#define MADV_4K_PAGES 12 /* Use 4K pages */
|
||||
#define MADV_16K_PAGES 14 /* Use 16K pages */
|
||||
#define MADV_64K_PAGES 16 /* Use 64K pages */
|
||||
#define MADV_256K_PAGES 18 /* Use 256K pages */
|
||||
#define MADV_1M_PAGES 20 /* Use 1 Megabyte pages */
|
||||
#define MADV_4M_PAGES 22 /* Use 4 Megabyte pages */
|
||||
#define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */
|
||||
#define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */
|
||||
|
||||
#define MADV_MERGEABLE 65 /* KSM may merge identical pages */
|
||||
#define MADV_UNMERGEABLE 66 /* KSM may not merge identical pages */
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
#ifndef _PARISC_SIGINFO_H
|
||||
#define _PARISC_SIGINFO_H
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
|
||||
#endif
|
||||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
#undef NSIGTRAP
|
||||
|
@ -449,6 +449,55 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
regs->gr[28]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check how the syscall number gets loaded into %r20 within
|
||||
* the delay branch in userspace and adjust as needed.
|
||||
*/
|
||||
|
||||
static void check_syscallno_in_delay_branch(struct pt_regs *regs)
|
||||
{
|
||||
u32 opcode, source_reg;
|
||||
u32 __user *uaddr;
|
||||
int err;
|
||||
|
||||
/* Usually we don't have to restore %r20 (the system call number)
|
||||
* because it gets loaded in the delay slot of the branch external
|
||||
* instruction via the ldi instruction.
|
||||
* In some cases a register-to-register copy instruction might have
|
||||
* been used instead, in which case we need to copy the syscall
|
||||
* number into the source register before returning to userspace.
|
||||
*/
|
||||
|
||||
/* A syscall is just a branch, so all we have to do is fiddle the
|
||||
* return pointer so that the ble instruction gets executed again.
|
||||
*/
|
||||
regs->gr[31] -= 8; /* delayed branching */
|
||||
|
||||
/* Get assembler opcode of code in delay branch */
|
||||
uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
|
||||
err = get_user(opcode, uaddr);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
/* Check if delay branch uses "ldi int,%r20" */
|
||||
if ((opcode & 0xffff0000) == 0x34140000)
|
||||
return; /* everything ok, just return */
|
||||
|
||||
/* Check if delay branch uses "nop" */
|
||||
if (opcode == INSN_NOP)
|
||||
return;
|
||||
|
||||
/* Check if delay branch uses "copy %rX,%r20" */
|
||||
if ((opcode & 0xffe0ffff) == 0x08000254) {
|
||||
source_reg = (opcode >> 16) & 31;
|
||||
regs->gr[source_reg] = regs->gr[20];
|
||||
return;
|
||||
}
|
||||
|
||||
pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
|
||||
current->comm, task_pid_nr(current), opcode);
|
||||
}
|
||||
|
||||
static inline void
|
||||
syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
{
|
||||
@ -471,10 +520,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
}
|
||||
/* fallthrough */
|
||||
case -ERESTARTNOINTR:
|
||||
/* A syscall is just a branch, so all
|
||||
* we have to do is fiddle the return pointer.
|
||||
*/
|
||||
regs->gr[31] -= 8; /* delayed branching */
|
||||
check_syscallno_in_delay_branch(regs);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -523,15 +569,9 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
}
|
||||
case -ERESTARTNOHAND:
|
||||
case -ERESTARTSYS:
|
||||
case -ERESTARTNOINTR: {
|
||||
/* Hooray for delayed branching. We don't
|
||||
* have to restore %r20 (the system call
|
||||
* number) because it gets loaded in the delay
|
||||
* slot of the branch external instruction.
|
||||
*/
|
||||
regs->gr[31] -= 8;
|
||||
case -ERESTARTNOINTR:
|
||||
check_syscallno_in_delay_branch(regs);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -278,7 +278,7 @@
|
||||
#define __NR_fsetxattr 256
|
||||
#define __NR_getxattr 257
|
||||
#define __NR_lgetxattr 258
|
||||
#define __NR_fgetxattr 269
|
||||
#define __NR_fgetxattr 259
|
||||
#define __NR_listxattr 260
|
||||
#define __NR_llistxattr 261
|
||||
#define __NR_flistxattr 262
|
||||
|
@ -125,6 +125,23 @@ int af_alg_release(struct socket *sock)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(af_alg_release);
|
||||
|
||||
void af_alg_release_parent(struct sock *sk)
|
||||
{
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
bool last;
|
||||
|
||||
sk = ask->parent;
|
||||
ask = alg_sk(sk);
|
||||
|
||||
lock_sock(sk);
|
||||
last = !--ask->refcnt;
|
||||
release_sock(sk);
|
||||
|
||||
if (last)
|
||||
sock_put(sk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(af_alg_release_parent);
|
||||
|
||||
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
@ -132,6 +149,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
struct sockaddr_alg *sa = (void *)uaddr;
|
||||
const struct af_alg_type *type;
|
||||
void *private;
|
||||
int err;
|
||||
|
||||
if (sock->state == SS_CONNECTED)
|
||||
return -EINVAL;
|
||||
@ -157,16 +175,22 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
return PTR_ERR(private);
|
||||
}
|
||||
|
||||
err = -EBUSY;
|
||||
lock_sock(sk);
|
||||
if (ask->refcnt)
|
||||
goto unlock;
|
||||
|
||||
swap(ask->type, type);
|
||||
swap(ask->private, private);
|
||||
|
||||
err = 0;
|
||||
|
||||
unlock:
|
||||
release_sock(sk);
|
||||
|
||||
alg_do_release(type, private);
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int alg_setkey(struct sock *sk, char __user *ukey,
|
||||
@ -199,11 +223,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
|
||||
struct sock *sk = sock->sk;
|
||||
struct alg_sock *ask = alg_sk(sk);
|
||||
const struct af_alg_type *type;
|
||||
int err = -ENOPROTOOPT;
|
||||
int err = -EBUSY;
|
||||
|
||||
lock_sock(sk);
|
||||
if (ask->refcnt)
|
||||
goto unlock;
|
||||
|
||||
type = ask->type;
|
||||
|
||||
err = -ENOPROTOOPT;
|
||||
if (level != SOL_ALG || !type)
|
||||
goto unlock;
|
||||
|
||||
@ -247,14 +275,13 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
|
||||
security_sk_clone(sk, sk2);
|
||||
|
||||
err = type->accept(ask->private, sk2);
|
||||
if (err) {
|
||||
sk_free(sk2);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
sk2->sk_family = PF_ALG;
|
||||
|
||||
sock_hold(sk);
|
||||
if (!ask->refcnt++)
|
||||
sock_hold(sk);
|
||||
alg_sk(sk2)->parent = sk;
|
||||
alg_sk(sk2)->type = type;
|
||||
|
||||
|
@ -51,7 +51,8 @@ static int hash_sendmsg(struct kiocb *unused, struct socket *sock,
|
||||
|
||||
lock_sock(sk);
|
||||
if (!ctx->more) {
|
||||
err = crypto_ahash_init(&ctx->req);
|
||||
err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
|
||||
&ctx->completion);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
@ -131,6 +132,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
|
||||
} else {
|
||||
if (!ctx->more) {
|
||||
err = crypto_ahash_init(&ctx->req);
|
||||
err = af_alg_wait_for_completion(err, &ctx->completion);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
@ -192,9 +194,14 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
|
||||
struct sock *sk2;
|
||||
struct alg_sock *ask2;
|
||||
struct hash_ctx *ctx2;
|
||||
bool more;
|
||||
int err;
|
||||
|
||||
err = crypto_ahash_export(req, state);
|
||||
lock_sock(sk);
|
||||
more = ctx->more;
|
||||
err = more ? crypto_ahash_export(req, state) : 0;
|
||||
release_sock(sk);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@ -205,7 +212,10 @@ static int hash_accept(struct socket *sock, struct socket *newsock, int flags)
|
||||
sk2 = newsock->sk;
|
||||
ask2 = alg_sk(sk2);
|
||||
ctx2 = ask2->private;
|
||||
ctx2->more = 1;
|
||||
ctx2->more = more;
|
||||
|
||||
if (!more)
|
||||
return err;
|
||||
|
||||
err = crypto_ahash_import(&ctx2->req, state);
|
||||
if (err) {
|
||||
|
@ -477,6 +477,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
if (link->dump == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&crypto_alg_sem);
|
||||
list_for_each_entry(alg, &crypto_alg_list, cra_list)
|
||||
dump_alloc += CRYPTO_REPORT_MAXSIZE;
|
||||
|
||||
@ -486,8 +487,11 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
.done = link->done,
|
||||
.min_dump_alloc = dump_alloc,
|
||||
};
|
||||
return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
|
||||
err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
|
||||
}
|
||||
up_read(&crypto_alg_sem);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
|
||||
|
@ -247,6 +247,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
|
||||
|
@ -486,8 +486,8 @@ void ahci_save_initial_config(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* fabricate port_map from cap.nr_ports */
|
||||
if (!port_map) {
|
||||
/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
|
||||
if (!port_map && vers < 0x10300) {
|
||||
port_map = (1 << ahci_nr_ports(cap)) - 1;
|
||||
dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
|
||||
|
||||
@ -1244,6 +1244,15 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
|
||||
ata_tf_to_fis(tf, pmp, is_cmd, fis);
|
||||
ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
|
||||
|
||||
/* set port value for softreset of Port Multiplier */
|
||||
if (pp->fbs_enabled && pp->fbs_last_dev != pmp) {
|
||||
tmp = readl(port_mmio + PORT_FBS);
|
||||
tmp &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
|
||||
tmp |= pmp << PORT_FBS_DEV_OFFSET;
|
||||
writel(tmp, port_mmio + PORT_FBS);
|
||||
pp->fbs_last_dev = pmp;
|
||||
}
|
||||
|
||||
/* issue & wait */
|
||||
writel(1, port_mmio + PORT_CMD_ISSUE);
|
||||
|
||||
|
@ -529,7 +529,7 @@ static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq,
|
||||
}
|
||||
ibmvtpm->rtce_size = be16_to_cpu(crq->len);
|
||||
ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size,
|
||||
GFP_KERNEL);
|
||||
GFP_ATOMIC);
|
||||
if (!ibmvtpm->rtce_buf) {
|
||||
dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n");
|
||||
return;
|
||||
|
@ -490,8 +490,6 @@ static void hid_ctrl(struct urb *urb)
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int unplug = 0, status = urb->status;
|
||||
|
||||
spin_lock(&usbhid->lock);
|
||||
|
||||
switch (status) {
|
||||
case 0: /* success */
|
||||
if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
|
||||
@ -511,6 +509,8 @@ static void hid_ctrl(struct urb *urb)
|
||||
hid_warn(urb->dev, "ctrl urb status %d received\n", status);
|
||||
}
|
||||
|
||||
spin_lock(&usbhid->lock);
|
||||
|
||||
if (unplug) {
|
||||
usbhid->ctrltail = usbhid->ctrlhead;
|
||||
} else {
|
||||
|
@ -1608,11 +1608,8 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
|
||||
/*
|
||||
* Only pass ioctls through if the device sizes match exactly.
|
||||
*/
|
||||
if (!bdev || ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT) {
|
||||
int err = scsi_verify_blk_ioctl(NULL, cmd);
|
||||
if (err)
|
||||
r = err;
|
||||
}
|
||||
if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
|
||||
r = scsi_verify_blk_ioctl(NULL, cmd);
|
||||
|
||||
if (r == -ENOTCONN && !fatal_signal_pending(current))
|
||||
queue_work(kmultipathd, &m->process_queued_ios);
|
||||
|
@ -455,8 +455,10 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root,
|
||||
|
||||
r = insert_at(sizeof(__le64), pn, parent_index + 1,
|
||||
le64_to_cpu(rn->keys[0]), &location);
|
||||
if (r)
|
||||
if (r) {
|
||||
unlock_block(s->info, right);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (key < le64_to_cpu(rn->keys[0])) {
|
||||
unlock_block(s->info, right);
|
||||
|
@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa7134_dev *dev)
|
||||
|
||||
static int alsa_device_exit(struct saa7134_dev *dev)
|
||||
{
|
||||
if (!snd_saa7134_cards[dev->nr])
|
||||
return 1;
|
||||
|
||||
snd_card_free(snd_saa7134_cards[dev->nr]);
|
||||
snd_saa7134_cards[dev->nr] = NULL;
|
||||
@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void)
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < SNDRV_CARDS; idx++) {
|
||||
snd_card_free(snd_saa7134_cards[idx]);
|
||||
if (snd_saa7134_cards[idx])
|
||||
snd_card_free(snd_saa7134_cards[idx]);
|
||||
}
|
||||
|
||||
saa7134_dmasound_init = NULL;
|
||||
|
@ -264,7 +264,7 @@ static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_
|
||||
|
||||
struct v4l2_standard32 {
|
||||
__u32 index;
|
||||
__u32 id[2]; /* __u64 would get the alignment wrong */
|
||||
compat_u64 id;
|
||||
__u8 name[24];
|
||||
struct v4l2_fract frameperiod; /* Frames, not fields */
|
||||
__u32 framelines;
|
||||
@ -284,7 +284,7 @@ static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32
|
||||
{
|
||||
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
|
||||
put_user(kp->index, &up->index) ||
|
||||
copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
|
||||
put_user(kp->id, &up->id) ||
|
||||
copy_to_user(up->name, kp->name, 24) ||
|
||||
copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
|
||||
put_user(kp->framelines, &up->framelines) ||
|
||||
@ -598,10 +598,10 @@ struct v4l2_input32 {
|
||||
__u32 type; /* Type of input */
|
||||
__u32 audioset; /* Associated audios (bitfield) */
|
||||
__u32 tuner; /* Associated tuner */
|
||||
v4l2_std_id std;
|
||||
compat_u64 std;
|
||||
__u32 status;
|
||||
__u32 reserved[4];
|
||||
} __attribute__ ((packed));
|
||||
};
|
||||
|
||||
/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
|
||||
Otherwise it is identical to the 32-bit version. */
|
||||
@ -744,6 +744,7 @@ struct v4l2_event32 {
|
||||
struct v4l2_event_vsync vsync;
|
||||
struct v4l2_event_ctrl ctrl;
|
||||
struct v4l2_event_frame_sync frame_sync;
|
||||
compat_s64 value64;
|
||||
__u8 data[64];
|
||||
} u;
|
||||
__u32 pending;
|
||||
|
@ -117,7 +117,8 @@ static void vb2_dc_prepare(void *buf_priv)
|
||||
if (!sgt || buf->db_attach)
|
||||
return;
|
||||
|
||||
dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
|
||||
dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->orig_nents,
|
||||
buf->dma_dir);
|
||||
}
|
||||
|
||||
static void vb2_dc_finish(void *buf_priv)
|
||||
@ -129,7 +130,7 @@ static void vb2_dc_finish(void *buf_priv)
|
||||
if (!sgt || buf->db_attach)
|
||||
return;
|
||||
|
||||
dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
|
||||
dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
|
@ -644,8 +644,10 @@ int add_mtd_partitions(struct mtd_info *master,
|
||||
|
||||
for (i = 0; i < nbparts; i++) {
|
||||
slave = allocate_partition(master, parts + i, i, cur_offset);
|
||||
if (IS_ERR(slave))
|
||||
if (IS_ERR(slave)) {
|
||||
del_mtd_partitions(master);
|
||||
return PTR_ERR(slave);
|
||||
}
|
||||
|
||||
mutex_lock(&mtd_partitions_mutex);
|
||||
list_add(&slave->list, &mtd_partitions);
|
||||
|
@ -203,19 +203,23 @@ static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
|
||||
|
||||
static inline void wl1271_power_off(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
|
||||
return;
|
||||
|
||||
ret = wl->if_ops->power(wl->dev, false);
|
||||
if (wl->if_ops->power)
|
||||
ret = wl->if_ops->power(wl->dev, false);
|
||||
if (!ret)
|
||||
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
}
|
||||
|
||||
static inline int wl1271_power_on(struct wl1271 *wl)
|
||||
{
|
||||
int ret = wl->if_ops->power(wl->dev, true);
|
||||
int ret = 0;
|
||||
|
||||
if (wl->if_ops->power)
|
||||
ret = wl->if_ops->power(wl->dev, true);
|
||||
if (ret == 0)
|
||||
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
|
||||
|
||||
|
@ -72,7 +72,10 @@
|
||||
*/
|
||||
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
|
||||
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
|
||||
/* Maximum number of SPI write chunks */
|
||||
#define WSPI_MAX_NUM_OF_CHUNKS \
|
||||
((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
|
||||
|
||||
|
||||
struct wl12xx_spi_glue {
|
||||
struct device *dev;
|
||||
@ -270,9 +273,10 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
|
||||
void *buf, size_t len, bool fixed)
|
||||
{
|
||||
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
|
||||
struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)];
|
||||
/* SPI write buffers - 2 for each chunk */
|
||||
struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
|
||||
struct spi_message m;
|
||||
u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
|
||||
u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
|
||||
u32 *cmd;
|
||||
u32 chunk_len;
|
||||
int i;
|
||||
|
@ -156,7 +156,7 @@ rproc_recovery_write(struct file *filp, const char __user *user_buf,
|
||||
char buf[10];
|
||||
int ret;
|
||||
|
||||
if (count > sizeof(buf))
|
||||
if (count < 1 || count > sizeof(buf))
|
||||
return count;
|
||||
|
||||
ret = copy_from_user(buf, user_buf, count);
|
||||
|
@ -594,7 +594,8 @@ static int atmel_spi_next_xfer_dma_submit(struct spi_master *master,
|
||||
|
||||
*plen = len;
|
||||
|
||||
if (atmel_spi_dma_slave_config(as, &slave_config, 8))
|
||||
if (atmel_spi_dma_slave_config(as, &slave_config,
|
||||
xfer->bits_per_word))
|
||||
goto err_exit;
|
||||
|
||||
/* Send both scatterlists */
|
||||
|
@ -1047,7 +1047,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
|
||||
master->bus_num = -1;
|
||||
master->num_chipselect = 1;
|
||||
master->dev.class = &spi_master_class;
|
||||
master->dev.parent = get_device(dev);
|
||||
master->dev.parent = dev;
|
||||
spi_master_set_devdata(master, &master[1]);
|
||||
|
||||
return master;
|
||||
|
@ -4823,6 +4823,9 @@ static int __init xhci_hcd_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
retval = xhci_register_pci();
|
||||
if (retval < 0) {
|
||||
printk(KERN_DEBUG "Problem registering PCI driver.");
|
||||
@ -4851,9 +4854,6 @@ static int __init xhci_hcd_init(void)
|
||||
/* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */
|
||||
BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8);
|
||||
|
||||
if (usb_disabled())
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
unreg_pci:
|
||||
xhci_unregister_pci();
|
||||
|
@ -98,6 +98,7 @@ static const struct usb_device_id id_table[] = {
|
||||
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
|
||||
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
|
||||
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
|
||||
{ USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
|
||||
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
|
||||
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
|
||||
{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
|
||||
|
@ -840,6 +840,7 @@ static struct usb_device_id id_table_combined [] = {
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
|
||||
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
|
||||
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
|
||||
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
|
||||
|
||||
/* Papouch devices based on FTDI chip */
|
||||
|
@ -615,6 +615,7 @@
|
||||
*/
|
||||
#define RATOC_VENDOR_ID 0x0584
|
||||
#define RATOC_PRODUCT_ID_USB60F 0xb020
|
||||
#define RATOC_PRODUCT_ID_SCU18 0xb03a
|
||||
|
||||
/*
|
||||
* Infineon Technologies
|
||||
|
@ -269,6 +269,8 @@ static void option_instat_callback(struct urb *urb);
|
||||
#define TELIT_PRODUCT_CC864_SINGLE 0x1006
|
||||
#define TELIT_PRODUCT_DE910_DUAL 0x1010
|
||||
#define TELIT_PRODUCT_UE910_V2 0x1012
|
||||
#define TELIT_PRODUCT_LE922_USBCFG0 0x1042
|
||||
#define TELIT_PRODUCT_LE922_USBCFG3 0x1043
|
||||
#define TELIT_PRODUCT_LE920 0x1200
|
||||
#define TELIT_PRODUCT_LE910 0x1201
|
||||
|
||||
@ -623,6 +625,16 @@ static const struct option_blacklist_info telit_le920_blacklist = {
|
||||
.reserved = BIT(1) | BIT(5),
|
||||
};
|
||||
|
||||
static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
|
||||
.sendsetup = BIT(2),
|
||||
.reserved = BIT(0) | BIT(1) | BIT(3),
|
||||
};
|
||||
|
||||
static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
|
||||
.sendsetup = BIT(0),
|
||||
.reserved = BIT(1) | BIT(2) | BIT(3),
|
||||
};
|
||||
|
||||
static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
|
||||
@ -1168,6 +1180,10 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
|
||||
.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
|
||||
.driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
|
||||
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
|
||||
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
|
||||
@ -1679,7 +1695,7 @@ static const struct usb_device_id option_ids[] = {
|
||||
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
|
||||
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
|
||||
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
|
||||
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
|
||||
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
|
||||
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
|
||||
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
|
||||
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
|
||||
|
@ -158,7 +158,7 @@ static unsigned int product_5052_count;
|
||||
/* the array dimension is the number of default entries plus */
|
||||
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
|
||||
/* null entry */
|
||||
static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
static struct usb_device_id ti_id_table_3410[16+TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
|
||||
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
|
||||
@ -184,7 +184,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
|
||||
};
|
||||
|
||||
static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
static struct usb_device_id ti_id_table_combined[20+2*TI_EXTRA_VID_PID_COUNT+1] = {
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
|
||||
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
|
||||
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
|
||||
|
@ -551,6 +551,11 @@ static int treo_attach(struct usb_serial *serial)
|
||||
(serial->num_interrupt_in == 0))
|
||||
return 0;
|
||||
|
||||
if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
|
||||
dev_err(&serial->interface->dev, "missing endpoints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/*
|
||||
* It appears that Treos and Kyoceras want to use the
|
||||
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
|
||||
@ -604,8 +609,10 @@ static int clie_5_attach(struct usb_serial *serial)
|
||||
*/
|
||||
|
||||
/* some sanity check */
|
||||
if (serial->num_ports < 2)
|
||||
return -1;
|
||||
if (serial->num_bulk_out < 2) {
|
||||
dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* port 0 now uses the modified endpoint Address */
|
||||
port = serial->port[0];
|
||||
|
@ -682,16 +682,16 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
||||
*/
|
||||
would_dump(bprm, interpreter);
|
||||
|
||||
retval = kernel_read(interpreter, 0, bprm->buf,
|
||||
BINPRM_BUF_SIZE);
|
||||
if (retval != BINPRM_BUF_SIZE) {
|
||||
/* Get the exec headers */
|
||||
retval = kernel_read(interpreter, 0,
|
||||
(void *)&loc->interp_elf_ex,
|
||||
sizeof(loc->interp_elf_ex));
|
||||
if (retval != sizeof(loc->interp_elf_ex)) {
|
||||
if (retval >= 0)
|
||||
retval = -EIO;
|
||||
goto out_free_dentry;
|
||||
}
|
||||
|
||||
/* Get the exec headers */
|
||||
loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
|
||||
break;
|
||||
}
|
||||
elf_ppnt++;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <linux/seqlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/blockgroup_lock.h>
|
||||
#include <linux/percpu_counter.h>
|
||||
@ -728,19 +729,55 @@ struct move_extent {
|
||||
<= (EXT4_GOOD_OLD_INODE_SIZE + \
|
||||
(einode)->i_extra_isize)) \
|
||||
|
||||
/*
|
||||
* We use an encoding that preserves the times for extra epoch "00":
|
||||
*
|
||||
* extra msb of adjust for signed
|
||||
* epoch 32-bit 32-bit tv_sec to
|
||||
* bits time decoded 64-bit tv_sec 64-bit tv_sec valid time range
|
||||
* 0 0 1 -0x80000000..-0x00000001 0x000000000 1901-12-13..1969-12-31
|
||||
* 0 0 0 0x000000000..0x07fffffff 0x000000000 1970-01-01..2038-01-19
|
||||
* 0 1 1 0x080000000..0x0ffffffff 0x100000000 2038-01-19..2106-02-07
|
||||
* 0 1 0 0x100000000..0x17fffffff 0x100000000 2106-02-07..2174-02-25
|
||||
* 1 0 1 0x180000000..0x1ffffffff 0x200000000 2174-02-25..2242-03-16
|
||||
* 1 0 0 0x200000000..0x27fffffff 0x200000000 2242-03-16..2310-04-04
|
||||
* 1 1 1 0x280000000..0x2ffffffff 0x300000000 2310-04-04..2378-04-22
|
||||
* 1 1 0 0x300000000..0x37fffffff 0x300000000 2378-04-22..2446-05-10
|
||||
*
|
||||
* Note that previous versions of the kernel on 64-bit systems would
|
||||
* incorrectly use extra epoch bits 1,1 for dates between 1901 and
|
||||
* 1970. e2fsck will correct this, assuming that it is run on the
|
||||
* affected filesystem before 2242.
|
||||
*/
|
||||
|
||||
static inline __le32 ext4_encode_extra_time(struct timespec *time)
|
||||
{
|
||||
return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
|
||||
(time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
|
||||
((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
|
||||
u32 extra = sizeof(time->tv_sec) > 4 ?
|
||||
((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
|
||||
return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
|
||||
}
|
||||
|
||||
static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
|
||||
{
|
||||
if (sizeof(time->tv_sec) > 4)
|
||||
time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
|
||||
<< 32;
|
||||
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
|
||||
if (unlikely(sizeof(time->tv_sec) > 4 &&
|
||||
(extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
|
||||
/* Handle legacy encoding of pre-1970 dates with epoch
|
||||
* bits 1,1. We assume that by kernel version 4.20,
|
||||
* everyone will have run fsck over the affected
|
||||
* filesystems to correct the problem. (This
|
||||
* backwards compatibility may be removed before this
|
||||
* time, at the discretion of the ext4 developers.)
|
||||
*/
|
||||
u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
|
||||
if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
|
||||
extra_bits = 0;
|
||||
time->tv_sec += extra_bits << 32;
|
||||
#else
|
||||
time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
|
||||
#endif
|
||||
}
|
||||
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
|
||||
}
|
||||
|
||||
#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
|
||||
|
@ -1025,7 +1025,7 @@ exit_free:
|
||||
* do not copy the full number of backups at this time. The resize
|
||||
* which changed s_groups_count will backup again.
|
||||
*/
|
||||
static void update_backups(struct super_block *sb, int blk_off, char *data,
|
||||
static void update_backups(struct super_block *sb, sector_t blk_off, char *data,
|
||||
int size, int meta_bg)
|
||||
{
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
@ -1050,7 +1050,7 @@ static void update_backups(struct super_block *sb, int blk_off, char *data,
|
||||
group = ext4_list_backups(sb, &three, &five, &seven);
|
||||
last = sbi->s_groups_count;
|
||||
} else {
|
||||
group = ext4_meta_bg_first_group(sb, group) + 1;
|
||||
group = ext4_get_group_number(sb, blk_off) + 1;
|
||||
last = (ext4_group_t)(group + EXT4_DESC_PER_BLOCK(sb) - 2);
|
||||
}
|
||||
|
||||
|
@ -45,9 +45,6 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
|
||||
netfs->primary_index->parent = &fscache_fsdef_index;
|
||||
netfs->primary_index->netfs_data = netfs;
|
||||
|
||||
atomic_inc(&netfs->primary_index->parent->usage);
|
||||
atomic_inc(&netfs->primary_index->parent->n_children);
|
||||
|
||||
spin_lock_init(&netfs->primary_index->lock);
|
||||
INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
|
||||
|
||||
@ -60,6 +57,9 @@ int __fscache_register_netfs(struct fscache_netfs *netfs)
|
||||
goto already_registered;
|
||||
}
|
||||
|
||||
atomic_inc(&netfs->primary_index->parent->usage);
|
||||
atomic_inc(&netfs->primary_index->parent->n_children);
|
||||
|
||||
list_add(&netfs->link, &fscache_netfs_list);
|
||||
ret = 0;
|
||||
|
||||
@ -70,8 +70,7 @@ already_registered:
|
||||
up_write(&fscache_addremove_sem);
|
||||
|
||||
if (ret < 0) {
|
||||
netfs->primary_index->parent = NULL;
|
||||
__fscache_cookie_put(netfs->primary_index);
|
||||
kmem_cache_free(fscache_cookie_jar, netfs->primary_index);
|
||||
netfs->primary_index = NULL;
|
||||
}
|
||||
|
||||
|
@ -1936,6 +1936,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
|
||||
|
||||
if (!buffer_dirty(bh)) {
|
||||
/* bdflush has written it. We can drop it now */
|
||||
__jbd2_journal_remove_checkpoint(jh);
|
||||
goto zap_buffer;
|
||||
}
|
||||
|
||||
@ -1965,6 +1966,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
|
||||
/* The orphan record's transaction has
|
||||
* committed. We can cleanse this buffer */
|
||||
clear_buffer_jbddirty(bh);
|
||||
__jbd2_journal_remove_checkpoint(jh);
|
||||
goto zap_buffer;
|
||||
}
|
||||
}
|
||||
|
@ -2456,6 +2456,11 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
|
||||
spin_lock(&dlm->master_lock);
|
||||
ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
|
||||
namelen, target, dlm->node_num);
|
||||
/* get an extra reference on the mle.
|
||||
* otherwise the assert_master from the new
|
||||
* master will destroy this.
|
||||
*/
|
||||
dlm_get_mle_inuse(mle);
|
||||
spin_unlock(&dlm->master_lock);
|
||||
spin_unlock(&dlm->spinlock);
|
||||
|
||||
@ -2491,6 +2496,7 @@ fail:
|
||||
if (mle_added) {
|
||||
dlm_mle_detach_hb_events(dlm, mle);
|
||||
dlm_put_mle(mle);
|
||||
dlm_put_mle_inuse(mle);
|
||||
} else if (mle) {
|
||||
kmem_cache_free(dlm_mle_cache, mle);
|
||||
mle = NULL;
|
||||
@ -2508,17 +2514,6 @@ fail:
|
||||
* ensure that all assert_master work is flushed. */
|
||||
flush_workqueue(dlm->dlm_worker);
|
||||
|
||||
/* get an extra reference on the mle.
|
||||
* otherwise the assert_master from the new
|
||||
* master will destroy this.
|
||||
* also, make sure that all callers of dlm_get_mle
|
||||
* take both dlm->spinlock and dlm->master_lock */
|
||||
spin_lock(&dlm->spinlock);
|
||||
spin_lock(&dlm->master_lock);
|
||||
dlm_get_mle_inuse(mle);
|
||||
spin_unlock(&dlm->master_lock);
|
||||
spin_unlock(&dlm->spinlock);
|
||||
|
||||
/* notify new node and send all lock state */
|
||||
/* call send_one_lockres with migration flag.
|
||||
* this serves as notice to the target node that a
|
||||
@ -3246,6 +3241,15 @@ top:
|
||||
mle->new_master != dead_node)
|
||||
continue;
|
||||
|
||||
if (mle->new_master == dead_node && mle->inuse) {
|
||||
mlog(ML_NOTICE, "%s: target %u died during "
|
||||
"migration from %u, the MLE is "
|
||||
"still keep used, ignore it!\n",
|
||||
dlm->name, dead_node,
|
||||
mle->master);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we have reached this point, this mle needs to be
|
||||
* removed from the list and freed. */
|
||||
dlm_clean_migration_mle(dlm, mle);
|
||||
|
@ -2326,6 +2326,8 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
|
||||
break;
|
||||
}
|
||||
}
|
||||
dlm_lockres_clear_refmap_bit(dlm, res,
|
||||
dead_node);
|
||||
spin_unlock(&res->spinlock);
|
||||
continue;
|
||||
}
|
||||
|
@ -162,14 +162,8 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
|
||||
inode->i_fop = &sysv_dir_operations;
|
||||
inode->i_mapping->a_ops = &sysv_aops;
|
||||
} else if (S_ISLNK(inode->i_mode)) {
|
||||
if (inode->i_blocks) {
|
||||
inode->i_op = &sysv_symlink_inode_operations;
|
||||
inode->i_mapping->a_ops = &sysv_aops;
|
||||
} else {
|
||||
inode->i_op = &sysv_fast_symlink_inode_operations;
|
||||
nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size,
|
||||
sizeof(SYSV_I(inode)->i_data) - 1);
|
||||
}
|
||||
inode->i_op = &sysv_symlink_inode_operations;
|
||||
inode->i_mapping->a_ops = &sysv_aops;
|
||||
} else
|
||||
init_special_inode(inode, inode->i_mode, rdev);
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ struct alg_sock {
|
||||
|
||||
struct sock *parent;
|
||||
|
||||
unsigned int refcnt;
|
||||
|
||||
const struct af_alg_type *type;
|
||||
void *private;
|
||||
};
|
||||
@ -64,6 +66,7 @@ int af_alg_register_type(const struct af_alg_type *type);
|
||||
int af_alg_unregister_type(const struct af_alg_type *type);
|
||||
|
||||
int af_alg_release(struct socket *sock);
|
||||
void af_alg_release_parent(struct sock *sk);
|
||||
int af_alg_accept(struct sock *sk, struct socket *newsock);
|
||||
|
||||
int af_alg_make_sg(struct af_alg_sgl *sgl, void __user *addr, int len,
|
||||
@ -80,11 +83,6 @@ static inline struct alg_sock *alg_sk(struct sock *sk)
|
||||
return (struct alg_sock *)sk;
|
||||
}
|
||||
|
||||
static inline void af_alg_release_parent(struct sock *sk)
|
||||
{
|
||||
sock_put(alg_sk(sk)->parent);
|
||||
}
|
||||
|
||||
static inline void af_alg_init_completion(struct af_alg_completion *completion)
|
||||
{
|
||||
init_completion(&completion->completion);
|
||||
|
@ -247,7 +247,6 @@ extern int sigprocmask(int, sigset_t *, sigset_t *);
|
||||
extern void set_current_blocked(sigset_t *);
|
||||
extern void __set_current_blocked(const sigset_t *);
|
||||
extern int show_unhandled_signals;
|
||||
extern int sigsuspend(sigset_t *);
|
||||
|
||||
struct sigaction {
|
||||
#ifndef __ARCH_HAS_IRIX_SIGACTION
|
||||
|
@ -3551,7 +3551,7 @@ SYSCALL_DEFINE0(pause)
|
||||
|
||||
#endif
|
||||
|
||||
int sigsuspend(sigset_t *set)
|
||||
static int sigsuspend(sigset_t *set)
|
||||
{
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(set);
|
||||
|
@ -377,7 +377,7 @@ static void nop_mcount(Elf_Shdr const *const relhdr,
|
||||
|
||||
if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
|
||||
if (make_nop)
|
||||
ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
|
||||
ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
|
||||
if (warn_on_notrace_sect && !once) {
|
||||
printf("Section %s has mcount callers being ignored\n",
|
||||
txtname);
|
||||
|
@ -44,6 +44,13 @@
|
||||
#include <sound/compress_offload.h>
|
||||
#include <sound/compress_driver.h>
|
||||
|
||||
/* struct snd_compr_codec_caps overflows the ioctl bit size for some
|
||||
* architectures, so we need to disable the relevant ioctls.
|
||||
*/
|
||||
#if _IOC_SIZEBITS < 14
|
||||
#define COMPR_CODEC_CAPS_OVERFLOW
|
||||
#endif
|
||||
|
||||
/* TODO:
|
||||
* - add substream support for multiple devices in case of
|
||||
* SND_DYNAMIC_MINORS is not used
|
||||
@ -443,6 +450,7 @@ out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
#ifndef COMPR_CODEC_CAPS_OVERFLOW
|
||||
static int
|
||||
snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
|
||||
{
|
||||
@ -466,6 +474,7 @@ out:
|
||||
kfree(caps);
|
||||
return retval;
|
||||
}
|
||||
#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
|
||||
|
||||
/* revisit this with snd_pcm_preallocate_xxx */
|
||||
static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
|
||||
@ -844,6 +853,11 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
|
||||
|
||||
mutex_lock(&stream->device->lock);
|
||||
switch (_IOC_NR(cmd)) {
|
||||
#ifndef COMPR_CODEC_CAPS_OVERFLOW
|
||||
case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
|
||||
retval = snd_compr_get_codec_caps(stream, arg);
|
||||
break;
|
||||
#endif
|
||||
case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
|
||||
retval = snd_compr_set_params(stream, arg);
|
||||
break;
|
||||
|
@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_substream *substream,
|
||||
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
|
||||
}
|
||||
|
||||
static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
|
||||
static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
|
||||
bool trylock)
|
||||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct snd_pcm_hw_params *params, *sparams;
|
||||
@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
|
||||
struct snd_mask sformat_mask;
|
||||
struct snd_mask mask;
|
||||
|
||||
if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
||||
if (trylock) {
|
||||
if (!(mutex_trylock(&runtime->oss.params_lock)))
|
||||
return -EAGAIN;
|
||||
} else if (mutex_lock_interruptible(&runtime->oss.params_lock))
|
||||
return -EINTR;
|
||||
sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
|
||||
params = kmalloc(sizeof(*params), GFP_KERNEL);
|
||||
@ -1091,7 +1095,7 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil
|
||||
if (asubstream == NULL)
|
||||
asubstream = substream;
|
||||
if (substream->runtime->oss.params) {
|
||||
err = snd_pcm_oss_change_params(substream);
|
||||
err = snd_pcm_oss_change_params(substream, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -1130,7 +1134,7 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
|
||||
return 0;
|
||||
runtime = substream->runtime;
|
||||
if (runtime->oss.params) {
|
||||
err = snd_pcm_oss_change_params(substream);
|
||||
err = snd_pcm_oss_change_params(substream, false);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
@ -2168,7 +2172,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
|
||||
runtime = substream->runtime;
|
||||
|
||||
if (runtime->oss.params &&
|
||||
(err = snd_pcm_oss_change_params(substream)) < 0)
|
||||
(err = snd_pcm_oss_change_params(substream, false)) < 0)
|
||||
return err;
|
||||
|
||||
info.fragsize = runtime->oss.period_bytes;
|
||||
@ -2804,7 +2808,12 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
|
||||
return -EIO;
|
||||
|
||||
if (runtime->oss.params) {
|
||||
if ((err = snd_pcm_oss_change_params(substream)) < 0)
|
||||
/* use mutex_trylock() for params_lock for avoiding a deadlock
|
||||
* between mmap_sem and params_lock taken by
|
||||
* copy_from/to_user() in snd_pcm_oss_write/read()
|
||||
*/
|
||||
err = snd_pcm_oss_change_params(substream, true);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
|
||||
|
@ -956,18 +956,26 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
|
||||
unsigned long flags;
|
||||
long result = 0, count1;
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
unsigned long appl_ptr;
|
||||
|
||||
if (userbuf)
|
||||
mutex_lock(&runtime->realloc_mutex);
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
while (count > 0 && runtime->avail) {
|
||||
count1 = runtime->buffer_size - runtime->appl_ptr;
|
||||
if (count1 > count)
|
||||
count1 = count;
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
if (count1 > (int)runtime->avail)
|
||||
count1 = runtime->avail;
|
||||
|
||||
/* update runtime->appl_ptr before unlocking for userbuf */
|
||||
appl_ptr = runtime->appl_ptr;
|
||||
runtime->appl_ptr += count1;
|
||||
runtime->appl_ptr %= runtime->buffer_size;
|
||||
runtime->avail -= count1;
|
||||
|
||||
if (kernelbuf)
|
||||
memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
|
||||
memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
|
||||
if (userbuf) {
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
if (copy_to_user(userbuf + result,
|
||||
@ -977,13 +985,10 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
|
||||
}
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
}
|
||||
runtime->appl_ptr += count1;
|
||||
runtime->appl_ptr %= runtime->buffer_size;
|
||||
runtime->avail -= count1;
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
result += count1;
|
||||
count -= count1;
|
||||
}
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
if (userbuf)
|
||||
mutex_unlock(&runtime->realloc_mutex);
|
||||
return result;
|
||||
@ -1188,8 +1193,9 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
||||
unsigned long flags;
|
||||
long count1, result;
|
||||
struct snd_rawmidi_runtime *runtime = substream->runtime;
|
||||
unsigned long appl_ptr;
|
||||
|
||||
if (snd_BUG_ON(!kernelbuf && !userbuf))
|
||||
if (!kernelbuf && !userbuf)
|
||||
return -EINVAL;
|
||||
if (snd_BUG_ON(!runtime->buffer))
|
||||
return -EINVAL;
|
||||
@ -1212,12 +1218,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
||||
count1 = count;
|
||||
if (count1 > (long)runtime->avail)
|
||||
count1 = runtime->avail;
|
||||
|
||||
/* update runtime->appl_ptr before unlocking for userbuf */
|
||||
appl_ptr = runtime->appl_ptr;
|
||||
runtime->appl_ptr += count1;
|
||||
runtime->appl_ptr %= runtime->buffer_size;
|
||||
runtime->avail -= count1;
|
||||
|
||||
if (kernelbuf)
|
||||
memcpy(runtime->buffer + runtime->appl_ptr,
|
||||
memcpy(runtime->buffer + appl_ptr,
|
||||
kernelbuf + result, count1);
|
||||
else if (userbuf) {
|
||||
spin_unlock_irqrestore(&runtime->lock, flags);
|
||||
if (copy_from_user(runtime->buffer + runtime->appl_ptr,
|
||||
if (copy_from_user(runtime->buffer + appl_ptr,
|
||||
userbuf + result, count1)) {
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
result = result > 0 ? result : -EFAULT;
|
||||
@ -1225,9 +1238,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
|
||||
}
|
||||
spin_lock_irqsave(&runtime->lock, flags);
|
||||
}
|
||||
runtime->appl_ptr += count1;
|
||||
runtime->appl_ptr %= runtime->buffer_size;
|
||||
runtime->avail -= count1;
|
||||
result += count1;
|
||||
count -= count1;
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
|
||||
struct seq_oss_synth *rec;
|
||||
struct seq_oss_synthinfo *info;
|
||||
|
||||
if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
|
||||
if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
|
||||
return;
|
||||
for (i = 0; i < dp->max_synthdev; i++) {
|
||||
info = &dp->synths[i];
|
||||
|
@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
|
||||
else
|
||||
down_read(&grp->list_mutex);
|
||||
list_for_each_entry(subs, &grp->list_head, src_list) {
|
||||
/* both ports ready? */
|
||||
if (atomic_read(&subs->ref_count) != 2)
|
||||
continue;
|
||||
event->dest = subs->info.dest;
|
||||
if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
|
||||
/* convert time according to flag with subscription */
|
||||
|
@ -175,10 +175,6 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
|
||||
}
|
||||
|
||||
/* */
|
||||
enum group_type {
|
||||
SRC_LIST, DEST_LIST
|
||||
};
|
||||
|
||||
static int subscribe_port(struct snd_seq_client *client,
|
||||
struct snd_seq_client_port *port,
|
||||
struct snd_seq_port_subs_info *grp,
|
||||
@ -205,6 +201,20 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
||||
struct snd_seq_client_port *port,
|
||||
struct snd_seq_subscribers *subs,
|
||||
bool is_src, bool ack);
|
||||
|
||||
static inline struct snd_seq_subscribers *
|
||||
get_subscriber(struct list_head *p, bool is_src)
|
||||
{
|
||||
if (is_src)
|
||||
return list_entry(p, struct snd_seq_subscribers, src_list);
|
||||
else
|
||||
return list_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* remove all subscribers on the list
|
||||
* this is called from port_delete, for each src and dest list.
|
||||
@ -212,7 +222,7 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
|
||||
static void clear_subscriber_list(struct snd_seq_client *client,
|
||||
struct snd_seq_client_port *port,
|
||||
struct snd_seq_port_subs_info *grp,
|
||||
int grptype)
|
||||
int is_src)
|
||||
{
|
||||
struct list_head *p, *n;
|
||||
|
||||
@ -221,15 +231,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
||||
struct snd_seq_client *c;
|
||||
struct snd_seq_client_port *aport;
|
||||
|
||||
if (grptype == SRC_LIST) {
|
||||
subs = list_entry(p, struct snd_seq_subscribers, src_list);
|
||||
subs = get_subscriber(p, is_src);
|
||||
if (is_src)
|
||||
aport = get_client_port(&subs->info.dest, &c);
|
||||
} else {
|
||||
subs = list_entry(p, struct snd_seq_subscribers, dest_list);
|
||||
else
|
||||
aport = get_client_port(&subs->info.sender, &c);
|
||||
}
|
||||
list_del(p);
|
||||
unsubscribe_port(client, port, grp, &subs->info, 0);
|
||||
delete_and_unsubscribe_port(client, port, subs, is_src, false);
|
||||
|
||||
if (!aport) {
|
||||
/* looks like the connected port is being deleted.
|
||||
* we decrease the counter, and when both ports are deleted
|
||||
@ -237,21 +245,14 @@ static void clear_subscriber_list(struct snd_seq_client *client,
|
||||
*/
|
||||
if (atomic_dec_and_test(&subs->ref_count))
|
||||
kfree(subs);
|
||||
} else {
|
||||
/* ok we got the connected port */
|
||||
struct snd_seq_port_subs_info *agrp;
|
||||
agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
|
||||
down_write(&agrp->list_mutex);
|
||||
if (grptype == SRC_LIST)
|
||||
list_del(&subs->dest_list);
|
||||
else
|
||||
list_del(&subs->src_list);
|
||||
up_write(&agrp->list_mutex);
|
||||
unsubscribe_port(c, aport, agrp, &subs->info, 1);
|
||||
kfree(subs);
|
||||
snd_seq_port_unlock(aport);
|
||||
snd_seq_client_unlock(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ok we got the connected port */
|
||||
delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
|
||||
kfree(subs);
|
||||
snd_seq_port_unlock(aport);
|
||||
snd_seq_client_unlock(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,8 +265,8 @@ static int port_delete(struct snd_seq_client *client,
|
||||
snd_use_lock_sync(&port->use_lock);
|
||||
|
||||
/* clear subscribers info */
|
||||
clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
|
||||
clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
|
||||
clear_subscriber_list(client, port, &port->c_src, true);
|
||||
clear_subscriber_list(client, port, &port->c_dest, false);
|
||||
|
||||
if (port->private_free)
|
||||
port->private_free(port->private_data);
|
||||
@ -484,6 +485,75 @@ static int match_subs_info(struct snd_seq_port_subscribe *r,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_and_subscribe_port(struct snd_seq_client *client,
|
||||
struct snd_seq_client_port *port,
|
||||
struct snd_seq_subscribers *subs,
|
||||
bool is_src, bool exclusive, bool ack)
|
||||
{
|
||||
struct snd_seq_port_subs_info *grp;
|
||||
struct list_head *p;
|
||||
struct snd_seq_subscribers *s;
|
||||
int err;
|
||||
|
||||
grp = is_src ? &port->c_src : &port->c_dest;
|
||||
err = -EBUSY;
|
||||
down_write(&grp->list_mutex);
|
||||
if (exclusive) {
|
||||
if (!list_empty(&grp->list_head))
|
||||
goto __error;
|
||||
} else {
|
||||
if (grp->exclusive)
|
||||
goto __error;
|
||||
/* check whether already exists */
|
||||
list_for_each(p, &grp->list_head) {
|
||||
s = get_subscriber(p, is_src);
|
||||
if (match_subs_info(&subs->info, &s->info))
|
||||
goto __error;
|
||||
}
|
||||
}
|
||||
|
||||
err = subscribe_port(client, port, grp, &subs->info, ack);
|
||||
if (err < 0) {
|
||||
grp->exclusive = 0;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
/* add to list */
|
||||
write_lock_irq(&grp->list_lock);
|
||||
if (is_src)
|
||||
list_add_tail(&subs->src_list, &grp->list_head);
|
||||
else
|
||||
list_add_tail(&subs->dest_list, &grp->list_head);
|
||||
grp->exclusive = exclusive;
|
||||
atomic_inc(&subs->ref_count);
|
||||
write_unlock_irq(&grp->list_lock);
|
||||
err = 0;
|
||||
|
||||
__error:
|
||||
up_write(&grp->list_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
||||
struct snd_seq_client_port *port,
|
||||
struct snd_seq_subscribers *subs,
|
||||
bool is_src, bool ack)
|
||||
{
|
||||
struct snd_seq_port_subs_info *grp;
|
||||
|
||||
grp = is_src ? &port->c_src : &port->c_dest;
|
||||
down_write(&grp->list_mutex);
|
||||
write_lock_irq(&grp->list_lock);
|
||||
if (is_src)
|
||||
list_del(&subs->src_list);
|
||||
else
|
||||
list_del(&subs->dest_list);
|
||||
grp->exclusive = 0;
|
||||
write_unlock_irq(&grp->list_lock);
|
||||
up_write(&grp->list_mutex);
|
||||
|
||||
unsubscribe_port(client, port, grp, &subs->info, ack);
|
||||
}
|
||||
|
||||
/* connect two ports */
|
||||
int snd_seq_port_connect(struct snd_seq_client *connector,
|
||||
@ -493,76 +563,42 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
|
||||
struct snd_seq_client_port *dest_port,
|
||||
struct snd_seq_port_subscribe *info)
|
||||
{
|
||||
struct snd_seq_port_subs_info *src = &src_port->c_src;
|
||||
struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
|
||||
struct snd_seq_subscribers *subs, *s;
|
||||
int err, src_called = 0;
|
||||
unsigned long flags;
|
||||
int exclusive;
|
||||
struct snd_seq_subscribers *subs;
|
||||
bool exclusive;
|
||||
int err;
|
||||
|
||||
subs = kzalloc(sizeof(*subs), GFP_KERNEL);
|
||||
if (! subs)
|
||||
if (!subs)
|
||||
return -ENOMEM;
|
||||
|
||||
subs->info = *info;
|
||||
atomic_set(&subs->ref_count, 2);
|
||||
atomic_set(&subs->ref_count, 0);
|
||||
INIT_LIST_HEAD(&subs->src_list);
|
||||
INIT_LIST_HEAD(&subs->dest_list);
|
||||
|
||||
down_write(&src->list_mutex);
|
||||
down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
|
||||
exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
|
||||
|
||||
exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
|
||||
err = -EBUSY;
|
||||
if (exclusive) {
|
||||
if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
|
||||
goto __error;
|
||||
} else {
|
||||
if (src->exclusive || dest->exclusive)
|
||||
goto __error;
|
||||
/* check whether already exists */
|
||||
list_for_each_entry(s, &src->list_head, src_list) {
|
||||
if (match_subs_info(info, &s->info))
|
||||
goto __error;
|
||||
}
|
||||
list_for_each_entry(s, &dest->list_head, dest_list) {
|
||||
if (match_subs_info(info, &s->info))
|
||||
goto __error;
|
||||
}
|
||||
}
|
||||
err = check_and_subscribe_port(src_client, src_port, subs, true,
|
||||
exclusive,
|
||||
connector->number != src_client->number);
|
||||
if (err < 0)
|
||||
goto error;
|
||||
err = check_and_subscribe_port(dest_client, dest_port, subs, false,
|
||||
exclusive,
|
||||
connector->number != dest_client->number);
|
||||
if (err < 0)
|
||||
goto error_dest;
|
||||
|
||||
if ((err = subscribe_port(src_client, src_port, src, info,
|
||||
connector->number != src_client->number)) < 0)
|
||||
goto __error;
|
||||
src_called = 1;
|
||||
|
||||
if ((err = subscribe_port(dest_client, dest_port, dest, info,
|
||||
connector->number != dest_client->number)) < 0)
|
||||
goto __error;
|
||||
|
||||
/* add to list */
|
||||
write_lock_irqsave(&src->list_lock, flags);
|
||||
// write_lock(&dest->list_lock); // no other lock yet
|
||||
list_add_tail(&subs->src_list, &src->list_head);
|
||||
list_add_tail(&subs->dest_list, &dest->list_head);
|
||||
// write_unlock(&dest->list_lock); // no other lock yet
|
||||
write_unlock_irqrestore(&src->list_lock, flags);
|
||||
|
||||
src->exclusive = dest->exclusive = exclusive;
|
||||
|
||||
up_write(&dest->list_mutex);
|
||||
up_write(&src->list_mutex);
|
||||
return 0;
|
||||
|
||||
__error:
|
||||
if (src_called)
|
||||
unsubscribe_port(src_client, src_port, src, info,
|
||||
connector->number != src_client->number);
|
||||
error_dest:
|
||||
delete_and_unsubscribe_port(src_client, src_port, subs, true,
|
||||
connector->number != src_client->number);
|
||||
error:
|
||||
kfree(subs);
|
||||
up_write(&dest->list_mutex);
|
||||
up_write(&src->list_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* remove the connection */
|
||||
int snd_seq_port_disconnect(struct snd_seq_client *connector,
|
||||
struct snd_seq_client *src_client,
|
||||
@ -572,37 +608,28 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
|
||||
struct snd_seq_port_subscribe *info)
|
||||
{
|
||||
struct snd_seq_port_subs_info *src = &src_port->c_src;
|
||||
struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
|
||||
struct snd_seq_subscribers *subs;
|
||||
int err = -ENOENT;
|
||||
unsigned long flags;
|
||||
|
||||
down_write(&src->list_mutex);
|
||||
down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
|
||||
|
||||
/* look for the connection */
|
||||
list_for_each_entry(subs, &src->list_head, src_list) {
|
||||
if (match_subs_info(info, &subs->info)) {
|
||||
write_lock_irqsave(&src->list_lock, flags);
|
||||
// write_lock(&dest->list_lock); // no lock yet
|
||||
list_del(&subs->src_list);
|
||||
list_del(&subs->dest_list);
|
||||
// write_unlock(&dest->list_lock);
|
||||
write_unlock_irqrestore(&src->list_lock, flags);
|
||||
src->exclusive = dest->exclusive = 0;
|
||||
unsubscribe_port(src_client, src_port, src, info,
|
||||
connector->number != src_client->number);
|
||||
unsubscribe_port(dest_client, dest_port, dest, info,
|
||||
connector->number != dest_client->number);
|
||||
kfree(subs);
|
||||
atomic_dec(&subs->ref_count); /* mark as not ready */
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
up_write(&dest->list_mutex);
|
||||
up_write(&src->list_mutex);
|
||||
return err;
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
delete_and_unsubscribe_port(src_client, src_port, subs, true,
|
||||
connector->number != src_client->number);
|
||||
delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
|
||||
connector->number != dest_client->number);
|
||||
kfree(subs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr)
|
||||
|
||||
void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
/* setup defaults */
|
||||
tmr->ppq = 96; /* 96 PPQ */
|
||||
tmr->tempo = 500000; /* 120 BPM */
|
||||
@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
|
||||
tmr->preferred_resolution = seq_default_timer_resolution;
|
||||
|
||||
tmr->skew = tmr->skew_base = SKEW_BASE;
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
}
|
||||
|
||||
void snd_seq_timer_reset(struct snd_seq_timer * tmr)
|
||||
static void seq_timer_reset(struct snd_seq_timer *tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
|
||||
/* reset time & songposition */
|
||||
tmr->cur_time.tv_sec = 0;
|
||||
tmr->cur_time.tv_nsec = 0;
|
||||
|
||||
tmr->tick.cur_tick = 0;
|
||||
tmr->tick.fraction = 0;
|
||||
}
|
||||
|
||||
void snd_seq_timer_reset(struct snd_seq_timer *tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
seq_timer_reset(tmr);
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
}
|
||||
|
||||
@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
|
||||
tmr = q->timer;
|
||||
if (tmr == NULL)
|
||||
return;
|
||||
if (!tmr->running)
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
if (!tmr->running) {
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
resolution *= ticks;
|
||||
if (tmr->skew != tmr->skew_base) {
|
||||
@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
|
||||
(((resolution & 0xffff) * tmr->skew) >> 16);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
|
||||
/* update timer */
|
||||
snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
|
||||
|
||||
@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
|
||||
t->callback = snd_seq_timer_interrupt;
|
||||
t->callback_data = q;
|
||||
t->flags |= SNDRV_TIMER_IFLG_AUTO;
|
||||
spin_lock_irq(&tmr->lock);
|
||||
tmr->timeri = t;
|
||||
spin_unlock_irq(&tmr->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_close(struct snd_seq_queue *q)
|
||||
{
|
||||
struct snd_seq_timer *tmr;
|
||||
struct snd_timer_instance *t;
|
||||
|
||||
tmr = q->timer;
|
||||
if (snd_BUG_ON(!tmr))
|
||||
return -EINVAL;
|
||||
if (tmr->timeri) {
|
||||
snd_timer_stop(tmr->timeri);
|
||||
snd_timer_close(tmr->timeri);
|
||||
tmr->timeri = NULL;
|
||||
}
|
||||
spin_lock_irq(&tmr->lock);
|
||||
t = tmr->timeri;
|
||||
tmr->timeri = NULL;
|
||||
spin_unlock_irq(&tmr->lock);
|
||||
if (t)
|
||||
snd_timer_close(t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_stop(struct snd_seq_timer * tmr)
|
||||
static int seq_timer_stop(struct snd_seq_timer *tmr)
|
||||
{
|
||||
if (! tmr->timeri)
|
||||
return -EINVAL;
|
||||
@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_timer * tmr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_stop(struct snd_seq_timer *tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
err = seq_timer_stop(tmr);
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int initialize_timer(struct snd_seq_timer *tmr)
|
||||
{
|
||||
struct snd_timer *t;
|
||||
@ -360,13 +383,13 @@ static int initialize_timer(struct snd_seq_timer *tmr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_start(struct snd_seq_timer * tmr)
|
||||
static int seq_timer_start(struct snd_seq_timer *tmr)
|
||||
{
|
||||
if (! tmr->timeri)
|
||||
return -EINVAL;
|
||||
if (tmr->running)
|
||||
snd_seq_timer_stop(tmr);
|
||||
snd_seq_timer_reset(tmr);
|
||||
seq_timer_stop(tmr);
|
||||
seq_timer_reset(tmr);
|
||||
if (initialize_timer(tmr) < 0)
|
||||
return -EINVAL;
|
||||
snd_timer_start(tmr->timeri, tmr->ticks);
|
||||
@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_timer * tmr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_continue(struct snd_seq_timer * tmr)
|
||||
int snd_seq_timer_start(struct snd_seq_timer *tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
err = seq_timer_start(tmr);
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int seq_timer_continue(struct snd_seq_timer *tmr)
|
||||
{
|
||||
if (! tmr->timeri)
|
||||
return -EINVAL;
|
||||
if (tmr->running)
|
||||
return -EBUSY;
|
||||
if (! tmr->initialized) {
|
||||
snd_seq_timer_reset(tmr);
|
||||
seq_timer_reset(tmr);
|
||||
if (initialize_timer(tmr) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_seq_timer * tmr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int snd_seq_timer_continue(struct snd_seq_timer *tmr)
|
||||
{
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
err = seq_timer_continue(tmr);
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* return current 'real' time. use timeofday() to get better granularity. */
|
||||
snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
|
||||
{
|
||||
snd_seq_real_time_t cur_time;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&tmr->lock, flags);
|
||||
cur_time = tmr->cur_time;
|
||||
if (tmr->running) {
|
||||
struct timeval tm;
|
||||
@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
|
||||
}
|
||||
snd_seq_sanity_real_time(&cur_time);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&tmr->lock, flags);
|
||||
return cur_time;
|
||||
}
|
||||
|
||||
|
@ -254,9 +254,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
|
||||
*/
|
||||
static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
|
||||
{
|
||||
struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
|
||||
struct snd_virmidi *vmidi = substream->runtime->private_data;
|
||||
snd_midi_event_free(vmidi->parser);
|
||||
|
||||
write_lock_irq(&rdev->filelist_lock);
|
||||
list_del(&vmidi->list);
|
||||
write_unlock_irq(&rdev->filelist_lock);
|
||||
snd_midi_event_free(vmidi->parser);
|
||||
substream->runtime->private_data = NULL;
|
||||
kfree(vmidi);
|
||||
return 0;
|
||||
|
@ -300,8 +300,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _snd_timer_stop(struct snd_timer_instance *timeri,
|
||||
int keep_flag, int event);
|
||||
static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
|
||||
|
||||
/*
|
||||
* close a timer instance
|
||||
@ -343,7 +342,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
|
||||
spin_unlock_irq(&timer->lock);
|
||||
mutex_lock(®ister_mutex);
|
||||
list_del(&timeri->open_list);
|
||||
if (timer && list_empty(&timer->open_list_head) &&
|
||||
if (list_empty(&timer->open_list_head) &&
|
||||
timer->hw.close)
|
||||
timer->hw.close(timer);
|
||||
/* remove slave links */
|
||||
@ -415,7 +414,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
list_for_each_entry(ts, &ti->slave_active_head, active_list)
|
||||
if (ts->ccallback)
|
||||
ts->ccallback(ti, event + 100, &tstamp, resolution);
|
||||
ts->ccallback(ts, event + 100, &tstamp, resolution);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
}
|
||||
|
||||
@ -444,6 +443,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&slave_active_lock, flags);
|
||||
if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
|
||||
spin_unlock_irqrestore(&slave_active_lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
|
||||
if (timeri->master && timeri->timer) {
|
||||
spin_lock(&timeri->timer->lock);
|
||||
@ -468,23 +471,30 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
|
||||
return -EINVAL;
|
||||
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
|
||||
result = snd_timer_start_slave(timeri);
|
||||
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
|
||||
if (result >= 0)
|
||||
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
|
||||
return result;
|
||||
}
|
||||
timer = timeri->timer;
|
||||
if (timer == NULL)
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
|
||||
SNDRV_TIMER_IFLG_START)) {
|
||||
result = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
timeri->ticks = timeri->cticks = ticks;
|
||||
timeri->pticks = 0;
|
||||
result = snd_timer_start1(timer, timeri, ticks);
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
|
||||
if (result >= 0)
|
||||
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int _snd_timer_stop(struct snd_timer_instance * timeri,
|
||||
int keep_flag, int event)
|
||||
static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
|
||||
{
|
||||
struct snd_timer *timer;
|
||||
unsigned long flags;
|
||||
@ -493,19 +503,30 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
|
||||
return -ENXIO;
|
||||
|
||||
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
|
||||
if (!keep_flag) {
|
||||
spin_lock_irqsave(&slave_active_lock, flags);
|
||||
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
|
||||
list_del_init(&timeri->ack_list);
|
||||
list_del_init(&timeri->active_list);
|
||||
spin_lock_irqsave(&slave_active_lock, flags);
|
||||
if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
|
||||
spin_unlock_irqrestore(&slave_active_lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
if (timeri->timer)
|
||||
spin_lock(&timeri->timer->lock);
|
||||
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
|
||||
list_del_init(&timeri->ack_list);
|
||||
list_del_init(&timeri->active_list);
|
||||
if (timeri->timer)
|
||||
spin_unlock(&timeri->timer->lock);
|
||||
spin_unlock_irqrestore(&slave_active_lock, flags);
|
||||
goto __end;
|
||||
}
|
||||
timer = timeri->timer;
|
||||
if (!timer)
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
|
||||
SNDRV_TIMER_IFLG_START))) {
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
list_del_init(&timeri->ack_list);
|
||||
list_del_init(&timeri->active_list);
|
||||
if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
|
||||
@ -520,9 +541,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!keep_flag)
|
||||
timeri->flags &=
|
||||
~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
|
||||
timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
__end:
|
||||
if (event != SNDRV_TIMER_EVENT_RESOLUTION)
|
||||
@ -541,7 +560,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
|
||||
err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
|
||||
if (err < 0)
|
||||
return err;
|
||||
timer = timeri->timer;
|
||||
@ -571,10 +590,15 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
|
||||
if (! timer)
|
||||
return -EINVAL;
|
||||
spin_lock_irqsave(&timer->lock, flags);
|
||||
if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
|
||||
result = -EBUSY;
|
||||
goto unlock;
|
||||
}
|
||||
if (!timeri->cticks)
|
||||
timeri->cticks = 1;
|
||||
timeri->pticks = 0;
|
||||
result = snd_timer_start1(timer, timeri, timer->sticks);
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&timer->lock, flags);
|
||||
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
|
||||
return result;
|
||||
@ -585,7 +609,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
|
||||
*/
|
||||
int snd_timer_pause(struct snd_timer_instance * timeri)
|
||||
{
|
||||
return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
|
||||
return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -702,8 +726,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
|
||||
ti->cticks = ti->ticks;
|
||||
} else {
|
||||
ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
|
||||
if (--timer->running)
|
||||
list_del_init(&ti->active_list);
|
||||
--timer->running;
|
||||
list_del_init(&ti->active_list);
|
||||
}
|
||||
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
|
||||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
|
||||
|
@ -109,6 +109,9 @@ struct dummy_timer_ops {
|
||||
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
|
||||
};
|
||||
|
||||
#define get_dummy_ops(substream) \
|
||||
(*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
|
||||
|
||||
struct dummy_model {
|
||||
const char *name;
|
||||
int (*playback_constraints)(struct snd_pcm_runtime *runtime);
|
||||
@ -137,7 +140,6 @@ struct snd_dummy {
|
||||
int iobox;
|
||||
struct snd_kcontrol *cd_volume_ctl;
|
||||
struct snd_kcontrol *cd_switch_ctl;
|
||||
const struct dummy_timer_ops *timer_ops;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -231,6 +233,8 @@ struct dummy_model *dummy_models[] = {
|
||||
*/
|
||||
|
||||
struct dummy_systimer_pcm {
|
||||
/* ops must be the first item */
|
||||
const struct dummy_timer_ops *timer_ops;
|
||||
spinlock_t lock;
|
||||
struct timer_list timer;
|
||||
unsigned long base_time;
|
||||
@ -368,6 +372,8 @@ static struct dummy_timer_ops dummy_systimer_ops = {
|
||||
*/
|
||||
|
||||
struct dummy_hrtimer_pcm {
|
||||
/* ops must be the first item */
|
||||
const struct dummy_timer_ops *timer_ops;
|
||||
ktime_t base_time;
|
||||
ktime_t period_time;
|
||||
atomic_t running;
|
||||
@ -494,31 +500,25 @@ static struct dummy_timer_ops dummy_hrtimer_ops = {
|
||||
|
||||
static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
|
||||
{
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
|
||||
switch (cmd) {
|
||||
case SNDRV_PCM_TRIGGER_START:
|
||||
case SNDRV_PCM_TRIGGER_RESUME:
|
||||
return dummy->timer_ops->start(substream);
|
||||
return get_dummy_ops(substream)->start(substream);
|
||||
case SNDRV_PCM_TRIGGER_STOP:
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
return dummy->timer_ops->stop(substream);
|
||||
return get_dummy_ops(substream)->stop(substream);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
|
||||
return dummy->timer_ops->prepare(substream);
|
||||
return get_dummy_ops(substream)->prepare(substream);
|
||||
}
|
||||
|
||||
static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
|
||||
return dummy->timer_ops->pointer(substream);
|
||||
return get_dummy_ops(substream)->pointer(substream);
|
||||
}
|
||||
|
||||
static struct snd_pcm_hardware dummy_pcm_hardware = {
|
||||
@ -564,17 +564,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
struct dummy_model *model = dummy->model;
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
const struct dummy_timer_ops *ops;
|
||||
int err;
|
||||
|
||||
dummy->timer_ops = &dummy_systimer_ops;
|
||||
ops = &dummy_systimer_ops;
|
||||
#ifdef CONFIG_HIGH_RES_TIMERS
|
||||
if (hrtimer)
|
||||
dummy->timer_ops = &dummy_hrtimer_ops;
|
||||
ops = &dummy_hrtimer_ops;
|
||||
#endif
|
||||
|
||||
err = dummy->timer_ops->create(substream);
|
||||
err = ops->create(substream);
|
||||
if (err < 0)
|
||||
return err;
|
||||
get_dummy_ops(substream) = ops;
|
||||
|
||||
runtime->hw = dummy->pcm_hw;
|
||||
if (substream->pcm->device & 1) {
|
||||
@ -596,7 +598,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
||||
err = model->capture_constraints(substream->runtime);
|
||||
}
|
||||
if (err < 0) {
|
||||
dummy->timer_ops->free(substream);
|
||||
get_dummy_ops(substream)->free(substream);
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
@ -604,8 +606,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
|
||||
|
||||
static int dummy_pcm_close(struct snd_pcm_substream *substream)
|
||||
{
|
||||
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
|
||||
dummy->timer_ops->free(substream);
|
||||
get_dummy_ops(substream)->free(substream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2188,6 +2188,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
|
||||
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
|
||||
SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
|
||||
|
||||
/* All Apple entries are in codec SSIDs */
|
||||
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
|
||||
|
@ -1318,7 +1318,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
|
||||
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
|
||||
continue;
|
||||
|
||||
dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
|
||||
|
@ -905,8 +905,12 @@ void snd_usb_set_interface_quirk(struct usb_device *dev)
|
||||
* "Playback Design" products need a 50ms delay after setting the
|
||||
* USB interface.
|
||||
*/
|
||||
if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba)
|
||||
switch (le16_to_cpu(dev->descriptor.idVendor)) {
|
||||
case 0x23ba: /* Playback Design */
|
||||
case 0x0644: /* TEAC Corp. */
|
||||
mdelay(50);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
|
||||
@ -921,6 +925,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
|
||||
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
|
||||
mdelay(20);
|
||||
|
||||
/*
|
||||
* "TEAC Corp." products need a 20ms delay after each
|
||||
* class compliant request
|
||||
*/
|
||||
if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) &&
|
||||
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
|
||||
mdelay(20);
|
||||
|
||||
/* Marantz/Denon devices with USB DAC functionality need a delay
|
||||
* after each class compliant request
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user