This is the 3.10.97 stable release

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWx5XJAAoJEDjbvchgkmk+03kQAJkDjox3A7B9fdLPYOv/ophX
 c91Hd3TgKeioTLJiAgMXPpITWRDnwovPJVSlc1lZltojGtWg6JWE/W1/vQ3mNaJi
 cykBUngEp7qvLE08DUNDWW0PZaulBEY9sW2mcW4KgzxDQxoC2l8YnCLEjY8m5GMf
 AIw9SxmT9Kz2FSdDbH9/CCG7uVuKrPcBOmqSOOrl6bKV19dVnF6S46VDYuH3Y8hf
 8akUAgxl7pecHUywBWOdqfMWOhNokesYVAlHL0aYIukjL1rP+0WrjoJ9mOcfC47x
 DNzkT2wvjThbcESn/vAayX4LWLgTMx+UShiaMekEYxXBDp3t2rlGU2i/7oLmrexQ
 8P5qtT+x/sOORonQgplO7kPeSez54buCw7HLfxUAJGUjNhEmiOZb3kaH8uidLOVz
 J5FfrlxHS3HXX1nYAclEcNsnwo1U6lAnjZpT78lR9hpdzrjLaNj/LwswzrgVVq+E
 GOpyrTEvklgQCH5PdLA9+Iz49L5AXvg3vJnMcS9l8yyj1642gdemM9za7iKD5rwK
 TF6WdSySgxjameBI9EBQsS/9iPg3GK7jEq+CRUOLwRwfvFpL1etfrwkX7tRGhZkp
 kL3wqntlSb4UZbylxQ/SBRa/rogwjYFCKNiti66mkY7eYJwPa07OCUBvCxh/10GN
 ahTCcFEzYgg/BJqcL/dy
 =OLxa
 -----END PGP SIGNATURE-----

Merge tag 'v3.10.97' into HEAD

This is the 3.10.97 stable release

Change-Id: I57a42ce0af10c340f15384bab609c07fc6ab4b81
This commit is contained in:
Luca Stefani 2017-04-18 17:17:20 +02:00
commit 4bead31629
55 changed files with 626 additions and 303 deletions

View File

@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 10
SUBLEVEL = 96
SUBLEVEL = 97
EXTRAVERSION =
NAME = TOSSUG Baby Fish

View File

@ -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 */

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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. */
@ -741,9 +741,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
struct v4l2_event32 {
__u32 type;
union {
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;

View File

@ -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);
}
/*********************************************/

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -4825,6 +4825,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.");
@ -4853,9 +4856,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();

View File

@ -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 */

View File

@ -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 */

View File

@ -615,6 +615,7 @@
*/
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID_USB60F 0xb020
#define RATOC_PRODUCT_ID_SCU18 0xb03a
/*
* Infineon Technologies

View File

@ -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) },

View File

@ -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) },

View File

@ -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];

View File

@ -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++;

View File

@ -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) \

View File

@ -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);
}

View File

@ -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;
}

View File

@ -1924,6 +1924,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;
}
@ -1953,6 +1954,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;
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -3552,7 +3552,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);

View File

@ -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);

View File

@ -44,7 +44,12 @@
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
#define U32_MAX ((u32)~0U)
/* 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
@ -445,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)
{
@ -468,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,

View File

@ -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

View File

@ -934,31 +934,36 @@ 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;
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,
runtime->buffer + runtime->appl_ptr, count1)) {
runtime->buffer + appl_ptr, count1)) {
return result > 0 ? result : -EFAULT;
}
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);
return result;
}
@ -1161,8 +1166,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;
@ -1181,12 +1187,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;
@ -1194,9 +1207,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;
}

View File

@ -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];

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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(&register_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))

View File

@ -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;
}

View File

@ -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),

View File

@ -1345,7 +1345,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",

View File

@ -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
*/