diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt index b8b27b0aca10..3f89cbdc60b6 100644 --- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt +++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt @@ -10,6 +10,9 @@ Required properties: - "ns16850" - "nvidia,tegra20-uart" - "ibm,qpace-nwp-serial" + - "altr,16550-FIFO32" + - "altr,16550-FIFO64" + - "altr,16550-FIFO128" - "serial" if the port type is unknown. - reg : offset and length of the register set for the device. - interrupts : should contain uart interrupt. diff --git a/Makefile b/Makefile index 513b460b49f9..20f420096dfa 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 92 +SUBLEVEL = 93 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 0a070e98625d..b04850fdeb5b 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -158,8 +158,9 @@ extern int __put_user_8(void *, unsigned long long); #define put_user(x,p) \ ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ + const typeof(*(p)) __user *__tmp_p = (p); \ register const typeof(*(p)) __r2 asm("r2") = (x); \ - register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \ register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index e51fdc72cdc0..98bb43fc7df7 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -27,9 +27,6 @@ struct virtio_blk /* The disk structure for the kernel. */ struct gendisk *disk; - /* Request tracking. */ - struct list_head reqs; - mempool_t *pool; /* Process context for config space updates */ @@ -53,7 +50,6 @@ struct virtio_blk struct virtblk_req { - struct list_head list; struct request *req; struct virtio_blk_outhdr out_hdr; struct virtio_scsi_inhdr in_hdr; @@ -97,7 +93,6 @@ static void blk_done(struct virtqueue *vq) } __blk_end_request_all(vbr->req, error); - list_del(&vbr->list); mempool_free(vbr, vblk->pool); } /* In case queue is stopped waiting for more buffers. */ @@ -182,7 +177,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, return false; } - list_add_tail(&vbr->list, &vblk->reqs); return true; } @@ -435,7 +429,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) goto out_free_index; } - INIT_LIST_HEAD(&vblk->reqs); vblk->vdev = vdev; vblk->sg_elems = sg_elems; sg_init_table(vblk->sg, vblk->sg_elems); @@ -580,27 +573,30 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) { struct virtio_blk *vblk = vdev->priv; int index = vblk->index; + int refc; /* Prevent config work handler from accessing the device. */ mutex_lock(&vblk->config_lock); vblk->config_enable = false; mutex_unlock(&vblk->config_lock); - /* Nothing should be pending. */ - BUG_ON(!list_empty(&vblk->reqs)); + del_gendisk(vblk->disk); + blk_cleanup_queue(vblk->disk->queue); /* Stop all the virtqueues. */ vdev->config->reset(vdev); flush_work(&vblk->config_work); - del_gendisk(vblk->disk); - blk_cleanup_queue(vblk->disk->queue); + refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); put_disk(vblk->disk); mempool_destroy(vblk->pool); vdev->config->del_vqs(vdev); kfree(vblk); - ida_simple_remove(&vd_index_ida, index); + + /* Only free device id if we don't have any users */ + if (refc == 1) + ida_simple_remove(&vd_index_ida, index); } #ifdef CONFIG_PM diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 681be14f3605..d02f761d84ec 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x0CF3, 0xE019) }, { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, { USB_DEVICE(0x0489, 0xE03D) }, @@ -74,16 +75,35 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3012 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x0036) }, { USB_DEVICE(0x0CF3, 0x3004) }, + { USB_DEVICE(0x0CF3, 0x3008) }, { USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0CF3, 0x817a) }, { USB_DEVICE(0x13d3, 0x3375) }, + { USB_DEVICE(0x04CA, 0x3004) }, { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x04CA, 0x3006) }, + { USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, + { USB_DEVICE(0x0CF3, 0xE005) }, + { USB_DEVICE(0x0930, 0x0219) }, + { USB_DEVICE(0x0489, 0xe057) }, + { USB_DEVICE(0x13d3, 0x3393) }, + { USB_DEVICE(0x0489, 0xe04e) }, + { USB_DEVICE(0x0489, 0xe056) }, + { USB_DEVICE(0x0489, 0xe04d) }, + { USB_DEVICE(0x04c5, 0x1330) }, + { USB_DEVICE(0x13d3, 0x3402) }, + { USB_DEVICE(0x0cf3, 0x3121) }, + { USB_DEVICE(0x0cf3, 0xe003) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, + /* Atheros AR5BBU22 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE03C) }, + { USB_DEVICE(0x0489, 0xE036) }, + { } /* Terminating entry */ }; @@ -97,12 +117,31 @@ static struct usb_device_id ath3k_blist_tbl[] = { /* Atheros AR3012 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, + + /* Atheros AR5BBU22 with sflash firmware */ + { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 56fede149c1d..3cc242535012 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -63,6 +63,9 @@ static struct usb_device_id btusb_table[] = { /* Apple-specific (Broadcom) devices */ { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* MediaTek MT76x0E */ + { USB_DEVICE(0x0e8d, 0x763f) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x0a5c, 0x21e1) }, @@ -104,11 +107,14 @@ static struct usb_device_id btusb_table[] = { { USB_DEVICE(0x0c10, 0x0000) }, /* Broadcom BCM20702A0 */ + { USB_DEVICE(0x0b05, 0x17b5) }, + { USB_DEVICE(0x0b05, 0x17cb) }, + { USB_DEVICE(0x04ca, 0x2003) }, { USB_DEVICE(0x0489, 0xe042) }, { USB_DEVICE(0x413c, 0x8197) }, /* Foxconn - Hon Hai */ - { USB_DEVICE(0x0489, 0xe033) }, + { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) }, /*Broadcom devices with vendor specific id */ { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, @@ -127,6 +133,7 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3011 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, @@ -138,16 +145,35 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3012 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, + /* Atheros AR5BBU12 with sflash firmware */ + { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 }, + /* Broadcom BCM2035 */ { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 0cd2d50f9a56..a81f4694f322 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -131,7 +131,8 @@ struct ports_device { spinlock_t ports_lock; /* To protect the vq operations for the control channel */ - spinlock_t cvq_lock; + spinlock_t c_ivq_lock; + spinlock_t c_ovq_lock; /* The current config space is stored here */ struct virtio_console_config config; @@ -460,11 +461,14 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, vq = portdev->c_ovq; sg_init_one(sg, &cpkt, sizeof(cpkt)); + + spin_lock(&portdev->c_ovq_lock); if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) { virtqueue_kick(vq); while (!virtqueue_get_buf(vq, &len)) cpu_relax(); } + spin_unlock(&portdev->c_ovq_lock); return 0; } @@ -1474,23 +1478,23 @@ static void control_work_handler(struct work_struct *work) portdev = container_of(work, struct ports_device, control_work); vq = portdev->c_ivq; - spin_lock(&portdev->cvq_lock); + spin_lock(&portdev->c_ivq_lock); while ((buf = virtqueue_get_buf(vq, &len))) { - spin_unlock(&portdev->cvq_lock); + spin_unlock(&portdev->c_ivq_lock); buf->len = len; buf->offset = 0; handle_control_message(portdev, buf); - spin_lock(&portdev->cvq_lock); + spin_lock(&portdev->c_ivq_lock); if (add_inbuf(portdev->c_ivq, buf) < 0) { dev_warn(&portdev->vdev->dev, "Error adding buffer to queue\n"); free_buf(buf); } } - spin_unlock(&portdev->cvq_lock); + spin_unlock(&portdev->c_ivq_lock); } static void out_intr(struct virtqueue *vq) @@ -1751,10 +1755,12 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) if (multiport) { unsigned int nr_added_bufs; - spin_lock_init(&portdev->cvq_lock); + spin_lock_init(&portdev->c_ivq_lock); + spin_lock_init(&portdev->c_ovq_lock); INIT_WORK(&portdev->control_work, &control_work_handler); - nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock); + nr_added_bufs = fill_queue(portdev->c_ivq, + &portdev->c_ivq_lock); if (!nr_added_bufs) { dev_err(&vdev->dev, "Error allocating buffers for control queue\n"); @@ -1895,7 +1901,7 @@ static int virtcons_restore(struct virtio_device *vdev) return ret; if (use_multiport(portdev)) - fill_queue(portdev->c_ivq, &portdev->cvq_lock); + fill_queue(portdev->c_ivq, &portdev->c_ivq_lock); list_for_each_entry(port, &portdev->ports, list) { port->in_vq = portdev->in_vqs[port->id]; diff --git a/drivers/md/md.c b/drivers/md/md.c index 8590d2c256a6..3a8ef589d8c0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7071,8 +7071,10 @@ void md_do_sync(struct mddev *mddev) /* just incase thread restarts... */ if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) return; - if (mddev->ro) /* never try to sync a read-only array */ + if (mddev->ro) {/* never try to sync a read-only array */ + set_bit(MD_RECOVERY_INTR, &mddev->recovery); return; + } if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 599240af2244..bc88cabcfd43 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -99,6 +99,15 @@ static const struct pci_device_id hpsa_pci_device_id[] = { {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355}, {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1920}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1925}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928}, + {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x334d}, {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, {0,} @@ -118,13 +127,22 @@ static struct board_type products[] = { {0x3249103C, "Smart Array P812", &SA5_access}, {0x324a103C, "Smart Array P712m", &SA5_access}, {0x324b103C, "Smart Array P711m", &SA5_access}, - {0x3350103C, "Smart Array", &SA5_access}, - {0x3351103C, "Smart Array", &SA5_access}, - {0x3352103C, "Smart Array", &SA5_access}, - {0x3353103C, "Smart Array", &SA5_access}, - {0x3354103C, "Smart Array", &SA5_access}, - {0x3355103C, "Smart Array", &SA5_access}, - {0x3356103C, "Smart Array", &SA5_access}, + {0x3350103C, "Smart Array P222", &SA5_access}, + {0x3351103C, "Smart Array P420", &SA5_access}, + {0x3352103C, "Smart Array P421", &SA5_access}, + {0x3353103C, "Smart Array P822", &SA5_access}, + {0x3354103C, "Smart Array P420i", &SA5_access}, + {0x3355103C, "Smart Array P220i", &SA5_access}, + {0x3356103C, "Smart Array P721m", &SA5_access}, + {0x1920103C, "Smart Array", &SA5_access}, + {0x1921103C, "Smart Array", &SA5_access}, + {0x1922103C, "Smart Array", &SA5_access}, + {0x1923103C, "Smart Array", &SA5_access}, + {0x1924103C, "Smart Array", &SA5_access}, + {0x1925103C, "Smart Array", &SA5_access}, + {0x1926103C, "Smart Array", &SA5_access}, + {0x1928103C, "Smart Array", &SA5_access}, + {0x334d103C, "Smart Array P822se", &SA5_access}, {0xFFFF103C, "Unknown Smart Array", &SA5_access}, }; diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c index 2a81e1793e5d..b53becf3fe75 100644 --- a/drivers/scsi/isci/task.c +++ b/drivers/scsi/isci/task.c @@ -956,6 +956,7 @@ int isci_task_abort_task(struct sas_task *task) int ret = TMF_RESP_FUNC_FAILED; unsigned long flags; int perform_termination = 0; + int target_done_already = 0; /* Get the isci_request reference from the task. Note that * this check does not depend on the pending request list @@ -970,9 +971,11 @@ int isci_task_abort_task(struct sas_task *task) /* If task is already done, the request isn't valid */ if (!(task->task_state_flags & SAS_TASK_STATE_DONE) && (task->task_state_flags & SAS_TASK_AT_INITIATOR) && - old_request) + old_request) { isci_device = isci_lookup_device(task->dev); - + target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET, + &old_request->flags); + } spin_unlock(&task->task_state_lock); spin_unlock_irqrestore(&isci_host->scic_lock, flags); @@ -1031,7 +1034,7 @@ int isci_task_abort_task(struct sas_task *task) } if (task->task_proto == SAS_PROTOCOL_SMP || sas_protocol_ata(task->task_proto) || - test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) { + target_done_already) { spin_unlock_irqrestore(&isci_host->scic_lock, flags); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index db793621c403..f98cae7730b0 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -80,10 +80,6 @@ static int msix_disable = -1; module_param(msix_disable, int, 0); MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); -static int missing_delay[2] = {-1, -1}; -module_param_array(missing_delay, int, NULL, 0); -MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); - static int mpt2sas_fwfault_debug; MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault " "and halt firmware - (default=0)"); @@ -2168,7 +2164,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) } /** - * _base_update_missing_delay - change the missing delay timers + * mpt2sas_base_update_missing_delay - change the missing delay timers * @ioc: per adapter object * @device_missing_delay: amount of time till device is reported missing * @io_missing_delay: interval IO is returned when there is a missing device @@ -2179,8 +2175,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc) * delay, as well as the io missing delay. This should be called at driver * load time. */ -static void -_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, +void +mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, u16 device_missing_delay, u8 io_missing_delay) { u16 dmd, dmd_new, dmd_orignal; @@ -4371,9 +4367,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) if (r) goto out_free_resources; - if (missing_delay[0] != -1 && missing_delay[1] != -1) - _base_update_missing_delay(ioc, missing_delay[0], - missing_delay[1]); return 0; diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index c7459fdc06cc..04968bec5dc7 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -1047,6 +1047,9 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc); +void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc, + u16 device_missing_delay, u8 io_missing_delay); + int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc); /* scsih shared API */ diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 9b2fb60d49c4..a16bc6110905 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -101,6 +101,10 @@ static ushort max_sectors = 0xFFFF; module_param(max_sectors, ushort, 0); MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767"); +static int missing_delay[2] = {-1, -1}; +module_param_array(missing_delay, int, NULL, 0); +MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); + /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ #define MPT2SAS_MAX_LUN (16895) static int max_lun = MPT2SAS_MAX_LUN; @@ -7039,11 +7043,14 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) struct _sas_device *sas_device; struct _sas_node *expander_device; static struct _raid_device *raid_device; + u8 retry_count; printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name); _scsih_sas_host_refresh(ioc); + printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n", + ioc->name); /* expanders */ handle = 0xFFFF; while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, @@ -7052,19 +7059,39 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) MPI2_IOCSTATUS_MASK; if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) break; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: " + "ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } handle = le16_to_cpu(expander_pg0.DevHandle); expander_device = mpt2sas_scsih_expander_find_by_sas_address( ioc, le64_to_cpu(expander_pg0.SASAddress)); if (expander_device) _scsih_refresh_expander_links(ioc, expander_device, handle); - else + else { + printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: " + "handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(expander_pg0.SASAddress)); _scsih_expander_add(ioc, handle); + printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: " + "handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(expander_pg0.SASAddress)); + } } + printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n", + ioc->name); + if (!ioc->ir_firmware) goto skip_to_sas; + printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name); /* phys disk */ phys_disk_num = 0xFF; while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply, @@ -7074,6 +7101,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) MPI2_IOCSTATUS_MASK; if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) break; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:" + "ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } phys_disk_num = pd_pg0.PhysDiskNum; handle = le16_to_cpu(pd_pg0.DevHandle); sas_device = _scsih_sas_device_find_by_handle(ioc, handle); @@ -7083,17 +7117,46 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle) != 0) continue; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan " + "ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { + printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: " + " handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(sas_device_pg0.SASAddress)); mpt2sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); set_bit(handle, ioc->pd_handles); - _scsih_add_device(ioc, handle, 0, 1); + retry_count = 0; + /* This will retry adding the end device. + * _scsih_add_device() will decide on retries and + * return "1" when it should be retried + */ + while (_scsih_add_device(ioc, handle, retry_count++, + 1)) { + ssleep(1); + } + printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: " + " handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(sas_device_pg0.SASAddress)); } } + printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n", + ioc->name); + + printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name); /* volumes */ handle = 0xFFFF; while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply, @@ -7102,6 +7165,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) MPI2_IOCSTATUS_MASK; if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) break; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: " + "ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } handle = le16_to_cpu(volume_pg1.DevHandle); raid_device = _scsih_raid_device_find_by_wwid(ioc, le64_to_cpu(volume_pg1.WWID)); @@ -7111,18 +7181,38 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, sizeof(Mpi2RaidVolPage0_t))) continue; + ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & + MPI2_IOCSTATUS_MASK; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: " + "ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; element.VolDevHandle = volume_pg1.DevHandle; + printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: " + " handle (0x%04x)\n", ioc->name, + volume_pg1.DevHandle); _scsih_sas_volume_add(ioc, &element); + printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: " + " handle (0x%04x)\n", ioc->name, + volume_pg1.DevHandle); } } + printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n", + ioc->name); + skip_to_sas: + printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n", + ioc->name); /* sas devices */ handle = 0xFFFF; while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, @@ -7132,6 +7222,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) MPI2_IOCSTATUS_MASK; if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) break; + if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { + printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:" + " ioc_status(0x%04x), loginfo(0x%08x)\n", + ioc->name, ioc_status, + le32_to_cpu(mpi_reply.IOCLogInfo)); + break; + } handle = le16_to_cpu(sas_device_pg0.DevHandle); if (!(_scsih_is_end_device( le32_to_cpu(sas_device_pg0.DeviceInfo)))) @@ -7142,12 +7239,31 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc) continue; parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { + printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: " + "handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(sas_device_pg0.SASAddress)); mpt2sas_transport_update_links(ioc, sas_address, handle, sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - _scsih_add_device(ioc, handle, 0, 0); + retry_count = 0; + /* This will retry adding the end device. + * _scsih_add_device() will decide on retries and + * return "1" when it should be retried + */ + while (_scsih_add_device(ioc, handle, retry_count++, + 0)) { + ssleep(1); + } + printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: " + "handle (0x%04x), sas_addr(0x%016llx)\n", + ioc->name, handle, (unsigned long long) + le64_to_cpu(sas_device_pg0.SASAddress)); } } + printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n", + ioc->name); + printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name); } @@ -7239,7 +7355,9 @@ _firmware_event_work(struct work_struct *work) case MPT2SAS_PORT_ENABLE_COMPLETE: ioc->start_scan = 0; - + if (missing_delay[0] != -1 && missing_delay[1] != -1) + mpt2sas_base_update_missing_delay(ioc, missing_delay[0], + missing_delay[1]); dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete " "from worker thread\n", ioc->name)); diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 463d125ee77b..192218ae6797 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -2219,6 +2219,7 @@ static void __exit speakup_exit(void) unregister_keyboard_notifier(&keyboard_notifier_block); unregister_vt_notifier(&vt_notifier_block); speakup_unregister_devsynth(); + speakup_cancel_paste(); del_timer(&cursor_timer); kthread_stop(speakup_task); speakup_task = NULL; diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c index 1217c79ed712..7eb602c8b6a0 100644 --- a/drivers/staging/speakup/selection.c +++ b/drivers/staging/speakup/selection.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "speakup.h" @@ -121,20 +123,24 @@ int speakup_set_selection(struct tty_struct *tty) return 0; } -/* TODO: move to some helper thread, probably. That'd fix having to check for - * in_atomic(). */ -int speakup_paste_selection(struct tty_struct *tty) +struct speakup_paste_work { + struct work_struct work; + struct tty_struct *tty; +}; + +static void __speakup_paste_selection(struct work_struct *work) { + struct speakup_paste_work *spw = + container_of(work, struct speakup_paste_work, work); + struct tty_struct *tty = xchg(&spw->tty, NULL); struct vc_data *vc = (struct vc_data *) tty->driver_data; int pasted = 0, count; DECLARE_WAITQUEUE(wait, current); + add_wait_queue(&vc->paste_wait, &wait); while (sel_buffer && sel_buffer_lth > pasted) { set_current_state(TASK_INTERRUPTIBLE); if (test_bit(TTY_THROTTLED, &tty->flags)) { - if (in_atomic()) - /* if we are in an interrupt handler, abort */ - break; schedule(); continue; } @@ -146,6 +152,26 @@ int speakup_paste_selection(struct tty_struct *tty) } remove_wait_queue(&vc->paste_wait, &wait); current->state = TASK_RUNNING; + tty_kref_put(tty); +} + +static struct speakup_paste_work speakup_paste_work = { + .work = __WORK_INITIALIZER(speakup_paste_work.work, + __speakup_paste_selection) +}; + +int speakup_paste_selection(struct tty_struct *tty) +{ + if (cmpxchg(&speakup_paste_work.tty, NULL, tty) != NULL) + return -EBUSY; + + tty_kref_get(tty); + schedule_work_on(WORK_CPU_UNBOUND, &speakup_paste_work.work); return 0; } +void speakup_cancel_paste(void) +{ + cancel_work_sync(&speakup_paste_work.work); + tty_kref_put(speakup_paste_work.tty); +} diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h index 22f0fbb85f42..cfbd88c191a4 100644 --- a/drivers/staging/speakup/speakup.h +++ b/drivers/staging/speakup/speakup.h @@ -84,6 +84,7 @@ extern void synth_buffer_clear(void); extern void speakup_clear_selection(void); extern int speakup_set_selection(struct tty_struct *tty); extern int speakup_paste_selection(struct tty_struct *tty); +extern void speakup_cancel_paste(void); extern void speakup_register_devsynth(void); extern void speakup_unregister_devsynth(void); extern void synth_write(const char *buf, size_t count); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 3cb7a4f5b988..bc7d08fc8bbd 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -131,13 +131,13 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn) initiatorname_param = iscsi_find_param_from_key( INITIATORNAME, conn->param_list); - if (!initiatorname_param) - return -1; - sessiontype_param = iscsi_find_param_from_key( SESSIONTYPE, conn->param_list); - if (!sessiontype_param) + if (!initiatorname_param || !sessiontype_param) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_MISSING_FIELDS); return -1; + } sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0; diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 60470ee98fe2..89f89092b5f2 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -628,8 +628,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log login->req_buf, payload_length, conn->param_list); - if (ret < 0) + if (ret < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_INIT_ERR); return -1; + } if (login->first_request) if (iscsi_target_check_first_request(conn, login) < 0) @@ -644,8 +647,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log login->rsp_buf, &login->rsp_length, conn->param_list); - if (ret < 0) + if (ret < 0) { + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR, + ISCSI_LOGIN_STATUS_INIT_ERR); return -1; + } if (!login->auth_complete && ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) { diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index aa3c1062157a..b10f585cd11a 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -394,7 +394,7 @@ static inline int core_alua_state_standby( case SEND_DIAGNOSTIC: return 0; case MAINTENANCE_IN: - switch (cdb[1]) { + switch (cdb[1] & 0x1f) { case MI_REPORT_TARGET_PGS: return 0; default: @@ -437,7 +437,7 @@ static inline int core_alua_state_unavailable( case REPORT_LUNS: return 0; case MAINTENANCE_IN: - switch (cdb[1]) { + switch (cdb[1] & 0x1f) { case MI_REPORT_TARGET_PGS: return 0; default: @@ -478,7 +478,7 @@ static inline int core_alua_state_transition( case REPORT_LUNS: return 0; case MAINTENANCE_IN: - switch (cdb[1]) { + switch (cdb[1] & 0x1f) { case MI_REPORT_TARGET_PGS: return 0; default: diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index a251efd783de..f44459a2a7c5 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -299,7 +299,7 @@ static int fd_do_readv(struct se_task *task) for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { iov[i].iov_len = sg->length; - iov[i].iov_base = sg_virt(sg); + iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; } old_fs = get_fs(); @@ -307,6 +307,8 @@ static int fd_do_readv(struct se_task *task) ret = vfs_readv(fd, &iov[0], task->task_sg_nents, &pos); set_fs(old_fs); + for_each_sg(task->task_sg, sg, task->task_sg_nents, i) + kunmap(sg_page(sg)); kfree(iov); /* * Return zeros and GOOD status even if the READ did not return @@ -352,7 +354,7 @@ static int fd_do_writev(struct se_task *task) for_each_sg(task->task_sg, sg, task->task_sg_nents, i) { iov[i].iov_len = sg->length; - iov[i].iov_base = sg_virt(sg); + iov[i].iov_base = kmap(sg_page(sg)) + sg->offset; } old_fs = get_fs(); @@ -360,6 +362,9 @@ static int fd_do_writev(struct se_task *task) ret = vfs_writev(fd, &iov[0], task->task_sg_nents, &pos); set_fs(old_fs); + for_each_sg(task->task_sg, sg, task->task_sg_nents, i) + kunmap(sg_page(sg)); + kfree(iov); if (ret < 0 || ret != task->task_size) { diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index d084ba328af0..d34577dbfd25 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -128,10 +128,10 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag) * pSCSI Host ID and enable for phba mode */ sh = scsi_host_lookup(phv->phv_host_id); - if (IS_ERR(sh)) { + if (!sh) { pr_err("pSCSI: Unable to locate SCSI Host for" " phv_host_id: %d\n", phv->phv_host_id); - return PTR_ERR(sh); + return -EINVAL; } phv->phv_lld_host = sh; @@ -562,10 +562,10 @@ static struct se_device *pscsi_create_virtdevice( sh = phv->phv_lld_host; } else { sh = scsi_host_lookup(pdv->pdv_host_id); - if (IS_ERR(sh)) { + if (!sh) { pr_err("pSCSI: Unable to locate" " pdv_host_id: %d\n", pdv->pdv_host_id); - return ERR_CAST(sh); + return ERR_PTR(-EINVAL); } } } else { diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index f687892b00be..34df0b2a630e 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1458,6 +1458,7 @@ static inline void transport_generic_prepare_cdb( case VERIFY_16: /* SBC - VRProtect */ case WRITE_VERIFY: /* SBC - VRProtect */ case WRITE_VERIFY_12: /* SBC - VRProtect */ + case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */ break; default: cdb[1] &= 0x1f; /* clear logical unit number */ @@ -2813,7 +2814,7 @@ static int transport_generic_cmd_sequencer( /* * Check for emulated MI_REPORT_TARGET_PGS. */ - if (cdb[1] == MI_REPORT_TARGET_PGS && + if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS && su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) { cmd->execute_task = target_emulate_report_target_port_groups; @@ -4701,7 +4702,7 @@ int transport_send_check_condition_and_sense( /* ILLEGAL REQUEST */ buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* LOGICAL UNIT COMMUNICATION FAILURE */ - buffer[offset+SPC_ASC_KEY_OFFSET] = 0x80; + buffer[offset+SPC_ASC_KEY_OFFSET] = 0x08; break; } /* diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d537431d7e2e..5fe219142d41 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -282,6 +282,33 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, }, + [PORT_BRCM_TRUMANAGE] = { + .name = "TruManage", + .fifo_size = 1, + .tx_loadsz = 1024, + .flags = UART_CAP_HFIFO, + }, + [PORT_ALTR_16550_F32] = { + .name = "Altera 16550 FIFO32", + .fifo_size = 32, + .tx_loadsz = 32, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_ALTR_16550_F64] = { + .name = "Altera 16550 FIFO64", + .fifo_size = 64, + .tx_loadsz = 64, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, + [PORT_ALTR_16550_F128] = { + .name = "Altera 16550 FIFO128", + .fifo_size = 128, + .tx_loadsz = 128, + .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, + .flags = UART_CAP_FIFO | UART_CAP_AFE, + }, }; #if defined(CONFIG_MIPS_ALCHEMY) @@ -1470,6 +1497,11 @@ void serial8250_tx_chars(struct uart_8250_port *up) port->icount.tx++; if (uart_circ_empty(xmit)) break; + if (up->capabilities & UART_CAP_HFIFO) { + if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != + BOTH_EMPTY) + break; + } } while (--count > 0); if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) @@ -2641,7 +2673,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser) if (ser->irq >= nr_irqs || ser->irq < 0 || ser->baud_base < 9600 || ser->type < PORT_UNKNOWN || ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS || - ser->type == PORT_STARTECH) + ser->type == PORT_STARTECH || uart_config[ser->type].name == NULL) return -EINVAL; return 0; } @@ -2651,7 +2683,7 @@ serial8250_type(struct uart_port *port) { int type = port->type; - if (type >= ARRAY_SIZE(uart_config)) + if (type >= ARRAY_SIZE(uart_config) || uart_config[type].name == NULL) type = 0; return uart_config[type].name; } diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 2868a1da254d..b37147c45c5c 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h @@ -69,6 +69,7 @@ struct serial8250_config { #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ +#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index fdc669cbf7c5..c48cf891e6bc 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1077,6 +1077,18 @@ pci_omegapci_setup(struct serial_private *priv, return setup_port(priv, port, 2, idx * 8, 0); } +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + int ret = pci_default_setup(priv, board, port, idx); + + port->port.type = PORT_BRCM_TRUMANAGE; + port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); + return ret; +} + static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_port *port, int idx) @@ -1151,9 +1163,11 @@ pci_xr17c154_setup(struct serial_private *priv, #define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d +#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 +#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588 /* * Master list of serial port init/setup/exit quirks. @@ -1425,15 +1439,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { }, { .vendor = PCI_VENDOR_ID_PLX, - .device = PCI_DEVICE_ID_PLX_9050, - .subvendor = PCI_VENDOR_ID_PLX, - .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584, - .init = pci_plx9050_init, - .setup = pci_default_setup, - .exit = __devexit_p(pci_plx9050_exit), - }, - { - .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_ROMULUS, .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, @@ -1692,6 +1697,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { .setup = pci_omegapci_setup, }, /* + * Broadcom TruManage (NetXtreme) + */ + { + .vendor = PCI_VENDOR_ID_BROADCOM, + .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_brcm_trumanage_setup, + }, + + /* * Default "match everything" terminator entry */ { @@ -1880,6 +1896,7 @@ enum pci_board_num_t { pbn_ce4100_1_115200, pbn_omegapci, pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, }; /* @@ -2586,6 +2603,12 @@ static struct pciserial_board pci_boards[] __devinitdata = { .num_ports = 2, .base_baud = 115200, }, + [pbn_brcm_trumanage] = { + .flags = FL_BASE0, + .num_ports = 1, + .reg_shift = 2, + .base_baud = 115200, + }, }; static const struct pci_device_id softmodem_blacklist[] = { @@ -3109,7 +3132,12 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX, PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0, - pbn_b0_4_115200 }, + pbn_b2_4_115200 }, + /* Unknown card - subdevice 0x1588 */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_PLX, + PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0, + pbn_b2_8_115200 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_SUBVENDOR_ID_KEYSPAN, PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, @@ -4143,6 +4171,13 @@ static struct pci_device_id serial_pci_tbl[] = { pbn_omegapci }, /* + * Broadcom TruManage + */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_brcm_trumanage }, + + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL */ diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index e8c9cee07d00..6563cad09293 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c @@ -182,6 +182,12 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { { .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16850", .data = (void *)PORT_16850, }, { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, + { .compatible = "altr,16550-FIFO32", + .data = (void *)PORT_ALTR_16550_F32, }, + { .compatible = "altr,16550-FIFO64", + .data = (void *)PORT_ALTR_16550_F64, }, + { .compatible = "altr,16550-FIFO128", + .data = (void *)PORT_ALTR_16550_F128, }, #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL { .compatible = "ibm,qpace-nwp-serial", .data = (void *)PORT_NWPSERIAL, }, diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 2e99f7959b96..e78d2a6b4083 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -646,11 +646,12 @@ static int dma_push_rx(struct eg20t_port *priv, int size) dev_warn(port->dev, "Rx overrun: dropping %u bytes\n", size - room); if (!room) - return room; + goto out; tty_insert_flip_string(tty, sg_virt(&priv->sg_rx), size); port->icount.rx += room; +out: tty_kref_put(tty); return room; @@ -1064,6 +1065,8 @@ static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr) if (tty == NULL) { for (i = 0; error_msg[i] != NULL; i++) dev_err(&priv->pdev->dev, error_msg[i]); + } else { + tty_kref_put(tty); } } diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 6c9b7cd6778a..4f02f9ce05c5 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty) { struct tty_buffer *thead; - while ((thead = tty->buf.head) != NULL) { - tty->buf.head = thead->next; - tty_buffer_free(tty, thead); + if (tty->buf.head == NULL) + return; + while ((thead = tty->buf.head->next) != NULL) { + tty_buffer_free(tty, tty->buf.head); + tty->buf.head = thead; } - tty->buf.tail = NULL; + WARN_ON(tty->buf.head != tty->buf.tail); + tty->buf.head->read = tty->buf.head->commit; } /** diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index c4d894a95701..35bc3baa8427 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1708,10 +1708,13 @@ int usb_runtime_suspend(struct device *dev) if (status == -EAGAIN || status == -EBUSY) usb_mark_last_busy(udev); - /* The PM core reacts badly unless the return code is 0, - * -EAGAIN, or -EBUSY, so always return -EBUSY on an error. + /* + * The PM core reacts badly unless the return code is 0, + * -EAGAIN, or -EBUSY, so always return -EBUSY on an error + * (except for root hubs, because they don't suspend through + * an upstream port like other USB devices). */ - if (status != 0) + if (status != 0 && udev->parent) return -EBUSY; return status; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d2b7327d9de3..e0d4d901e99d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1401,8 +1401,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); - /* Hubs have proper suspend/resume support. */ - usb_enable_autosuspend(hdev); + /* + * Hubs have proper suspend/resume support, except for root hubs + * where the controller driver doesn't have bus_suspend and + * bus_resume methods. + */ + if (hdev->parent) { /* normal device */ + usb_enable_autosuspend(hdev); + } else { /* root hub */ + const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver; + + if (drv->bus_suspend && drv->bus_resume) + usb_enable_autosuspend(hdev); + } if (hdev->level == MAX_TOPO_LEVEL) { dev_err(&intf->dev, diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 3347e9be9a67..197685852638 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1812,6 +1812,16 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) kfree(cur_cd); } + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); + for (i = 0; i < num_ports; i++) { + struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; + for (j = 0; j < XHCI_MAX_INTERVAL; j++) { + struct list_head *ep = &bwt->interval_bw[j].endpoints; + while (!list_empty(ep)) + list_del_init(ep->next); + } + } + for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -1852,16 +1862,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) if (!xhci->rh_bw) goto no_bw; - num_ports = HCS_MAX_PORTS(xhci->hcs_params1); - for (i = 0; i < num_ports; i++) { - struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; - for (j = 0; j < XHCI_MAX_INTERVAL; j++) { - struct list_head *ep = &bwt->interval_bw[j].endpoints; - while (!list_empty(ep)) - list_del_init(ep->next); - } - } - for (i = 0; i < num_ports; i++) { struct xhci_tt_bw_info *tt, *n; list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) { diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3b2dfe9c5212..bb9f4111d1b8 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -591,6 +591,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 993c93df6874..500474c48f4b 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -538,6 +538,11 @@ */ #define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ +/* + * NovaTech product ids (FTDI_VID) + */ +#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */ + /********************************/ /** third-party VID/PID combos **/ diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 5cca1b3cb083..51751828562f 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -915,7 +915,7 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data; i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK; - i2c_header->Size = (__u16)buffer_size; + i2c_header->Size = cpu_to_le16(buffer_size); i2c_header->CheckSum = cs; firmware_rec->Ver_Major = OperationalMajorVersion; firmware_rec->Ver_Minor = OperationalMinorVersion; diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h index 51f83fbb73bb..6f6a856bc37c 100644 --- a/drivers/usb/serial/io_usbvend.h +++ b/drivers/usb/serial/io_usbvend.h @@ -594,7 +594,7 @@ struct edge_boot_descriptor { struct ti_i2c_desc { __u8 Type; // Type of descriptor - __u16 Size; // Size of data only not including header + __le16 Size; // Size of data only not including header __u8 CheckSum; // Checksum (8 bit sum of data only) __u8 Data[0]; // Data starts here } __attribute__((packed)); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e9c113dab5c4..def9ed02bf19 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -161,6 +161,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 #define NOVATELWIRELESS_PRODUCT_E362 0x9010 +#define NOVATELWIRELESS_PRODUCT_E371 0x9011 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 @@ -1025,6 +1026,7 @@ static const struct usb_device_id option_ids[] = { /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index d014727fc8f2..4db777d3dc05 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -213,6 +213,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) struct sockaddr *sap = (struct sockaddr *)&address; size_t salen = sizeof(address); char *fo_path; + struct net *net = file->f_dentry->d_sb->s_fs_info; /* sanity check */ if (size == 0) @@ -225,7 +226,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) if (qword_get(&buf, fo_path, size) < 0) return -EINVAL; - if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0) + if (rpc_pton(net, fo_path, size, sap, salen) == 0) return -EINVAL; return nlmsvc_unlock_all_by_ip(sap); @@ -389,6 +390,8 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) { char *mesg = buf; int rv; + struct net *net = file->f_dentry->d_sb->s_fs_info; + if (size > 0) { int newthreads; rv = get_int(&mesg, &newthreads); @@ -396,7 +399,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return rv; if (newthreads < 0) return -EINVAL; - rv = nfsd_svc(NFS_PORT, newthreads); + rv = nfsd_svc(NFS_PORT, newthreads, net); if (rv < 0) return rv; } else @@ -438,6 +441,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) int len; int npools; int *nthreads; + struct net *net = file->f_dentry->d_sb->s_fs_info; mutex_lock(&nfsd_mutex); npools = nfsd_nrpools(); @@ -468,7 +472,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size) if (nthreads[i] < 0) goto out_free; } - rv = nfsd_set_nrthreads(i, nthreads); + rv = nfsd_set_nrthreads(i, nthreads, net); if (rv) goto out_free; } @@ -647,17 +651,21 @@ static ssize_t __write_ports_names(char *buf) * a socket of a supported family/protocol, and we use it as an * nfsd listener. */ -static ssize_t __write_ports_addfd(char *buf) +static ssize_t __write_ports_addfd(char *buf, struct net *net) { char *mesg = buf; int fd, err; - struct net *net = &init_net; err = get_int(&mesg, &fd); if (err != 0 || fd < 0) return -EINVAL; - err = nfsd_create_serv(); + if (svc_alien_sock(net, fd)) { + printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__); + return -EINVAL; + } + + err = nfsd_create_serv(net); if (err != 0) return err; @@ -695,12 +703,11 @@ static ssize_t __write_ports_delfd(char *buf) * A transport listener is added by writing it's transport name and * a port number. */ -static ssize_t __write_ports_addxprt(char *buf) +static ssize_t __write_ports_addxprt(char *buf, struct net *net) { char transport[16]; struct svc_xprt *xprt; int port, err; - struct net *net = &init_net; if (sscanf(buf, "%15s %4u", transport, &port) != 2) return -EINVAL; @@ -708,7 +715,7 @@ static ssize_t __write_ports_addxprt(char *buf) if (port < 1 || port > USHRT_MAX) return -EINVAL; - err = nfsd_create_serv(); + err = nfsd_create_serv(net); if (err != 0) return err; @@ -740,7 +747,7 @@ out_err: * A transport listener is removed by writing a "-", it's transport * name, and it's port number. */ -static ssize_t __write_ports_delxprt(char *buf) +static ssize_t __write_ports_delxprt(char *buf, struct net *net) { struct svc_xprt *xprt; char transport[16]; @@ -752,7 +759,7 @@ static ssize_t __write_ports_delxprt(char *buf) if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL) return -EINVAL; - xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port); + xprt = svc_find_xprt(nfsd_serv, transport, net, AF_UNSPEC, port); if (xprt == NULL) return -ENOTCONN; @@ -761,22 +768,23 @@ static ssize_t __write_ports_delxprt(char *buf) return 0; } -static ssize_t __write_ports(struct file *file, char *buf, size_t size) +static ssize_t __write_ports(struct file *file, char *buf, size_t size, + struct net *net) { if (size == 0) return __write_ports_names(buf); if (isdigit(buf[0])) - return __write_ports_addfd(buf); + return __write_ports_addfd(buf, net); if (buf[0] == '-' && isdigit(buf[1])) return __write_ports_delfd(buf); if (isalpha(buf[0])) - return __write_ports_addxprt(buf); + return __write_ports_addxprt(buf, net); if (buf[0] == '-' && isalpha(buf[1])) - return __write_ports_delxprt(buf); + return __write_ports_delxprt(buf, net); return -EINVAL; } @@ -855,9 +863,10 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size) static ssize_t write_ports(struct file *file, char *buf, size_t size) { ssize_t rv; + struct net *net = file->f_dentry->d_sb->s_fs_info; mutex_lock(&nfsd_mutex); - rv = __write_ports(file, buf, size); + rv = __write_ports(file, buf, size, net); mutex_unlock(&nfsd_mutex); return rv; } @@ -1092,20 +1101,35 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) #endif /* last one */ {""} }; - return simple_fill_super(sb, 0x6e667364, nfsd_files); + struct net *net = data; + int ret; + + ret = simple_fill_super(sb, 0x6e667364, nfsd_files); + if (ret) + return ret; + sb->s_fs_info = get_net(net); + return 0; } static struct dentry *nfsd_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - return mount_single(fs_type, flags, data, nfsd_fill_super); + return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super); +} + +static void nfsd_umount(struct super_block *sb) +{ + struct net *net = sb->s_fs_info; + + kill_litter_super(sb); + put_net(net); } static struct file_system_type nfsd_fs_type = { .owner = THIS_MODULE, .name = "nfsd", .mount = nfsd_mount, - .kill_sb = kill_litter_super, + .kill_sb = nfsd_umount, }; #ifdef CONFIG_PROC_FS diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 1336a6512cdc..a0989a269262 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -65,13 +65,13 @@ extern const struct seq_operations nfs_exports_op; /* * Function prototypes. */ -int nfsd_svc(unsigned short port, int nrservs); +int nfsd_svc(unsigned short port, int nrservs, struct net *net); int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); int nfsd_nrthreads(void); int nfsd_nrpools(void); int nfsd_get_nrthreads(int n, int *); -int nfsd_set_nrthreads(int n, int *); +int nfsd_set_nrthreads(int n, int *, struct net *); static inline void nfsd_destroy(struct net *net) { @@ -101,7 +101,7 @@ enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL }; int nfsd_vers(int vers, enum vers_op change); int nfsd_minorversion(u32 minorversion, enum vers_op change); void nfsd_reset_versions(void); -int nfsd_create_serv(void); +int nfsd_create_serv(struct net *net); extern int nfsd_max_blksize; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 25d839ed0ae1..ed8eedfbdb63 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -182,18 +182,18 @@ int nfsd_nrthreads(void) return rv; } -static int nfsd_init_socks(int port) +static int nfsd_init_socks(int port, struct net *net) { int error; if (!list_empty(&nfsd_serv->sv_permsocks)) return 0; - error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, + error = svc_create_xprt(nfsd_serv, "udp", net, PF_INET, port, SVC_SOCK_DEFAULTS); if (error < 0) return error; - error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, + error = svc_create_xprt(nfsd_serv, "tcp", net, PF_INET, port, SVC_SOCK_DEFAULTS); if (error < 0) return error; @@ -203,7 +203,7 @@ static int nfsd_init_socks(int port) static bool nfsd_up = false; -static int nfsd_startup(unsigned short port, int nrservs) +static int nfsd_startup(unsigned short port, int nrservs, struct net *net) { int ret; @@ -217,10 +217,10 @@ static int nfsd_startup(unsigned short port, int nrservs) ret = nfsd_racache_init(2*nrservs); if (ret) return ret; - ret = nfsd_init_socks(port); + ret = nfsd_init_socks(port, net); if (ret) goto out_racache; - ret = lockd_up(&init_net); + ret = lockd_up(net); if (ret) goto out_racache; ret = nfs4_state_start(); @@ -229,13 +229,13 @@ static int nfsd_startup(unsigned short port, int nrservs) nfsd_up = true; return 0; out_lockd: - lockd_down(&init_net); + lockd_down(net); out_racache: nfsd_racache_shutdown(); return ret; } -static void nfsd_shutdown(void) +static void nfsd_shutdown(struct net *net) { /* * write_ports can create the server without actually starting @@ -246,14 +246,14 @@ static void nfsd_shutdown(void) if (!nfsd_up) return; nfs4_state_shutdown(); - lockd_down(&init_net); + lockd_down(net); nfsd_racache_shutdown(); nfsd_up = false; } static void nfsd_last_thread(struct svc_serv *serv, struct net *net) { - nfsd_shutdown(); + nfsd_shutdown(net); svc_rpcb_cleanup(serv, net); @@ -326,10 +326,9 @@ static int nfsd_get_default_max_blksize(void) return ret; } -int nfsd_create_serv(void) +int nfsd_create_serv(struct net *net) { int error; - struct net *net = &init_net; WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { @@ -375,12 +374,11 @@ int nfsd_get_nrthreads(int n, int *nthreads) return 0; } -int nfsd_set_nrthreads(int n, int *nthreads) +int nfsd_set_nrthreads(int n, int *nthreads, struct net *net) { int i = 0; int tot = 0; int err = 0; - struct net *net = &init_net; WARN_ON(!mutex_is_locked(&nfsd_mutex)); @@ -435,11 +433,10 @@ int nfsd_set_nrthreads(int n, int *nthreads) * this is the first time nrservs is nonzero. */ int -nfsd_svc(unsigned short port, int nrservs) +nfsd_svc(unsigned short port, int nrservs, struct net *net) { int error; bool nfsd_up_before; - struct net *net = &init_net; mutex_lock(&nfsd_mutex); dprintk("nfsd: creating service\n"); @@ -451,13 +448,13 @@ nfsd_svc(unsigned short port, int nrservs) if (nrservs == 0 && nfsd_serv == NULL) goto out; - error = nfsd_create_serv(); + error = nfsd_create_serv(net); if (error) goto out; nfsd_up_before = nfsd_up; - error = nfsd_startup(port, nrservs); + error = nfsd_startup(port, nrservs, net); if (error) goto out_destroy; error = svc_set_num_threads(nfsd_serv, NULL, nrservs); @@ -470,7 +467,7 @@ nfsd_svc(unsigned short port, int nrservs) error = nfsd_serv->sv_nrthreads - 1; out_shutdown: if (error < 0 && !nfsd_up_before) - nfsd_shutdown(); + nfsd_shutdown(net); out_destroy: nfsd_destroy(net); /* Release server */ out: @@ -486,6 +483,8 @@ static int nfsd(void *vrqstp) { struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; + struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list); + struct net *net = perm_sock->xpt_net; int err, preverr = 0; /* Lock module and set up kernel thread */ @@ -560,7 +559,7 @@ out: /* Release the thread */ svc_exit_thread(rqstp); - nfsd_destroy(&init_net); + nfsd_destroy(net); /* Release module */ mutex_unlock(&nfsd_mutex); @@ -671,7 +670,7 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) int nfsd_pool_stats_release(struct inode *inode, struct file *file) { int ret = seq_release(inode, file); - struct net *net = &init_net; + struct net *net = inode->i_sb->s_fs_info; mutex_lock(&nfsd_mutex); /* this function really, really should have been called svc_put() */ diff --git a/include/linux/highmem.h b/include/linux/highmem.h index d3999b4e26cc..e186e3c28ed8 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -39,10 +39,17 @@ extern unsigned long totalhigh_pages; void kmap_flush_unused(void); +struct page *kmap_to_page(void *addr); + #else /* CONFIG_HIGHMEM */ static inline unsigned int nr_free_highpages(void) { return 0; } +static inline struct page *kmap_to_page(void *addr) +{ + return virt_to_page(addr); +} + #define totalhigh_pages 0UL #ifndef ARCH_HAS_KMAP diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index d7dbf4ec89d2..0a7e4f4201b1 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -752,6 +752,7 @@ #define PCI_DEVICE_ID_HP_CISSD 0x3238 #define PCI_DEVICE_ID_HP_CISSE 0x323a #define PCI_DEVICE_ID_HP_CISSF 0x323b +#define PCI_DEVICE_ID_HP_CISSH 0x323c #define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031 #define PCI_VENDOR_ID_PCTECH 0x1042 diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 2db407a40051..60f55645af32 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -47,7 +47,11 @@ #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ -#define PORT_MAX_8250 21 /* max port ID */ +#define PORT_BRCM_TRUMANAGE 25 +#define PORT_ALTR_16550_F32 26 /* Altera 16550 UART with 32 FIFOs */ +#define PORT_ALTR_16550_F64 27 /* Altera 16550 UART with 64 FIFOs */ +#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */ +#define PORT_MAX_8250 28 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index cb4ac69e1f33..e4c6cec9ff1a 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -42,6 +42,7 @@ void svc_sock_update_bufs(struct svc_serv *serv); int svc_sock_names(struct svc_serv *serv, char *buf, const size_t buflen, const char *toclose); +bool svc_alien_sock(struct net *net, int fd); int svc_addsock(struct svc_serv *serv, const int fd, char *name_return, const size_t len); void svc_init_xprt_sock(void); diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index bdf4b0034739..82e12ad3d97f 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -39,7 +39,7 @@ #define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */ #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ -#define VIRTIO_CONSOLE_BAD_ID (~(u32)0) +#define VIRTIO_CONSOLE_BAD_ID (~(__u32)0) struct virtio_console_config { /* colums of the screens */ diff --git a/kernel/cpu.c b/kernel/cpu.c index 26feaa985a52..04671bf91c12 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -631,10 +631,12 @@ void set_cpu_present(unsigned int cpu, bool present) void set_cpu_online(unsigned int cpu, bool online) { - if (online) + if (online) { cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits)); - else + cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits)); + } else { cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits)); + } } void set_cpu_active(unsigned int cpu, bool active) diff --git a/kernel/events/core.c b/kernel/events/core.c index e39346fb2e91..685ce46b2aff 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1196,6 +1196,11 @@ group_sched_out(struct perf_event *group_event, cpuctx->exclusive = 0; } +struct remove_event { + struct perf_event *event; + bool detach_group; +}; + /* * Cross CPU call to remove a performance event * @@ -1204,12 +1209,15 @@ group_sched_out(struct perf_event *group_event, */ static int __perf_remove_from_context(void *info) { - struct perf_event *event = info; + struct remove_event *re = info; + struct perf_event *event = re->event; struct perf_event_context *ctx = event->ctx; struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); raw_spin_lock(&ctx->lock); event_sched_out(event, cpuctx, ctx); + if (re->detach_group) + perf_group_detach(event); list_del_event(event, ctx); if (!ctx->nr_events && cpuctx->task_ctx == ctx) { ctx->is_active = 0; @@ -1234,10 +1242,14 @@ static int __perf_remove_from_context(void *info) * When called from perf_event_exit_task, it's OK because the * context has been detached from its task. */ -static void perf_remove_from_context(struct perf_event *event) +static void perf_remove_from_context(struct perf_event *event, bool detach_group) { struct perf_event_context *ctx = event->ctx; struct task_struct *task = ctx->task; + struct remove_event re = { + .event = event, + .detach_group = detach_group, + }; lockdep_assert_held(&ctx->mutex); @@ -1246,12 +1258,12 @@ static void perf_remove_from_context(struct perf_event *event) * Per cpu events are removed via an smp call and * the removal is always successful. */ - cpu_function_call(event->cpu, __perf_remove_from_context, event); + cpu_function_call(event->cpu, __perf_remove_from_context, &re); return; } retry: - if (!task_function_call(task, __perf_remove_from_context, event)) + if (!task_function_call(task, __perf_remove_from_context, &re)) return; raw_spin_lock_irq(&ctx->lock); @@ -1268,6 +1280,8 @@ retry: * Since the task isn't running, its safe to remove the event, us * holding the ctx->lock ensures the task won't get scheduled in. */ + if (detach_group) + perf_group_detach(event); list_del_event(event, ctx); raw_spin_unlock_irq(&ctx->lock); } @@ -2962,10 +2976,7 @@ int perf_event_release_kernel(struct perf_event *event) * to trigger the AB-BA case. */ mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING); - raw_spin_lock_irq(&ctx->lock); - perf_group_detach(event); - raw_spin_unlock_irq(&ctx->lock); - perf_remove_from_context(event); + perf_remove_from_context(event, true); mutex_unlock(&ctx->mutex); free_event(event); @@ -4854,6 +4865,9 @@ struct swevent_htable { /* Recursion avoidance in each contexts */ int recursion[PERF_NR_CONTEXTS]; + + /* Keeps track of cpu being initialized/exited */ + bool online; }; static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); @@ -5101,8 +5115,14 @@ static int perf_swevent_add(struct perf_event *event, int flags) hwc->state = !(flags & PERF_EF_START); head = find_swevent_head(swhash, event); - if (WARN_ON_ONCE(!head)) + if (!head) { + /* + * We can race with cpu hotplug code. Do not + * WARN if the cpu just got unplugged. + */ + WARN_ON_ONCE(swhash->online); return -EINVAL; + } hlist_add_head_rcu(&event->hlist_entry, head); @@ -6347,6 +6367,9 @@ SYSCALL_DEFINE5(perf_event_open, if (attr.freq) { if (attr.sample_freq > sysctl_perf_event_sample_rate) return -EINVAL; + } else { + if (attr.sample_period & (1ULL << 63)) + return -EINVAL; } /* @@ -6493,7 +6516,7 @@ SYSCALL_DEFINE5(perf_event_open, struct perf_event_context *gctx = group_leader->ctx; mutex_lock(&gctx->mutex); - perf_remove_from_context(group_leader); + perf_remove_from_context(group_leader, false); /* * Removing from the context ends up with disabled @@ -6503,7 +6526,7 @@ SYSCALL_DEFINE5(perf_event_open, perf_event__state_init(group_leader); list_for_each_entry(sibling, &group_leader->sibling_list, group_entry) { - perf_remove_from_context(sibling); + perf_remove_from_context(sibling, false); perf_event__state_init(sibling); put_ctx(gctx); } @@ -6656,13 +6679,7 @@ __perf_event_exit_task(struct perf_event *child_event, struct perf_event_context *child_ctx, struct task_struct *child) { - if (child_event->parent) { - raw_spin_lock_irq(&child_ctx->lock); - perf_group_detach(child_event); - raw_spin_unlock_irq(&child_ctx->lock); - } - - perf_remove_from_context(child_event); + perf_remove_from_context(child_event, !!child_event->parent); /* * It can happen that the parent exits first, and has events @@ -7124,6 +7141,7 @@ static void __cpuinit perf_event_init_cpu(int cpu) struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); mutex_lock(&swhash->hlist_mutex); + swhash->online = true; if (swhash->hlist_refcount > 0) { struct swevent_hlist *hlist; @@ -7146,14 +7164,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu) static void __perf_event_exit_context(void *__info) { + struct remove_event re = { .detach_group = false }; struct perf_event_context *ctx = __info; - struct perf_event *event; perf_pmu_rotate_stop(ctx->pmu); rcu_read_lock(); - list_for_each_entry_rcu(event, &ctx->event_list, event_entry) - __perf_remove_from_context(event); + list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry) + __perf_remove_from_context(&re); rcu_read_unlock(); } @@ -7181,6 +7199,7 @@ static void perf_event_exit_cpu(int cpu) perf_event_exit_cpu_context(cpu); mutex_lock(&swhash->hlist_mutex); + swhash->online = false; swevent_hlist_release(swhash); mutex_unlock(&swhash->hlist_mutex); } diff --git a/kernel/sched/core.c b/kernel/sched/core.c index e01398f0a52e..af837d82634e 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5656,7 +5656,6 @@ static int __cpuinit sched_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { - case CPU_STARTING: case CPU_DOWN_FAILED: set_cpu_active((long)hcpu, true); return NOTIFY_OK; diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c index d72586fdf660..beb9a8f3811e 100644 --- a/kernel/sched/cpupri.c +++ b/kernel/sched/cpupri.c @@ -68,8 +68,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p, int idx = 0; int task_pri = convert_prio(p->prio); - if (task_pri >= MAX_RT_PRIO) - return 0; + BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES); for (idx = 0; idx < task_pri; idx++) { struct cpupri_vec *vec = &cp->pri_to_cpu[idx]; diff --git a/mm/highmem.c b/mm/highmem.c index 57d82c6250c3..09fc744d104e 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -94,6 +94,19 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait); do { spin_unlock(&kmap_lock); (void)(flags); } while (0) #endif +struct page *kmap_to_page(void *vaddr) +{ + unsigned long addr = (unsigned long)vaddr; + + if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) { + int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT; + return pte_page(pkmap_page_table[i]); + } + + return virt_to_page(addr); +} +EXPORT_SYMBOL(kmap_to_page); + static void flush_all_zero_pkmaps(void) { int i; diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 455a67971570..2fe9bf640c71 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1122,6 +1122,8 @@ int memory_failure(unsigned long pfn, int trapno, int flags) */ if (!PageHWPoison(p)) { printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn); + atomic_long_sub(nr_pages, &mce_bad_pages); + put_page(hpage); res = 0; goto out; } diff --git a/mm/rmap.c b/mm/rmap.c index f02c862fab69..3ff473feafd4 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -1721,10 +1721,9 @@ void __put_anon_vma(struct anon_vma *anon_vma) { struct anon_vma *root = anon_vma->root; + anon_vma_free(anon_vma); if (root != anon_vma && atomic_dec_and_test(&root->refcount)) anon_vma_free(root); - - anon_vma_free(anon_vma); } #ifdef CONFIG_MIGRATION diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 052d343d43ff..9f4fcc5419e5 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -325,7 +326,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan, int count = nr_pages; while (nr_pages) { s = rest_of_page(data); - pages[index++] = virt_to_page(data); + pages[index++] = kmap_to_page(data); data += s; nr_pages--; } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 932420de2f38..3bb535b08822 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2620,10 +2620,15 @@ done: } } -static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_command_rej(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; + if (cmd_len < sizeof(*rej)) + return -EPROTO; + if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD) return 0; @@ -2640,7 +2645,8 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd return 0; } -static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static int l2cap_connect_req(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; @@ -2648,8 +2654,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd struct sock *parent, *sk = NULL; int result, status = L2CAP_CS_NO_INFO; - u16 dcid = 0, scid = __le16_to_cpu(req->scid); - __le16 psm = req->psm; + u16 dcid = 0, scid; + __le16 psm; + + if (cmd_len < sizeof(struct l2cap_conn_req)) + return -EPROTO; + + scid = __le16_to_cpu(req->scid); + psm = req->psm; BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); @@ -2770,7 +2782,9 @@ sendresp: return 0; } -static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static int l2cap_connect_rsp(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; @@ -2778,6 +2792,9 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd u8 req[128]; int err; + if (cmd_len < sizeof(*rsp)) + return -EPROTO; + scid = __le16_to_cpu(rsp->scid); dcid = __le16_to_cpu(rsp->dcid); result = __le16_to_cpu(rsp->result); @@ -2857,6 +2874,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr struct l2cap_chan *chan; int len; + if (cmd_len < sizeof(*req)) + return -EPROTO; + dcid = __le16_to_cpu(req->dcid); flags = __le16_to_cpu(req->flags); @@ -2882,7 +2902,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr /* Reject if config buffer is too small. */ len = cmd_len - sizeof(*req); - if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { + if (chan->conf_len + len > sizeof(chan->conf_req)) { l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(chan, rsp, L2CAP_CONF_REJECT, flags), rsp); @@ -2959,12 +2979,17 @@ unlock: return 0; } -static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_config_rsp(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; struct l2cap_chan *chan; - int len = cmd->len - sizeof(*rsp); + int len = cmd_len - sizeof(*rsp); + + if (cmd_len < sizeof(*rsp)) + return -EPROTO; scid = __le16_to_cpu(rsp->scid); flags = __le16_to_cpu(rsp->flags); @@ -3066,7 +3091,9 @@ done: return 0; } -static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_disconnect_req(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; struct l2cap_disconn_rsp rsp; @@ -3074,6 +3101,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd struct l2cap_chan *chan; struct sock *sk; + if (cmd_len != sizeof(*req)) + return -EPROTO; + scid = __le16_to_cpu(req->scid); dcid = __le16_to_cpu(req->dcid); @@ -3110,12 +3140,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd return 0; } -static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; struct l2cap_chan *chan; + if (cmd_len != sizeof(*rsp)) + return -EPROTO; + scid = __le16_to_cpu(rsp->scid); dcid = __le16_to_cpu(rsp->dcid); @@ -3142,11 +3177,16 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd return 0; } -static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_information_req(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_info_req *req = (struct l2cap_info_req *) data; u16 type; + if (cmd_len != sizeof(*req)) + return -EPROTO; + type = __le16_to_cpu(req->type); BT_DBG("type 0x%4.4x", type); @@ -3192,11 +3232,16 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm return 0; } -static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) +static inline int l2cap_information_rsp(struct l2cap_conn *conn, + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + u8 *data) { struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; u16 type, result; + if (cmd_len != sizeof(*rsp)) + return -EPROTO; + type = __le16_to_cpu(rsp->type); result = __le16_to_cpu(rsp->result); @@ -3282,11 +3327,12 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn, } static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, - struct l2cap_cmd_hdr *cmd, void *data) + struct l2cap_cmd_hdr *cmd, u16 cmd_len, + void *data) { BT_DBG("conn %p", conn); - return l2cap_connect_rsp(conn, cmd, data); + return l2cap_connect_rsp(conn, cmd, cmd_len, data); } static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident, @@ -3399,7 +3445,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, struct l2cap_move_chan_cfm_rsp *rsp = data; u16 icid; - if (cmd_len != sizeof(*rsp)) + if (cmd_len < sizeof(*rsp)) return -EPROTO; icid = le16_to_cpu(rsp->icid); @@ -3479,15 +3525,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, switch (cmd->code) { case L2CAP_COMMAND_REJ: - l2cap_command_rej(conn, cmd, data); + l2cap_command_rej(conn, cmd, cmd_len, data); break; case L2CAP_CONN_REQ: - err = l2cap_connect_req(conn, cmd, data); + err = l2cap_connect_req(conn, cmd, cmd_len, data); break; case L2CAP_CONN_RSP: - err = l2cap_connect_rsp(conn, cmd, data); + err = l2cap_connect_rsp(conn, cmd, cmd_len, data); break; case L2CAP_CONF_REQ: @@ -3495,15 +3541,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, break; case L2CAP_CONF_RSP: - err = l2cap_config_rsp(conn, cmd, data); + err = l2cap_config_rsp(conn, cmd, cmd_len, data); break; case L2CAP_DISCONN_REQ: - err = l2cap_disconnect_req(conn, cmd, data); + err = l2cap_disconnect_req(conn, cmd, cmd_len, data); break; case L2CAP_DISCONN_RSP: - err = l2cap_disconnect_rsp(conn, cmd, data); + err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data); break; case L2CAP_ECHO_REQ: @@ -3514,11 +3560,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, break; case L2CAP_INFO_REQ: - err = l2cap_information_req(conn, cmd, data); + err = l2cap_information_req(conn, cmd, cmd_len, data); break; case L2CAP_INFO_RSP: - err = l2cap_information_rsp(conn, cmd, data); + err = l2cap_information_rsp(conn, cmd, cmd_len, data); break; case L2CAP_CREATE_CHAN_REQ: @@ -3526,7 +3572,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, break; case L2CAP_CREATE_CHAN_RSP: - err = l2cap_create_channel_rsp(conn, cmd, data); + err = l2cap_create_channel_rsp(conn, cmd, cmd_len, data); break; case L2CAP_MOVE_CHAN_REQ: diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f190ea96f112..4c23cfc0296c 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1441,6 +1441,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, return svsk; } +bool svc_alien_sock(struct net *net, int fd) +{ + int err; + struct socket *sock = sockfd_lookup(fd, &err); + bool ret = false; + + if (!sock) + goto out; + if (sock_net(sock->sk) != net) + ret = true; + sockfd_put(sock); +out: + return ret; +} +EXPORT_SYMBOL_GPL(svc_alien_sock); + /** * svc_addsock - add a listener socket to an RPC service * @serv: pointer to RPC service to which to add a new listener diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2a122954d2a6..2415dcec3265 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4951,12 +4951,10 @@ static const struct alc_fixup alc260_fixups[] = { [ALC260_FIXUP_COEF] = { .type = ALC_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 }, + { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 }, { } }, - .chained = true, - .chain_id = ALC260_FIXUP_HP_PIN_0F, }, [ALC260_FIXUP_GPIO1] = { .type = ALC_FIXUP_VERBS, @@ -4971,8 +4969,8 @@ static const struct alc_fixup alc260_fixups[] = { [ALC260_FIXUP_REPLACER] = { .type = ALC_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { - { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 }, - { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 }, + { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 }, + { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 }, { } }, .chained = true,