diff options
Diffstat (limited to 'drivers')
38 files changed, 259 insertions, 122 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 06ed6b4e7df5..3719c94be19c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev, int loading = simple_strtol(buf, NULL, 10); int i; + mutex_lock(&fw_lock); + + if (!fw_priv->fw) + goto out; + switch (loading) { case 1: - mutex_lock(&fw_lock); - if (!fw_priv->fw) { - mutex_unlock(&fw_lock); - break; - } firmware_free_data(fw_priv->fw); memset(fw_priv->fw, 0, sizeof(struct firmware)); /* If the pages are not owned by 'struct firmware' */ @@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev, fw_priv->page_array_size = 0; fw_priv->nr_pages = 0; set_bit(FW_STATUS_LOADING, &fw_priv->status); - mutex_unlock(&fw_lock); break; case 0: if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) { @@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev, fw_load_abort(fw_priv); break; } - +out: + mutex_unlock(&fw_lock); return count; } diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 30a3085d3354..fda56bde36b8 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h @@ -18,6 +18,9 @@ void bcma_bus_unregister(struct bcma_bus *bus); int __init bcma_bus_early_register(struct bcma_bus *bus, struct bcma_device *core_cc, struct bcma_device *core_mips); +#ifdef CONFIG_PM +int bcma_bus_resume(struct bcma_bus *bus); +#endif /* scan.c */ int bcma_bus_scan(struct bcma_bus *bus); diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index 1b51d8b7ac80..990f5a8e9c19 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c @@ -224,6 +224,41 @@ static void bcma_host_pci_remove(struct pci_dev *dev) pci_set_drvdata(dev, NULL); } +#ifdef CONFIG_PM +static int bcma_host_pci_suspend(struct pci_dev *dev, pm_message_t state) +{ + /* Host specific */ + pci_save_state(dev); + pci_disable_device(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); + + return 0; +} + +static int bcma_host_pci_resume(struct pci_dev *dev) +{ + struct bcma_bus *bus = pci_get_drvdata(dev); + int err; + + /* Host specific */ + pci_set_power_state(dev, 0); + err = pci_enable_device(dev); + if (err) + return err; + pci_restore_state(dev); + + /* Bus specific */ + err = bcma_bus_resume(bus); + if (err) + return err; + + return 0; +} +#else /* CONFIG_PM */ +# define bcma_host_pci_suspend NULL +# define bcma_host_pci_resume NULL +#endif /* CONFIG_PM */ + static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, @@ -239,6 +274,8 @@ static struct pci_driver bcma_pci_bridge_driver = { .id_table = bcma_pci_bridge_tbl, .probe = bcma_host_pci_probe, .remove = bcma_host_pci_remove, + .suspend = bcma_host_pci_suspend, + .resume = bcma_host_pci_resume, }; int __init bcma_host_pci_init(void) diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 70c84b951098..10f92b371e58 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -240,6 +240,22 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, return 0; } +#ifdef CONFIG_PM +int bcma_bus_resume(struct bcma_bus *bus) +{ + struct bcma_device *core; + + /* Init CC core */ + core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); + if (core) { + bus->drv_cc.setup_done = false; + bcma_core_chipcommon_init(&bus->drv_cc); + } + + return 0; +} +#endif + int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) { drv->drv.name = drv->name; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 0c048dd8013f..d2d0a2a9676d 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -62,6 +62,14 @@ struct hv_device_info { struct hv_dev_port_info outbound; }; +static int vmbus_exists(void) +{ + if (hv_acpi_dev == NULL) + return -ENODEV; + + return 0; +} + static void get_channel_info(struct hv_device *device, struct hv_device_info *info) @@ -590,6 +598,10 @@ int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, c pr_info("registering driver %s\n", hv_driver->name); + ret = vmbus_exists(); + if (ret < 0) + return ret; + hv_driver->driver.name = hv_driver->name; hv_driver->driver.owner = owner; hv_driver->driver.mod_name = mod_name; @@ -614,8 +626,8 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver) { pr_info("unregistering driver %s\n", hv_driver->name); - driver_unregister(&hv_driver->driver); - + if (!vmbus_exists()) + driver_unregister(&hv_driver->driver); } EXPORT_SYMBOL_GPL(vmbus_driver_unregister); @@ -776,6 +788,7 @@ static int __init hv_acpi_init(void) cleanup: acpi_bus_unregister_driver(&vmbus_acpi_driver); + hv_acpi_dev = NULL; return ret; } diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 254f1649c734..e3db8ef4fe4e 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -241,11 +241,24 @@ static struct ib_qp *idr_read_qp(int qp_handle, struct ib_ucontext *context) return idr_read_obj(&ib_uverbs_qp_idr, qp_handle, context, 0); } +static struct ib_qp *idr_write_qp(int qp_handle, struct ib_ucontext *context) +{ + struct ib_uobject *uobj; + + uobj = idr_write_uobj(&ib_uverbs_qp_idr, qp_handle, context); + return uobj ? uobj->object : NULL; +} + static void put_qp_read(struct ib_qp *qp) { put_uobj_read(qp->uobject); } +static void put_qp_write(struct ib_qp *qp) +{ + put_uobj_write(qp->uobject); +} + static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context) { return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0); @@ -2375,7 +2388,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2404,7 +2417,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, kfree(mcast); out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } @@ -2422,7 +2435,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; - qp = idr_read_qp(cmd.qp_handle, file->ucontext); + qp = idr_write_qp(cmd.qp_handle, file->ucontext); if (!qp) return -EINVAL; @@ -2441,7 +2454,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, } out_put: - put_qp_read(qp); + put_qp_write(qp); return ret ? ret : in_len; } diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 781a802a321f..4f18e2d332df 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2076,9 +2076,11 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd) static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd, u32 updegr, u32 egrhd, u32 npkts) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_6120_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index 439d3c503cd5..7ec4048731c9 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -2725,9 +2725,11 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what) static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd, u32 updegr, u32 egrhd, u32 npkts) { - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 1d5895941e19..5a070e8c983d 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -4082,10 +4082,12 @@ static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd, */ if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT) adjust_rcv_timeout(rcd, npkts); - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); - qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); if (updegr) qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt); + mmiowb(); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt); + mmiowb(); } static u32 qib_7322_hdrqempty(struct qib_ctxtdata *rcd) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 7f8756825b8a..e58aa2b7a153 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1822,7 +1822,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) "but new slave device does not support netpoll.\n", bond_dev->name); res = -EBUSY; - goto err_close; + goto err_detach; } } #endif @@ -1831,7 +1831,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) res = bond_create_slave_symlinks(bond_dev, slave_dev); if (res) - goto err_close; + goto err_detach; res = netdev_rx_handler_register(slave_dev, bond_handle_frame, new_slave); @@ -1852,6 +1852,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) err_dest_symlinks: bond_destroy_slave_symlinks(bond_dev, slave_dev); +err_detach: + write_lock_bh(&bond->lock); + bond_detach_slave(bond, new_slave); + write_unlock_bh(&bond->lock); + err_close: dev_close(slave_dev); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index e95f0e60a9bc..dd2625a3371a 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -376,7 +376,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) skb_pull(skb, (size + 1) & 0xfffe); - if (skb->len == 0) + if (skb->len < sizeof(header)) break; head = (u8 *) skb->data; diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 69d5f85d11e2..8b9ff2815784 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -809,7 +809,7 @@ struct iwl_qosparam_cmd { #define IWLAGN_STATION_COUNT 16 #define IWL_INVALID_STATION 255 -#define IWL_MAX_TID_COUNT 9 +#define IWL_MAX_TID_COUNT 8 #define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) #define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 2b6756e8b8f9..5c2928182892 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -219,9 +219,7 @@ struct iwl_trans_pcie { /* INT ICT Table */ __le32 *ict_tbl; - void *ict_tbl_vir; dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; int ict_index; u32 inta; bool use_ict; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 374c68cc1d70..1920237f13ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1136,7 +1136,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) * ICT functions * ******************************************************************************/ -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) + +/* a device (PCI-E) page is 4096 bytes long */ +#define ICT_SHIFT 12 +#define ICT_SIZE (1 << ICT_SHIFT) +#define ICT_COUNT (ICT_SIZE / sizeof(u32)) /* Free dram table */ void iwl_free_isr_ict(struct iwl_trans *trans) @@ -1144,21 +1148,19 @@ void iwl_free_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (trans_pcie->ict_tbl_vir) { - dma_free_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - trans_pcie->ict_tbl_vir, + if (trans_pcie->ict_tbl) { + dma_free_coherent(bus(trans)->dev, ICT_SIZE, + trans_pcie->ict_tbl, trans_pcie->ict_tbl_dma); - trans_pcie->ict_tbl_vir = NULL; - memset(&trans_pcie->ict_tbl_dma, 0, - sizeof(trans_pcie->ict_tbl_dma)); - memset(&trans_pcie->aligned_ict_tbl_dma, 0, - sizeof(trans_pcie->aligned_ict_tbl_dma)); + trans_pcie->ict_tbl = NULL; + trans_pcie->ict_tbl_dma = 0; } } -/* allocate dram shared table it is a PAGE_SIZE aligned +/* + * allocate dram shared table, it is an aligned memory + * block of ICT_SIZE. * also reset all data related to ICT table interrupt. */ int iwl_alloc_isr_ict(struct iwl_trans *trans) @@ -1166,36 +1168,26 @@ int iwl_alloc_isr_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - /* allocate shrared data table */ - trans_pcie->ict_tbl_vir = - dma_alloc_coherent(bus(trans)->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &trans_pcie->ict_tbl_dma, GFP_KERNEL); - if (!trans_pcie->ict_tbl_vir) + trans_pcie->ict_tbl = + dma_alloc_coherent(bus(trans)->dev, ICT_SIZE, + &trans_pcie->ict_tbl_dma, + GFP_KERNEL); + if (!trans_pcie->ict_tbl) return -ENOMEM; - /* align table to PAGE_SIZE boundary */ - trans_pcie->aligned_ict_tbl_dma = - ALIGN(trans_pcie->ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(trans, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)trans_pcie->ict_tbl_dma, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + /* just an API sanity check ... it is guaranteed to be aligned */ + if (WARN_ON(trans_pcie->ict_tbl_dma & (ICT_SIZE - 1))) { + iwl_free_isr_ict(trans); + return -EINVAL; + } - trans_pcie->ict_tbl = trans_pcie->ict_tbl_vir + - (trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma); + IWL_DEBUG_ISR(trans, "ict dma addr %Lx\n", + (unsigned long long)trans_pcie->ict_tbl_dma); - IWL_DEBUG_ISR(trans, "ict vir addr %p vir aligned %p diff %d\n", - trans_pcie->ict_tbl, trans_pcie->ict_tbl_vir, - (int)(trans_pcie->aligned_ict_tbl_dma - - trans_pcie->ict_tbl_dma)); + IWL_DEBUG_ISR(trans, "ict vir addr %p\n", trans_pcie->ict_tbl); /* reset table and index to all 0 */ - memset(trans_pcie->ict_tbl_vir, 0, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); trans_pcie->ict_index = 0; /* add periodic RX interrupt */ @@ -1213,23 +1205,20 @@ int iwl_reset_ict(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - if (!trans_pcie->ict_tbl_vir) + if (!trans_pcie->ict_tbl) return 0; spin_lock_irqsave(&trans->shrd->lock, flags); iwl_disable_interrupts(trans); - memset(&trans_pcie->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); + memset(trans_pcie->ict_tbl, 0, ICT_SIZE); - val = trans_pcie->aligned_ict_tbl_dma >> PAGE_SHIFT; + val = trans_pcie->ict_tbl_dma >> ICT_SHIFT; val |= CSR_DRAM_INT_TBL_ENABLE; val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, - (unsigned long long)trans_pcie->aligned_ict_tbl_dma); + IWL_DEBUG_ISR(trans, "CSR_DRAM_INT_TBL_REG =0x%x\n", val); iwl_write32(bus(trans), CSR_DRAM_INT_TBL_REG, val); trans_pcie->use_ict = true; diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index a7f1ab28940d..db64ef154325 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -728,9 +728,11 @@ static void lbs_scan_worker(struct work_struct *work) le16_to_cpu(scan_cmd->hdr.size), lbs_ret_scan, 0); - if (priv->scan_channel >= priv->scan_req->n_channels) + if (priv->scan_channel >= priv->scan_req->n_channels) { /* Mark scan done */ + cancel_delayed_work(&priv->scan_work); lbs_scan_done(priv); + } /* Restart network */ if (carrier) @@ -759,12 +761,12 @@ static void _internal_start_scan(struct lbs_private *priv, bool internal, request->n_ssids, request->n_channels, request->ie_len); priv->scan_channel = 0; - queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(50)); - priv->scan_req = request; priv->internal_scan = internal; + queue_delayed_work(priv->work_thread, &priv->scan_work, + msecs_to_jiffies(50)); + lbs_deb_leave(LBS_DEB_CFG80211); } diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 377876315b8d..3265b341e96d 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -976,6 +976,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x13b1, 0x0031) }, { USB_DEVICE(0x1737, 0x0070) }, { USB_DEVICE(0x1737, 0x0071) }, + { USB_DEVICE(0x1737, 0x0077) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0162) }, { USB_DEVICE(0x0789, 0x0163) }, @@ -1171,7 +1172,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1740, 0x0605) }, { USB_DEVICE(0x1740, 0x0615) }, /* Linksys */ - { USB_DEVICE(0x1737, 0x0077) }, { USB_DEVICE(0x1737, 0x0078) }, /* Logitec */ { USB_DEVICE(0x0789, 0x0168) }, diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index 681337914976..a7b327d2e41b 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c @@ -347,6 +347,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 3; for (i = 0; i < burst_len; i++) { + if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); @@ -358,6 +361,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_ptr += 4; dest_addr += 4; } + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; } /* @@ -369,6 +375,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) */ nvs_ptr = (u8 *)wl->nvs + ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4); + + if (nvs_ptr >= (u8 *) wl->nvs + nvs_len) + goto out_badnvs; + nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ @@ -384,6 +394,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) kfree(nvs_aligned); return 0; + +out_badnvs: + wl1271_error("nvs data is malformed"); + return -EILSEQ; } static void wl1271_boot_enable_interrupts(struct wl1271 *wl) diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index a52299e548fa..54a0d667ff43 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c @@ -120,6 +120,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from INI out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -143,6 +148,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); @@ -162,6 +173,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) if (!wl->nvs) return -ENODEV; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from ini out of bounds"); + return -EINVAL; + } + gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); if (!gen_parms) return -ENOMEM; @@ -186,6 +202,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) gp->tx_bip_fem_manufacturer = gen_parms->general_params.tx_bip_fem_manufacturer; + if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) { + wl1271_warning("FEM index from FW out of bounds"); + ret = -EINVAL; + goto out; + } + wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c index 4ae8effaee22..abfb120df118 100644 --- a/drivers/net/wireless/wl12xx/testmode.c +++ b/drivers/net/wireless/wl12xx/testmode.c @@ -36,6 +36,7 @@ enum wl1271_tm_commands { WL1271_TM_CMD_TEST, WL1271_TM_CMD_INTERROGATE, WL1271_TM_CMD_CONFIGURE, + WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ WL1271_TM_CMD_SET_PLT_MODE, WL1271_TM_CMD_RECOVER, diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 4c823f341d98..90c8e3a49220 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -212,8 +212,9 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) { struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); unsigned int mode; + unsigned long flags; - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); /* Disable interrupts */ UART_PUT_IDR(port, atmel_port->tx_done_mask); @@ -244,7 +245,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) /* Enable interrupts */ UART_PUT_IER(port, atmel_port->tx_done_mask); - spin_unlock(&port->lock); + spin_unlock_irqrestore(&port->lock, flags); } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index a8078d0638fa..e61d9c43e985 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -554,10 +554,18 @@ static void acm_port_down(struct acm *acm) static void acm_tty_hangup(struct tty_struct *tty) { - struct acm *acm = tty->driver_data; - tty_port_hangup(&acm->port); + struct acm *acm; + mutex_lock(&open_mutex); + acm = tty->driver_data; + + if (!acm) + goto out; + + tty_port_hangup(&acm->port); acm_port_down(acm); + +out: mutex_unlock(&open_mutex); } @@ -1183,6 +1191,8 @@ made_compressed_probe: i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); if (i < 0) { kfree(acm->country_codes); + acm->country_codes = NULL; + acm->country_code_size = 0; goto skip_countries; } @@ -1191,6 +1201,8 @@ made_compressed_probe: if (i < 0) { device_remove_file(&intf->dev, &dev_attr_wCountryCodes); kfree(acm->country_codes); + acm->country_codes = NULL; + acm->country_code_size = 0; goto skip_countries; } } diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e3beaf229ee3..7abf06004b7a 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -249,7 +249,8 @@ static struct async *alloc_async(unsigned int numisoframes) static void free_async(struct async *as) { put_pid(as->pid); - put_cred(as->cred); + if (as->cred) + put_cred(as->cred); kfree(as->urb->transfer_buffer); kfree(as->urb->setup_packet); usb_free_urb(as->urb); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 8a5c16c76de7..505265e60219 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1412,11 +1412,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, ret = -EAGAIN; else urb->transfer_flags |= URB_DMA_MAP_SG; - if (n != urb->num_sgs) { - urb->num_sgs = n; + urb->num_mapped_sgs = n; + if (n != urb->num_sgs) urb->transfer_flags |= URB_DMA_SG_COMBINED; - } } else if (urb->sg) { struct scatterlist *sg = urb->sg; urb->transfer_dma = dma_map_page( diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index ecf12e15a7ef..4c65eb6a867a 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -117,9 +117,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x06a3, 0x0006), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, - /* Guillemot Webcam Hercules Dualpix Exchange*/ + /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */ { USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Guillemot Webcam Hercules Dualpix Exchange*/ + { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/host/ehci-pxa168.c b/drivers/usb/host/ehci-pxa168.c index ac0c16e8f539..8d0e7a22e711 100644 --- a/drivers/usb/host/ehci-pxa168.c +++ b/drivers/usb/host/ehci-pxa168.c @@ -299,7 +299,7 @@ static int __devinit ehci_pxa168_drv_probe(struct platform_device *pdev) ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs + 0x100; ehci->regs = hcd->regs + 0x100 + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); hcd->has_tt = 1; ehci->sbrn = 0x20; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 4e4066c35a09..fef1db3da37f 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -647,7 +647,7 @@ qh_urb_transaction ( /* * data transfer stage: buffer setup */ - i = urb->num_sgs; + i = urb->num_mapped_sgs; if (len > 0 && i > 0) { sg = urb->sg; buf = sg_dma_address(sg); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index f6ca80ee4cec..d2c6f5ac4626 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -943,7 +943,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, if (usb_pipein(urb->pipe)) status |= TD_CTRL_SPD; - i = urb->num_sgs; + i = urb->num_mapped_sgs; if (len > 0 && i > 0) { sg = urb->sg; data = sg_dma_address(sg); diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index a403b53e86b9..76083ae92138 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -443,7 +443,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u remaining = urb->transfer_buffer_length; - for_each_sg(urb->sg, sg, urb->num_sgs, i) { + for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { dma_addr_t dma_addr; size_t dma_remaining; dma_addr_t sp, ep; @@ -561,7 +561,7 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset, remaining = urb->transfer_buffer_length; - for_each_sg(urb->sg, sg, urb->num_sgs, i) { + for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) { size_t len; size_t sg_remaining; void *orig; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9f1d4b15d818..d28c5865f3ef 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2561,7 +2561,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) struct scatterlist *sg; sg = NULL; - num_sgs = urb->num_sgs; + num_sgs = urb->num_mapped_sgs; temp = urb->transfer_buffer_length; xhci_dbg(xhci, "count sg list trbs: \n"); @@ -2745,7 +2745,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, return -EINVAL; num_trbs = count_sg_trbs_needed(xhci, urb); - num_sgs = urb->num_sgs; + num_sgs = urb->num_mapped_sgs; total_packet_count = roundup(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a1afb7c39f7e..b33f0598ccfe 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1620,6 +1620,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, /* FIXME: can we allocate more resources for the HC? */ break; case COMP_BW_ERR: + case COMP_2ND_BW_ERR: dev_warn(&udev->dev, "Not enough bandwidth " "for new device state.\n"); ret = -ENOSPC; @@ -2796,8 +2797,7 @@ static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci, if (ret < 0) return ret; - max_streams = USB_SS_MAX_STREAMS( - eps[i]->ss_ep_comp.bmAttributes); + max_streams = usb_ss_max_streams(&eps[i]->ss_ep_comp); if (max_streams < (*num_streams - 1)) { xhci_dbg(xhci, "Ep 0x%x only supports %u stream IDs.\n", eps[i]->desc.bEndpointAddress, diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 3c8fbd2772ea..09eda3a8e51c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1033,7 +1033,6 @@ struct xhci_transfer_event { /* Invalid Stream ID Error */ #define COMP_STRID_ERR 34 /* Secondary Bandwidth Error - may be returned by a Configure Endpoint cmd */ -/* FIXME - check for this */ #define COMP_2ND_BW_ERR 35 /* Split Transaction Error */ #define COMP_SPLIT_ERR 36 diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c index fe1d44319d0a..8f725f651915 100644 --- a/drivers/usb/misc/isight_firmware.c +++ b/drivers/usb/misc/isight_firmware.c @@ -55,8 +55,9 @@ static int isight_firmware_load(struct usb_interface *intf, ptr = firmware->data; + buf[0] = 0x01; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "Failed to initialise isight firmware loader\n"); @@ -100,8 +101,9 @@ static int isight_firmware_load(struct usb_interface *intf, } } + buf[0] = 0x00; if (usb_control_msg - (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1, + (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1, 300) != 1) { printk(KERN_ERR "isight firmware loading completion failed\n"); ret = -ENODEV; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index b63ab1570103..920f04e5f3a8 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2012,8 +2012,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) if (status < 0) goto fail3; - pm_runtime_put(musb->controller); - status = musb_init_debugfs(musb); if (status < 0) goto fail4; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index fd67cc53545b..a1a324b30d2d 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -92,6 +92,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 60f38d5e64fc..0a8c1e64b247 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -315,7 +315,7 @@ static int omninet_write_room(struct tty_struct *tty) int room = 0; /* Default: no room */ /* FIXME: no consistent locking for write_urb_busy */ - if (wport->write_urb_busy) + if (!wport->write_urb_busy) room = wport->bulk_out_size - OMNINET_HEADERLEN; dbg("%s - returns %d", __func__, room); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6dd64534fad0..c96b6b6509fb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -476,6 +476,10 @@ static void option_instat_callback(struct urb *urb); #define VIETTEL_VENDOR_ID 0x2262 #define VIETTEL_PRODUCT_VT1000 0x0002 +/* ZD Incorporated */ +#define ZD_VENDOR_ID 0x0685 +#define ZD_PRODUCT_7000 0x7000 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1178,6 +1182,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c325e69415a1..9e069efeefee 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -1073,6 +1073,7 @@ static struct usb_driver usb_storage_driver = { .id_table = usb_storage_usb_ids, .supports_autosuspend = 1, .soft_unbind = 1, + .no_dynamic_id = 1, }; static int __init usb_stor_init(void) diff --git a/drivers/video/offb.c b/drivers/video/offb.c index cb163a5397be..3251a0236d56 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -100,36 +100,32 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info) { struct offb_par *par = (struct offb_par *) info->par; - int i, depth; - u32 *pal = info->pseudo_palette; - - depth = info->var.bits_per_pixel; - if (depth == 16) - depth = (info->var.green.length == 5) ? 15 : 16; - - if (regno > 255 || - (depth == 16 && regno > 63) || - (depth == 15 && regno > 31)) - return 1; - - if (regno < 16) { - switch (depth) { - case 15: - pal[regno] = (regno << 10) | (regno << 5) | regno; - break; - case 16: - pal[regno] = (regno << 11) | (regno << 5) | regno; - break; - case 24: - pal[regno] = (regno << 16) | (regno << 8) | regno; - break; - case 32: - i = (regno << 8) | regno; - pal[regno] = (i << 16) | i; - break; + + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *pal = info->pseudo_palette; + u32 cr = red >> (16 - info->var.red.length); + u32 cg = green >> (16 - info->var.green.length); + u32 cb = blue >> (16 - info->var.blue.length); + u32 value; + + if (regno >= 16) + return -EINVAL; + + value = (cr << info->var.red.offset) | + (cg << info->var.green.offset) | + (cb << info->var.blue.offset); + if (info->var.transp.length > 0) { + u32 mask = (1 << info->var.transp.length) - 1; + mask <<= info->var.transp.offset; + value |= mask; } + pal[regno] = value; + return 0; } + if (regno > 255) + return -EINVAL; + red >>= 8; green >>= 8; blue >>= 8; @@ -381,7 +377,7 @@ static void __init offb_init_fb(const char *name, const char *full_name, int pitch, unsigned long address, int foreign_endian, struct device_node *dp) { - unsigned long res_size = pitch * height * (depth + 7) / 8; + unsigned long res_size = pitch * height; struct offb_par *par = &default_par; unsigned long res_start = address; struct fb_fix_screeninfo *fix; |