diff options
Diffstat (limited to 'drivers')
150 files changed, 3650 insertions, 953 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 328826381a2d..b8d96ce37fc9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -260,6 +260,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -379,6 +380,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ { PCI_DEVICE(0x1b4b, 0x9123), + .class = PCI_CLASS_STORAGE_SATA_AHCI, + .class_mask = 0xffffff, .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ /* Promise */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a31fe96f7de6..d4e52e214859 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4138,6 +4138,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { * device and controller are SATA. */ { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, /* End Marker */ { } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5defc74973d7..600f6353ecf8 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1099,9 +1099,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, struct request_queue *q = sdev->request_queue; void *buf; - /* set the min alignment and padding */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_DMA_PAD_SZ - 1); + sdev->sector_size = ATA_SECT_SIZE; + + /* set DMA padding */ blk_queue_update_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1); @@ -1115,13 +1115,25 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { - /* ATA devices must be sector aligned */ sdev->sector_size = ata_id_logical_sector_size(dev->id); - blk_queue_update_dma_alignment(sdev->request_queue, - sdev->sector_size - 1); sdev->manage_start_stop = 1; } + /* + * ata_pio_sectors() expects buffer for each sector to not cross + * page boundary. Enforce it by requiring buffers to be sector + * aligned, which works iff sector_size is not larger than + * PAGE_SIZE. ATAPI devices also need the alignment as + * IDENTIFY_PACKET is executed as ATA_PROT_PIO. + */ + if (sdev->sector_size > PAGE_SIZE) + ata_dev_printk(dev, KERN_WARNING, + "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", + sdev->sector_size); + + blk_queue_update_dma_alignment(sdev->request_queue, + sdev->sector_size - 1); + if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index d7e57db36bc8..538ec38ba995 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -25,7 +25,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.6.9" +#define DRV_VERSION "0.6.10" struct hpt_clock { u8 xfer_mode; @@ -160,8 +160,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, while (list[i] != NULL) { if (!strcmp(list[i], model_num)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); + pr_warning(DRV_NAME ": %s is not supported for %s.\n", + modestr, list[i]); return 1; } i++; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index efdd18bc8663..4c5b5183225e 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.18" +#define DRV_VERSION "0.6.22" struct hpt_clock { u8 xfer_speed; @@ -229,8 +229,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, while (list[i] != NULL) { if (!strcmp(list[i], model_num)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); + pr_warning(DRV_NAME ": %s is not supported for %s.\n", + modestr, list[i]); return 1; } i++; @@ -642,7 +642,6 @@ static struct ata_port_operations hpt372_port_ops = { static struct ata_port_operations hpt374_fn1_port_ops = { .inherits = &hpt372_port_ops, .cable_detect = hpt374_fn1_cable_detect, - .prereset = hpt37x_pre_reset, }; /** @@ -803,7 +802,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = ATA_UDMA6, .port_ops = &hpt302_port_ops }; - /* HPT374 - UDMA100, function 1 uses different prereset method */ + /* HPT374 - UDMA100, function 1 uses different cable_detect method */ static const struct ata_port_info info_hpt374_fn0 = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, @@ -838,7 +837,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (rc) return rc; - if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { + switch (dev->device) { + case PCI_DEVICE_ID_TTI_HPT366: /* May be a later chip in disguise. Check */ /* Older chips are in the HPT366 driver. Ignore them */ if (rev < 3) @@ -863,54 +863,50 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) chip_table = &hpt372; break; default: - printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype, " + pr_err(DRV_NAME ": Unknown HPT366 subtype, " "please report (%d).\n", rev); return -ENODEV; } - } else { - switch (dev->device) { - case PCI_DEVICE_ID_TTI_HPT372: - /* 372N if rev >= 2 */ - if (rev >= 2) - return -ENODEV; - ppi[0] = &info_hpt372; - chip_table = &hpt372a; - break; - case PCI_DEVICE_ID_TTI_HPT302: - /* 302N if rev > 1 */ - if (rev > 1) - return -ENODEV; - ppi[0] = &info_hpt302; - /* Check this */ - chip_table = &hpt302; - break; - case PCI_DEVICE_ID_TTI_HPT371: - if (rev > 1) - return -ENODEV; - ppi[0] = &info_hpt302; - chip_table = &hpt371; - /* - * Single channel device, master is not present - * but the BIOS (or us for non x86) must mark it - * absent - */ - pci_read_config_byte(dev, 0x50, &mcr1); - mcr1 &= ~0x04; - pci_write_config_byte(dev, 0x50, mcr1); - break; - case PCI_DEVICE_ID_TTI_HPT374: - chip_table = &hpt374; - if (!(PCI_FUNC(dev->devfn) & 1)) - *ppi = &info_hpt374_fn0; - else - *ppi = &info_hpt374_fn1; - break; - default: - printk(KERN_ERR - "pata_hpt37x: PCI table is bogus, please report (%d).\n", - dev->device); - return -ENODEV; - } + break; + case PCI_DEVICE_ID_TTI_HPT372: + /* 372N if rev >= 2 */ + if (rev >= 2) + return -ENODEV; + ppi[0] = &info_hpt372; + chip_table = &hpt372a; + break; + case PCI_DEVICE_ID_TTI_HPT302: + /* 302N if rev > 1 */ + if (rev > 1) + return -ENODEV; + ppi[0] = &info_hpt302; + /* Check this */ + chip_table = &hpt302; + break; + case PCI_DEVICE_ID_TTI_HPT371: + if (rev > 1) + return -ENODEV; + ppi[0] = &info_hpt302; + chip_table = &hpt371; + /* + * Single channel device, master is not present but the BIOS + * (or us for non x86) must mark it absent + */ + pci_read_config_byte(dev, 0x50, &mcr1); + mcr1 &= ~0x04; + pci_write_config_byte(dev, 0x50, mcr1); + break; + case PCI_DEVICE_ID_TTI_HPT374: + chip_table = &hpt374; + if (!(PCI_FUNC(dev->devfn) & 1)) + *ppi = &info_hpt374_fn0; + else + *ppi = &info_hpt374_fn1; + break; + default: + pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n", + dev->device); + return -ENODEV; } /* Ok so this is a chip we support */ @@ -957,8 +953,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) u8 sr; u32 total = 0; - printk(KERN_WARNING - "pata_hpt37x: BIOS has not set timing clocks.\n"); + pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n"); /* This is the process the HPT371 BIOS is reported to use */ for (i = 0; i < 128; i++) { @@ -1014,7 +1009,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) (f_high << 16) | f_low | 0x100); } if (adjust == 8) { - printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); + pr_err(DRV_NAME ": DPLL did not stabilize!\n"); return -ENODEV; } if (dpll == 3) @@ -1022,8 +1017,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) else private_data = (void *)hpt37x_timings_50; - printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", - MHz[clock_slot], MHz[dpll]); + pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n", + MHz[clock_slot], MHz[dpll]); } else { private_data = (void *)chip_table->clocks[clock_slot]; /* @@ -1036,8 +1031,9 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) ppi[0] = &info_hpt370_33; if (clock_slot < 2 && ppi[0] == &info_hpt370a) ppi[0] = &info_hpt370a_33; - printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", - chip_table->name, MHz[clock_slot]); + + pr_info(DRV_NAME ": %s using %dMHz bus clock.\n", + chip_table->name, MHz[clock_slot]); } /* Now kick off ATA set up */ diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index d2239bbdb798..eca68caf5f46 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -25,7 +25,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3.13" +#define DRV_VERSION "0.3.14" enum { HPT_PCI_FAST = (1 << 31), @@ -418,7 +418,7 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev) u16 sr; u32 total = 0; - printk(KERN_WARNING "pata_hpt3x2n: BIOS clock data not set.\n"); + pr_warning(DRV_NAME ": BIOS clock data not set.\n"); /* This is the process the HPT371 BIOS is reported to use */ for (i = 0; i < 128; i++) { @@ -528,8 +528,7 @@ hpt372n: ppi[0] = &info_hpt372n; break; default: - printk(KERN_ERR - "pata_hpt3x2n: PCI table is bogus please report (%d).\n", + pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n", dev->device); return -ENODEV; } @@ -579,12 +578,11 @@ hpt372n: pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); } if (adjust == 8) { - printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n"); + pr_err(DRV_NAME ": DPLL did not stabilize!\n"); return -ENODEV; } - printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n", - pci_mhz); + pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz); /* * Set our private data up. We only need a few flags diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 8cc536e49a0a..d7d8026cde99 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = { }; static struct ata_port_operations mpc52xx_ata_port_ops = { - .inherits = &ata_sff_port_ops, + .inherits = &ata_bmdma_port_ops, .sff_dev_select = mpc52xx_ata_dev_select, .set_piomode = mpc52xx_ata_set_piomode, .set_dmamode = mpc52xx_ata_set_dmamode, diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index bca9cb89a118..487a54739854 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -151,7 +151,7 @@ static int fetch_stats(struct atm_dev *dev,struct idt77105_stats __user *arg,int spin_unlock_irqrestore(&idt77105_priv_lock, flags); if (arg == NULL) return 0; - return copy_to_user(arg, &PRIV(dev)->stats, + return copy_to_user(arg, &stats, sizeof(struct idt77105_stats)) ? -EFAULT : 0; } diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 656493a5e073..42615b419dfb 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -407,12 +407,15 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto out; } + /* Maybe the parent is now able to suspend. */ if (parent && !parent->power.ignore_children && !dev->power.irq_safe) { - spin_unlock_irq(&dev->power.lock); + spin_unlock(&dev->power.lock); - pm_request_idle(parent); + spin_lock(&parent->power.lock); + rpm_idle(parent, RPM_ASYNC); + spin_unlock(&parent->power.lock); - spin_lock_irq(&dev->power.lock); + spin_lock(&dev->power.lock); } out: diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 949ed09c6361..a126e614601f 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -47,46 +47,40 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); #define USB_REQ_DFU_DNLOAD 1 #define BULK_SIZE 4096 -struct ath3k_data { - struct usb_device *udev; - u8 *fw_data; - u32 fw_size; - u32 fw_sent; -}; - -static int ath3k_load_firmware(struct ath3k_data *data, - unsigned char *firmware, - int count) +static int ath3k_load_firmware(struct usb_device *udev, + const struct firmware *firmware) { u8 *send_buf; int err, pipe, len, size, sent = 0; + int count = firmware->size; - BT_DBG("ath3k %p udev %p", data, data->udev); + BT_DBG("udev %p", udev); - pipe = usb_sndctrlpipe(data->udev, 0); + pipe = usb_sndctrlpipe(udev, 0); - if ((usb_control_msg(data->udev, pipe, + send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); + if (!send_buf) { + BT_ERR("Can't allocate memory chunk for firmware"); + return -ENOMEM; + } + + memcpy(send_buf, firmware->data, 20); + if ((err = usb_control_msg(udev, pipe, USB_REQ_DFU_DNLOAD, USB_TYPE_VENDOR, 0, 0, - firmware, 20, USB_CTRL_SET_TIMEOUT)) < 0) { + send_buf, 20, USB_CTRL_SET_TIMEOUT)) < 0) { BT_ERR("Can't change to loading configuration err"); - return -EBUSY; + goto error; } sent += 20; count -= 20; - send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC); - if (!send_buf) { - BT_ERR("Can't allocate memory chunk for firmware"); - return -ENOMEM; - } - while (count) { size = min_t(uint, count, BULK_SIZE); - pipe = usb_sndbulkpipe(data->udev, 0x02); - memcpy(send_buf, firmware + sent, size); + pipe = usb_sndbulkpipe(udev, 0x02); + memcpy(send_buf, firmware->data + sent, size); - err = usb_bulk_msg(data->udev, pipe, send_buf, size, + err = usb_bulk_msg(udev, pipe, send_buf, size, &len, 3000); if (err || (len != size)) { @@ -112,57 +106,28 @@ static int ath3k_probe(struct usb_interface *intf, { const struct firmware *firmware; struct usb_device *udev = interface_to_usbdev(intf); - struct ath3k_data *data; - int size; BT_DBG("intf %p id %p", intf, id); if (intf->cur_altsetting->desc.bInterfaceNumber != 0) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->udev = udev; - if (request_firmware(&firmware, "ath3k-1.fw", &udev->dev) < 0) { - kfree(data); return -EIO; } - size = max_t(uint, firmware->size, 4096); - data->fw_data = kmalloc(size, GFP_KERNEL); - if (!data->fw_data) { + if (ath3k_load_firmware(udev, firmware)) { release_firmware(firmware); - kfree(data); - return -ENOMEM; - } - - memcpy(data->fw_data, firmware->data, firmware->size); - data->fw_size = firmware->size; - data->fw_sent = 0; - release_firmware(firmware); - - usb_set_intfdata(intf, data); - if (ath3k_load_firmware(data, data->fw_data, data->fw_size)) { - usb_set_intfdata(intf, NULL); - kfree(data->fw_data); - kfree(data); return -EIO; } + release_firmware(firmware); return 0; } static void ath3k_disconnect(struct usb_interface *intf) { - struct ath3k_data *data = usb_get_intfdata(intf); - BT_DBG("ath3k_disconnect intf %p", intf); - - kfree(data->fw_data); - kfree(data); } static struct usb_driver ath3k_driver = { diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 2aef5cd3acf5..49e5e99917e2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -6310,6 +6310,9 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) static bool apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; + /* Dell Precision M6300 * DCB entry 2: 02025312 00000010 * DCB entry 3: 02026312 00000020 @@ -6327,6 +6330,18 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) return false; } + /* GeForce3 Ti 200 + * + * DCB reports an LVDS output that should be TMDS: + * DCB entry 1: f2005014 ffffffff + */ + if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { + if (*conn == 0xf2005014 && *conf == 0xffffffff) { + fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1); + return false; + } + } + return true; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 01bffc4412d2..9821fcacc3d2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -848,9 +848,6 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_fence *fence); extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -/* nvc0_vram.c */ -extern const struct ttm_mem_type_manager_func nvc0_vram_manager; - /* nouveau_notifier.c */ extern int nouveau_notifier_init_channel(struct nouveau_channel *); extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 7ecc4adc1e45..8d9968e1cba8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -265,8 +265,8 @@ nouveau_temp_probe_i2c(struct drm_device *dev) struct i2c_board_info info[] = { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, { I2C_BOARD_INFO("w83781d", 0x2d) }, - { I2C_BOARD_INFO("f75375", 0x2e) }, { I2C_BOARD_INFO("adt7473", 0x2e) }, + { I2C_BOARD_INFO("f75375", 0x2e) }, { I2C_BOARD_INFO("lm99", 0x4c) }, { } }; diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 2d7ea75a09d4..37e21d2be95b 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -256,6 +256,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; unsigned long flags; @@ -265,6 +266,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) return; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pfifo->reassign(dev, false); pgraph->fifo_access(dev, false); if (pgraph->channel(dev) == chan) @@ -275,6 +277,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) dev_priv->engine.instmem.flush(dev); pgraph->fifo_access(dev, true); + pfifo->reassign(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index 38e523e10995..459ff08241e5 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -45,11 +45,6 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, } if (phys & 1) { - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; - phys |= 0x30; - } - if (coverage <= 32 * 1024 * 1024) phys |= 0x60; else if (coverage <= 64 * 1024 * 1024) diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index e6ea7d83187f..eb18a7e89f5b 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -31,6 +31,7 @@ #include "nvc0_graph.h" static void nvc0_graph_isr(struct drm_device *); +static void nvc0_runk140_isr(struct drm_device *); static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); void @@ -281,6 +282,7 @@ nvc0_graph_destroy(struct drm_device *dev) return; nouveau_irq_unregister(dev, 12); + nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); @@ -390,6 +392,7 @@ nvc0_graph_create(struct drm_device *dev) } nouveau_irq_register(dev, 12, nvc0_graph_isr); + nouveau_irq_register(dev, 25, nvc0_runk140_isr); NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ @@ -512,8 +515,8 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000); nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000); nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000); - nv_wr32(dev, TP_UNIT(gpc, tp, 0xe44), 0x001ffffe); - nv_wr32(dev, TP_UNIT(gpc, tp, 0xe4c), 0x0000000f); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f); } nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); @@ -777,3 +780,19 @@ nvc0_graph_isr(struct drm_device *dev) nv_wr32(dev, 0x400500, 0x00010001); } + +static void +nvc0_runk140_isr(struct drm_device *dev) +{ + u32 units = nv_rd32(dev, 0x00017c) & 0x1f; + + while (units) { + u32 unit = ffs(units) - 1; + u32 reg = 0x140000 + unit * 0x2000; + u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); + u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); + + NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); + units &= ~(1 << unit); + } +} diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c index b9e68b2d30aa..f880ff776db8 100644 --- a/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c @@ -1830,7 +1830,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) for (tp = 0, id = 0; tp < 4; tp++) { for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tp <= priv->tp_nr[gpc]) { + if (tp < priv->tp_nr[gpc]) { nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id); nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id); nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d3ca17080df7..842954fe74c5 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -994,6 +994,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, struct radeon_bo *rbo; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); int r; /* no fb bound */ @@ -1045,11 +1046,17 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, case 16: fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif break; case 24: case 32: fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif break; default: DRM_ERROR("Unsupported screen depth %d\n", @@ -1094,6 +1101,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); @@ -1150,6 +1158,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *target_fb; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; int r; /* no fb bound */ @@ -1203,12 +1212,18 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT; +#endif break; case 24: case 32: fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT; +#endif break; default: DRM_ERROR("Unsupported screen depth %d\n", @@ -1248,6 +1263,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, (u32) fb_location); WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + if (rdev->family >= CHIP_R600) + WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 4e7778d44b8d..695de9a38506 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -187,9 +187,9 @@ static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock) { int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock); - int bw = dp_lanes_for_mode_clock(dpcd, mode_clock); + int dp_clock = dp_link_clock_for_mode_clock(dpcd, mode_clock); - if ((lanes == 0) || (bw == 0)) + if ((lanes == 0) || (dp_clock == 0)) return MODE_CLOCK_HIGH; return MODE_OK; diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index b758dc7f2f2c..d4d4db49a8b8 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -232,7 +232,7 @@ draw_auto(struct radeon_device *rdev) } -/* emits 30 */ +/* emits 34 */ static void set_default_state(struct radeon_device *rdev) { @@ -245,6 +245,8 @@ set_default_state(struct radeon_device *rdev) int num_hs_threads, num_ls_threads; int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; int num_hs_stack_entries, num_ls_stack_entries; + u64 gpu_addr; + int dwords; switch (rdev->family) { case CHIP_CEDAR: @@ -497,6 +499,14 @@ set_default_state(struct radeon_device *rdev) radeon_ring_write(rdev, 0x00000000); radeon_ring_write(rdev, 0x00000000); + /* emit an IB pointing at default state */ + dwords = ALIGN(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; + radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC); + radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF); + radeon_ring_write(rdev, dwords); + } static inline uint32_t i2f(uint32_t input) @@ -527,8 +537,10 @@ static inline uint32_t i2f(uint32_t input) int evergreen_blit_init(struct radeon_device *rdev) { u32 obj_size; - int r; + int r, dwords; void *ptr; + u32 packet2s[16]; + int num_packet2s = 0; /* pin copy shader into vram if already initialized */ if (rdev->r600_blit.shader_obj) @@ -536,8 +548,17 @@ int evergreen_blit_init(struct radeon_device *rdev) mutex_init(&rdev->r600_blit.mutex); rdev->r600_blit.state_offset = 0; - rdev->r600_blit.state_len = 0; - obj_size = 0; + + rdev->r600_blit.state_len = evergreen_default_size; + + dwords = rdev->r600_blit.state_len; + while (dwords & 0xf) { + packet2s[num_packet2s++] = PACKET2(0); + dwords++; + } + + obj_size = dwords * 4; + obj_size = ALIGN(obj_size, 256); rdev->r600_blit.vs_offset = obj_size; obj_size += evergreen_vs_size * 4; @@ -567,6 +588,12 @@ int evergreen_blit_init(struct radeon_device *rdev) return r; } + memcpy_toio(ptr + rdev->r600_blit.state_offset, + evergreen_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4); memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4); radeon_bo_kunmap(rdev->r600_blit.shader_obj); @@ -652,7 +679,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) /* calculate number of loops correctly */ ring_size = num_loops * dwords_per_loop; /* set default + shaders */ - ring_size += 46; /* shaders + def state */ + ring_size += 50; /* shaders + def state */ ring_size += 10; /* fence emit for VB IB */ ring_size += 5; /* done copy */ ring_size += 10; /* fence emit for done copy */ @@ -660,7 +687,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) if (r) return r; - set_default_state(rdev); /* 30 */ + set_default_state(rdev); /* 34 */ set_shaders(rdev); /* 16 */ return 0; } diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 5968dde243e9..5f15820efe12 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1031,8 +1031,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) WREG32(RADEON_CP_CSQ_MODE, REG_SET(RADEON_INDIRECT2_START, indirect2_start) | REG_SET(RADEON_INDIRECT1_START, indirect1_start)); - WREG32(0x718, 0); - WREG32(0x744, 0x00004D4D); + WREG32(RADEON_CP_RB_WPTR_DELAY, 0); + WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D); WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); radeon_ring_start(rdev); r = radeon_ring_test(rdev); @@ -2347,10 +2347,10 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state) temp = RREG32(RADEON_CONFIG_CNTL); if (state == false) { - temp &= ~(1<<8); - temp |= (1<<9); + temp &= ~RADEON_CFG_VGA_RAM_EN; + temp |= RADEON_CFG_VGA_IO_DIS; } else { - temp &= ~(1<<9); + temp &= ~RADEON_CFG_VGA_IO_DIS; } WREG32(RADEON_CONFIG_CNTL, temp); } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index cf862ca580bf..55fe5ba7def3 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -69,6 +69,9 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) mb(); } +#define R300_PTE_WRITEABLE (1 << 2) +#define R300_PTE_READABLE (1 << 3) + int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; @@ -78,7 +81,7 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) } addr = (lower_32_bits(addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 24) | - 0xc; + R300_PTE_WRITEABLE | R300_PTE_READABLE; /* on x86 we want this to be CPU endian, on powerpc * on powerpc without HW swappers, it'll get swapped on way * into VRAM - so no need for cpu_to_le32 on VRAM tables */ @@ -135,7 +138,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); /* Clear error */ - WREG32_PCIE(0x18, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0); tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); tmp |= RADEON_PCIE_TX_GART_EN; tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index c387346f93a9..0b59ed7c7d2c 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -96,7 +96,7 @@ void r420_pipes_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } /* get max number of pipes */ - gb_pipe_select = RREG32(0x402C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); num_pipes = ((gb_pipe_select >> 12) & 3) + 1; /* SE chips have 1 pipe */ diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 3c8677f9e385..2ce80d976568 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -79,8 +79,8 @@ static void r520_gpu_init(struct radeon_device *rdev) WREG32(0x4128, 0xFF); } r420_pipes_init(rdev); - gb_pipe_select = RREG32(0x402C); - tmp = RREG32(0x170C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); pipe_select_current = (tmp >> 2) & 3; tmp = (1 << pipe_select_current) | (((gb_pipe_select >> 8) & 0xF) << 4); diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index 33cda016b083..f869897c7456 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -81,7 +81,11 @@ #define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720 #define R600_LOW_VID_LOWER_GPIO_CNTL 0x724 - +#define R600_D1GRPH_SWAP_CONTROL 0x610C +# define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) #define R600_HDP_NONSURFACE_BASE 0x2c04 diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 8fd184286c0b..5e90984d5ad2 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -641,7 +641,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if (drm_detect_monitor_audio(radeon_connector->edid)) { + if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; @@ -655,7 +655,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if (drm_detect_monitor_audio(radeon_connector->edid)) { + if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; @@ -673,7 +673,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; - else if (drm_detect_monitor_audio(radeon_connector->edid)) { + else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 98321298cffd..8387d32caaa7 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -247,6 +247,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, struct radeon_device *rdev = dev->dev_private; if (rdev->hyperz_filp == file_priv) rdev->hyperz_filp = NULL; + if (rdev->cmask_filp == file_priv) + rdev->cmask_filp = NULL; } /* diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 3cd4dace57c7..ec93a75369e6 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -375,6 +375,8 @@ #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CONFIG_BONDS 0x00e8 #define RADEON_CONFIG_CNTL 0x00e0 +# define RADEON_CFG_VGA_RAM_EN (1 << 8) +# define RADEON_CFG_VGA_IO_DIS (1 << 9) # define RADEON_CFG_ATI_REV_A11 (0 << 16) # define RADEON_CFG_ATI_REV_A12 (1 << 16) # define RADEON_CFG_ATI_REV_A13 (2 << 16) diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 5512e4e5e636..c76283d9eb3d 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -203,6 +203,9 @@ void rs400_gart_fini(struct radeon_device *rdev) radeon_gart_table_ram_free(rdev); } +#define RS400_PTE_WRITEABLE (1 << 2) +#define RS400_PTE_READABLE (1 << 3) + int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { uint32_t entry; @@ -213,7 +216,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) entry = (lower_32_bits(addr) & PAGE_MASK) | ((upper_32_bits(addr) & 0xff) << 4) | - 0xc; + RS400_PTE_WRITEABLE | RS400_PTE_READABLE; entry = cpu_to_le32(entry); rdev->gart.table.ram.ptr[i] = entry; return 0; @@ -226,8 +229,8 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev) for (i = 0; i < rdev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32(0x0150); - if (tmp & (1 << 2)) { + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & RADEON_MC_IDLE) { return 0; } DRM_UDELAY(1); @@ -241,7 +244,7 @@ void rs400_gpu_init(struct radeon_device *rdev) r420_pipes_init(rdev); if (rs400_mc_wait_for_idle(rdev)) { printk(KERN_WARNING "rs400: Failed to wait MC idle while " - "programming pipes. Bad things might happen. %08x\n", RREG32(0x150)); + "programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); } } @@ -300,9 +303,9 @@ static int rs400_debugfs_gart_info(struct seq_file *m, void *data) seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp); tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION); seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp); - tmp = RREG32_MC(0x100); + tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION); seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp); - tmp = RREG32(0x134); + tmp = RREG32(RS690_HDP_FB_LOCATION); seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp); } else { tmp = RREG32(RADEON_AGP_BASE); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 5d569f41f4ae..64b57af93714 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -69,13 +69,13 @@ void rv515_ring_start(struct radeon_device *rdev) ISYNC_CPSCRATCH_IDLEGUI); radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); - radeon_ring_write(rdev, PACKET0(0x170C, 0)); - radeon_ring_write(rdev, 1 << 31); + radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0)); + radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG); radeon_ring_write(rdev, PACKET0(GB_SELECT, 0)); radeon_ring_write(rdev, 0); radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(0x42C8, 0)); + radeon_ring_write(rdev, PACKET0(R500_SU_REG_DEST, 0)); radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0)); radeon_ring_write(rdev, 0); @@ -153,8 +153,8 @@ void rv515_gpu_init(struct radeon_device *rdev) } rv515_vga_render_disable(rdev); r420_pipes_init(rdev); - gb_pipe_select = RREG32(0x402C); - tmp = RREG32(0x170C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); pipe_select_current = (tmp >> 2) & 3; tmp = (1 << pipe_select_current) | (((gb_pipe_select >> 8) & 0xF) << 4); diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index ce0372f0615e..4c0743660e9c 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -1072,6 +1072,7 @@ static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) node->sda.dev_attr.show = grp->show; node->sda.dev_attr.store = grp->store; attr = &node->sda.dev_attr.attr; + sysfs_attr_init(attr); attr->name = node->name; attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0); ret = sysfs_create_file(&pdev->dev.kobj, attr); diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 2d68cf3c223b..b5e892017e0c 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -13,6 +13,7 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/slab.h> +#include <linux/dmi.h> #include <acpi/acpi.h> #include <acpi/acpixf.h> @@ -22,6 +23,21 @@ #define ATK_HID "ATK0110" +static bool new_if; +module_param(new_if, bool, 0); +MODULE_PARM_DESC(new_if, "Override detection heuristic and force the use of the new ATK0110 interface"); + +static const struct dmi_system_id __initconst atk_force_new_if[] = { + { + /* Old interface has broken MCH temp monitoring */ + .ident = "Asus Sabertooth X58", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") + } + }, + { } +}; + /* Minimum time between readings, enforced in order to avoid * hogging the CPU. */ @@ -1302,7 +1318,9 @@ static int atk_probe_if(struct atk_data *data) * analysis of multiple DSDTs indicates that when both interfaces * are present the new one (GGRP/GITM) is not functional. */ - if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle) + if (new_if) + dev_info(dev, "Overriding interface detection\n"); + if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle && !new_if) data->old_interface = true; else if (data->enumerate_handle && data->read_handle && data->write_handle) @@ -1420,6 +1438,9 @@ static int __init atk0110_init(void) return -EBUSY; } + if (dmi_check_system(atk_force_new_if)) + new_if = true; + ret = acpi_bus_register_driver(&atk_driver); if (ret) pr_info("acpi_bus_register_driver failed: %d\n", ret); diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c index 1b674b7d4584..d805e8e57967 100644 --- a/drivers/hwmon/lis3lv02d.c +++ b/drivers/hwmon/lis3lv02d.c @@ -957,7 +957,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev) /* bail if we did not get an IRQ from the bus layer */ if (!dev->irq) { - pr_err("No IRQ. Disabling /dev/freefall\n"); + pr_debug("No IRQ. Disabling /dev/freefall\n"); goto out; } diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 939476659ad6..ac471b77c18e 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -86,7 +86,7 @@ static const u32 tegra_kbc_default_keymap[] = { KEY(0, 5, KEY_Z), KEY(0, 7, KEY_FN), - KEY(1, 7, KEY_MENU), + KEY(1, 7, KEY_LEFTMETA), KEY(2, 6, KEY_RIGHTALT), KEY(2, 7, KEY_LEFTALT), @@ -355,8 +355,8 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) for (i = 0; i < KBC_MAX_GPIO; i++) { u32 r_shft = 5 * (i % 6); u32 c_shft = 4 * (i % 8); - u32 r_mask = 0x1f << r_shift; - u32 c_mask = 0x0f << c_shift; + u32 r_mask = 0x1f << r_shft; + u32 c_mask = 0x0f << c_shft; u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; u32 row_cfg = readl(kbc->mmio + r_offs); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index da392c22fc6c..aa186cf6c514 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -755,23 +755,26 @@ static int synaptics_reconnect(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; struct synaptics_data old_priv = *priv; + int retry = 0; + int error; - psmouse_reset(psmouse); + do { + psmouse_reset(psmouse); + error = synaptics_detect(psmouse, 0); + } while (error && ++retry < 3); - if (synaptics_detect(psmouse, 0)) + if (error) return -1; + if (retry > 1) + printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", + retry); + if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); return -1; } - if (old_priv.identity != priv->identity || - old_priv.model_id != priv->model_id || - old_priv.capabilities != priv->capabilities || - old_priv.ext_cap != priv->ext_cap) - return -1; - if (synaptics_set_absolute_mode(psmouse)) { printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); return -1; @@ -782,6 +785,19 @@ static int synaptics_reconnect(struct psmouse *psmouse) return -1; } + if (old_priv.identity != priv->identity || + old_priv.model_id != priv->model_id || + old_priv.capabilities != priv->capabilities || + old_priv.ext_cap != priv->ext_cap) { + printk(KERN_ERR "Synaptics hardware appears to be different: " + "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", + old_priv.identity, priv->identity, + old_priv.model_id, priv->model_id, + old_priv.capabilities, priv->capabilities, + old_priv.ext_cap, priv->ext_cap); + return -1; + } + return 0; } diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 72be8a02118c..512a2f4ada0e 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -458,21 +458,27 @@ static int ir_getkeycode(struct input_dev *idev, index = ir_lookup_by_scancode(rc_map, scancode); } - if (index >= rc_map->len) { - if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) - IR_dprintk(1, "unknown key for scancode 0x%04x\n", - scancode); + if (index < rc_map->len) { + entry = &rc_map->scan[index]; + + ke->index = index; + ke->keycode = entry->keycode; + ke->len = sizeof(entry->scancode); + memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); + + } else if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) { + /* + * We do not really know the valid range of scancodes + * so let's respond with KEY_RESERVED to anything we + * do not have mapping for [yet]. + */ + ke->index = index; + ke->keycode = KEY_RESERVED; + } else { retval = -EINVAL; goto out; } - entry = &rc_map->scan[index]; - - ke->index = index; - ke->keycode = entry->keycode; - ke->len = sizeof(entry->scancode); - memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); - retval = 0; out: diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index bac7d62866b7..0371bf502249 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -462,7 +462,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) goto out; } - mmc = mmc_alloc_host(sizeof(*mmc), &pdev->dev); + mmc = mmc_alloc_host(sizeof(struct sdh_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; goto out; diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b3a0ab0e4c2b..74218ad677e4 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -14,6 +14,7 @@ */ #include <linux/mmc/host.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/irq.h> #include <linux/interrupt.h> @@ -827,8 +828,8 @@ static int __devinit jz4740_mmc_probe(struct platform_device* pdev) } host->clk = clk_get(&pdev->dev, "mmc"); - if (!host->clk) { - ret = -ENOENT; + if (IS_ERR(host->clk)) { + ret = PTR_ERR(host->clk); dev_err(&pdev->dev, "Failed to get mmc clock\n"); goto err_free_host; } diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2de12fe155da..2d6de3e03e2d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -14,6 +14,7 @@ #include <linux/ioport.h> #include <linux/device.h> #include <linux/interrupt.h> +#include <linux/kernel.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/highmem.h> @@ -283,19 +284,19 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, u32 remain, success; /* Calculate how far we are into the transfer */ - remain = readl(host->base + MMCIDATACNT) << 2; + remain = readl(host->base + MMCIDATACNT); success = data->blksz * data->blocks - remain; dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); if (status & MCI_DATACRCFAIL) { /* Last block was not successful */ - host->data_xfered = ((success / data->blksz) - 1 * data->blksz); + host->data_xfered = round_down(success - 1, data->blksz); data->error = -EILSEQ; } else if (status & MCI_DATATIMEOUT) { - host->data_xfered = success; + host->data_xfered = round_down(success, data->blksz); data->error = -ETIMEDOUT; } else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) { - host->data_xfered = success; + host->data_xfered = round_down(success, data->blksz); data->error = -EIO; } @@ -319,7 +320,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, if (status & MCI_DATABLOCKEND) dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n"); - if (status & MCI_DATAEND) { + if (status & MCI_DATAEND || data->error) { mmci_stop_data(host); if (!data->error) @@ -342,15 +343,15 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, host->cmd = NULL; - cmd->resp[0] = readl(base + MMCIRESPONSE0); - cmd->resp[1] = readl(base + MMCIRESPONSE1); - cmd->resp[2] = readl(base + MMCIRESPONSE2); - cmd->resp[3] = readl(base + MMCIRESPONSE3); - if (status & MCI_CMDTIMEOUT) { cmd->error = -ETIMEDOUT; } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { cmd->error = -EILSEQ; + } else { + cmd->resp[0] = readl(base + MMCIRESPONSE0); + cmd->resp[1] = readl(base + MMCIRESPONSE1); + cmd->resp[2] = readl(base + MMCIRESPONSE2); + cmd->resp[3] = readl(base + MMCIRESPONSE3); } if (!cmd->data || cmd->error) { diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 17203586305c..5309ab95aada 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -277,10 +277,43 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) host->clock = clock; } +/** + * sdhci_s3c_platform_8bit_width - support 8bit buswidth + * @host: The SDHCI host being queried + * @width: MMC_BUS_WIDTH_ macro for the bus width being requested + * + * We have 8-bit width support but is not a v3 controller. + * So we add platform_8bit_width() and support 8bit width. + */ +static int sdhci_s3c_platform_8bit_width(struct sdhci_host *host, int width) +{ + u8 ctrl; + + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + + switch (width) { + case MMC_BUS_WIDTH_8: + ctrl |= SDHCI_CTRL_8BITBUS; + ctrl &= ~SDHCI_CTRL_4BITBUS; + break; + case MMC_BUS_WIDTH_4: + ctrl |= SDHCI_CTRL_4BITBUS; + ctrl &= ~SDHCI_CTRL_8BITBUS; + break; + default: + break; + } + + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + + return 0; +} + static struct sdhci_ops sdhci_s3c_ops = { .get_max_clock = sdhci_s3c_get_max_clk, .set_clock = sdhci_s3c_set_clock, .get_min_clock = sdhci_s3c_get_min_clock, + .platform_8bit_width = sdhci_s3c_platform_8bit_width, }; static void sdhci_s3c_notify_change(struct platform_device *dev, int state) @@ -473,6 +506,9 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) if (pdata->cd_type == S3C_SDHCI_CD_PERMANENT) host->mmc->caps = MMC_CAP_NONREMOVABLE; + if (pdata->host_caps) + host->mmc->caps |= pdata->host_caps; + host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_32BIT_DMA_SIZE); diff --git a/drivers/mmc/host/ushc.c b/drivers/mmc/host/ushc.c index f8f65df9b017..f08f944ac53c 100644 --- a/drivers/mmc/host/ushc.c +++ b/drivers/mmc/host/ushc.c @@ -19,7 +19,6 @@ #include <linux/module.h> #include <linux/usb.h> #include <linux/kernel.h> -#include <linux/usb.h> #include <linux/slab.h> #include <linux/dma-mapping.h> #include <linux/mmc/host.h> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index f49e49dc5928..5ebe280225d6 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -672,33 +672,7 @@ static int io_init(struct ubi_device *ubi) ubi->nor_flash = 1; } - /* - * Set UBI min. I/O size (@ubi->min_io_size). We use @mtd->writebufsize - * for these purposes, not @mtd->writesize. At the moment this does not - * matter for NAND, because currently @mtd->writebufsize is equivalent to - * @mtd->writesize for all NANDs. However, some CFI NOR flashes may - * have @mtd->writebufsize which is multiple of @mtd->writesize. - * - * The reason we use @mtd->writebufsize for @ubi->min_io_size is that - * UBI and UBIFS recovery algorithms rely on the fact that if there was - * an unclean power cut, then we can find offset of the last corrupted - * node, align the offset to @ubi->min_io_size, read the rest of the - * eraseblock starting from this offset, and check whether there are - * only 0xFF bytes. If yes, then we are probably dealing with a - * corruption caused by a power cut, if not, then this is probably some - * severe corruption. - * - * Thus, we have to use the maximum write unit size of the flash, which - * is @mtd->writebufsize, because @mtd->writesize is the minimum write - * size, not the maximum. - */ - if (ubi->mtd->type == MTD_NANDFLASH) - ubi_assert(ubi->mtd->writebufsize == ubi->mtd->writesize); - else if (ubi->mtd->type == MTD_NORFLASH) - ubi_assert(ubi->mtd->writebufsize % ubi->mtd->writesize == 0); - - ubi->min_io_size = ubi->mtd->writebufsize; - + ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; /* diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index df99edf3464a..0ba59d5aeb7f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -7553,6 +7553,10 @@ bnx2_set_flags(struct net_device *dev, u32 data) !(data & ETH_FLAG_RXVLAN)) return -EINVAL; + /* TSO with VLAN tag won't work with current firmware */ + if (!(data & ETH_FLAG_TXVLAN)) + return -EINVAL; + rc = ethtool_op_set_flags(dev, data, ETH_FLAG_RXHASH | ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN); if (rc) @@ -7962,11 +7966,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) /* AER (Advanced Error Reporting) hooks */ err = pci_enable_pcie_error_reporting(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_pcie_error_reporting " - "failed 0x%x\n", err); - /* non-fatal, continue */ - } + if (!err) + bp->flags |= BNX2_FLAG_AER_ENABLED; } else { bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); @@ -8229,8 +8230,10 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) return 0; err_out_unmap: - if (bp->flags & BNX2_FLAG_PCIE) + if (bp->flags & BNX2_FLAG_AER_ENABLED) { pci_disable_pcie_error_reporting(pdev); + bp->flags &= ~BNX2_FLAG_AER_ENABLED; + } if (bp->regview) { iounmap(bp->regview); @@ -8418,8 +8421,10 @@ bnx2_remove_one(struct pci_dev *pdev) kfree(bp->temp_stats_blk); - if (bp->flags & BNX2_FLAG_PCIE) + if (bp->flags & BNX2_FLAG_AER_ENABLED) { pci_disable_pcie_error_reporting(pdev); + bp->flags &= ~BNX2_FLAG_AER_ENABLED; + } free_netdev(dev); @@ -8535,7 +8540,7 @@ static pci_ers_result_t bnx2_io_slot_reset(struct pci_dev *pdev) } rtnl_unlock(); - if (!(bp->flags & BNX2_FLAG_PCIE)) + if (!(bp->flags & BNX2_FLAG_AER_ENABLED)) return result; err = pci_cleanup_aer_uncorrect_error_status(pdev); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 5488a2e82fe9..f459fb2f9add 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -6741,6 +6741,7 @@ struct bnx2 { #define BNX2_FLAG_JUMBO_BROKEN 0x00000800 #define BNX2_FLAG_CAN_KEEP_VLAN 0x00001000 #define BNX2_FLAG_BROKEN_STATS 0x00002000 +#define BNX2_FLAG_AER_ENABLED 0x00004000 struct bnx2_napi bnx2_napi[BNX2_MAX_MSIX_VEC]; diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index 171782e2bb39..1024ae158227 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -2470,6 +2470,10 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac if (!(dev->flags & IFF_MASTER)) goto out; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, sizeof(struct lacpdu))) goto out; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f4e638c65129..5c6fba802f2b 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -326,6 +326,10 @@ static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct goto out; } + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out; + if (!pskb_may_pull(skb, arp_hdr_len(bond_dev))) goto out; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b1025b85acf1..163e0b06eaa5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2733,6 +2733,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack if (!slave || !slave_do_arp_validate(bond, slave)) goto out_unlock; + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + goto out_unlock; + if (!pskb_may_pull(skb, arp_hdr_len(dev))) goto out_unlock; diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index d5a9db60ade9..986195eaa57c 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -117,6 +117,8 @@ source "drivers/net/can/sja1000/Kconfig" source "drivers/net/can/usb/Kconfig" +source "drivers/net/can/softing/Kconfig" + config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 07ca159ba3f9..53c82a71778e 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CAN_DEV) += can-dev.o can-dev-y := dev.o obj-y += usb/ +obj-y += softing/ obj-$(CONFIG_CAN_SJA1000) += sja1000/ obj-$(CONFIG_CAN_MSCAN) += mscan/ diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 7ef83d06f7ed..2532b9631538 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -2,7 +2,7 @@ * at91_can.c - CAN network driver for AT91 SoC CAN controller * * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> - * (C) 2008, 2009, 2010 by Marc Kleine-Budde <kernel@pengutronix.de> + * (C) 2008, 2009, 2010, 2011 by Marc Kleine-Budde <kernel@pengutronix.de> * * This software may be distributed under the terms of the GNU General * Public License ("GPL") version 2 as distributed in the 'COPYING' @@ -30,6 +30,7 @@ #include <linux/module.h> #include <linux/netdevice.h> #include <linux/platform_device.h> +#include <linux/rtnetlink.h> #include <linux/skbuff.h> #include <linux/spinlock.h> #include <linux/string.h> @@ -40,22 +41,23 @@ #include <mach/board.h> -#define AT91_NAPI_WEIGHT 12 +#define AT91_NAPI_WEIGHT 11 /* * RX/TX Mailbox split * don't dare to touch */ -#define AT91_MB_RX_NUM 12 +#define AT91_MB_RX_NUM 11 #define AT91_MB_TX_SHIFT 2 -#define AT91_MB_RX_FIRST 0 +#define AT91_MB_RX_FIRST 1 #define AT91_MB_RX_LAST (AT91_MB_RX_FIRST + AT91_MB_RX_NUM - 1) #define AT91_MB_RX_MASK(i) ((1 << (i)) - 1) #define AT91_MB_RX_SPLIT 8 #define AT91_MB_RX_LOW_LAST (AT91_MB_RX_SPLIT - 1) -#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT)) +#define AT91_MB_RX_LOW_MASK (AT91_MB_RX_MASK(AT91_MB_RX_SPLIT) & \ + ~AT91_MB_RX_MASK(AT91_MB_RX_FIRST)) #define AT91_MB_TX_NUM (1 << AT91_MB_TX_SHIFT) #define AT91_MB_TX_FIRST (AT91_MB_RX_LAST + 1) @@ -168,6 +170,8 @@ struct at91_priv { struct clk *clk; struct at91_can_data *pdata; + + canid_t mb0_id; }; static struct can_bittiming_const at91_bittiming_const = { @@ -220,6 +224,18 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb, set_mb_mode_prio(priv, mb, mode, 0); } +static inline u32 at91_can_id_to_reg_mid(canid_t can_id) +{ + u32 reg_mid; + + if (can_id & CAN_EFF_FLAG) + reg_mid = (can_id & CAN_EFF_MASK) | AT91_MID_MIDE; + else + reg_mid = (can_id & CAN_SFF_MASK) << 18; + + return reg_mid; +} + /* * Swtich transceiver on or off */ @@ -233,12 +249,22 @@ static void at91_setup_mailboxes(struct net_device *dev) { struct at91_priv *priv = netdev_priv(dev); unsigned int i; + u32 reg_mid; /* - * The first 12 mailboxes are used as a reception FIFO. The - * last mailbox is configured with overwrite option. The - * overwrite flag indicates a FIFO overflow. + * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first + * mailbox is disabled. The next 11 mailboxes are used as a + * reception FIFO. The last mailbox is configured with + * overwrite option. The overwrite flag indicates a FIFO + * overflow. */ + reg_mid = at91_can_id_to_reg_mid(priv->mb0_id); + for (i = 0; i < AT91_MB_RX_FIRST; i++) { + set_mb_mode(priv, i, AT91_MB_MODE_DISABLED); + at91_write(priv, AT91_MID(i), reg_mid); + at91_write(priv, AT91_MCR(i), 0x0); /* clear dlc */ + } + for (i = AT91_MB_RX_FIRST; i < AT91_MB_RX_LAST; i++) set_mb_mode(priv, i, AT91_MB_MODE_RX); set_mb_mode(priv, AT91_MB_RX_LAST, AT91_MB_MODE_RX_OVRWR); @@ -254,7 +280,8 @@ static void at91_setup_mailboxes(struct net_device *dev) set_mb_mode_prio(priv, i, AT91_MB_MODE_TX, 0); /* Reset tx and rx helper pointers */ - priv->tx_next = priv->tx_echo = priv->rx_next = 0; + priv->tx_next = priv->tx_echo = 0; + priv->rx_next = AT91_MB_RX_FIRST; } static int at91_set_bittiming(struct net_device *dev) @@ -372,12 +399,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) netdev_err(dev, "BUG! TX buffer full when queue awake!\n"); return NETDEV_TX_BUSY; } - - if (cf->can_id & CAN_EFF_FLAG) - reg_mid = (cf->can_id & CAN_EFF_MASK) | AT91_MID_MIDE; - else - reg_mid = (cf->can_id & CAN_SFF_MASK) << 18; - + reg_mid = at91_can_id_to_reg_mid(cf->can_id); reg_mcr = ((cf->can_id & CAN_RTR_FLAG) ? AT91_MCR_MRTR : 0) | (cf->can_dlc << 16) | AT91_MCR_MTCR; @@ -539,27 +561,31 @@ static void at91_read_msg(struct net_device *dev, unsigned int mb) * * Theory of Operation: * - * 12 of the 16 mailboxes on the chip are reserved for RX. we split - * them into 2 groups. The lower group holds 8 and upper 4 mailboxes. + * 11 of the 16 mailboxes on the chip are reserved for RX. we split + * them into 2 groups. The lower group holds 7 and upper 4 mailboxes. * * Like it or not, but the chip always saves a received CAN message * into the first free mailbox it finds (starting with the * lowest). This makes it very difficult to read the messages in the * right order from the chip. This is how we work around that problem: * - * The first message goes into mb nr. 0 and issues an interrupt. All + * The first message goes into mb nr. 1 and issues an interrupt. All * rx ints are disabled in the interrupt handler and a napi poll is * scheduled. We read the mailbox, but do _not_ reenable the mb (to * receive another message). * * lower mbxs upper - * ______^______ __^__ - * / \ / \ + * ____^______ __^__ + * / \ / \ * +-+-+-+-+-+-+-+-++-+-+-+-+ - * |x|x|x|x|x|x|x|x|| | | | | + * | |x|x|x|x|x|x|x|| | | | | * +-+-+-+-+-+-+-+-++-+-+-+-+ * 0 0 0 0 0 0 0 0 0 0 1 1 \ mail * 0 1 2 3 4 5 6 7 8 9 0 1 / box + * ^ + * | + * \ + * unused, due to chip bug * * The variable priv->rx_next points to the next mailbox to read a * message from. As long we're in the lower mailboxes we just read the @@ -590,10 +616,10 @@ static int at91_poll_rx(struct net_device *dev, int quota) "order of incoming frames cannot be guaranteed\n"); again: - for (mb = find_next_bit(addr, AT91_MB_RX_NUM, priv->rx_next); - mb < AT91_MB_RX_NUM && quota > 0; + for (mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, priv->rx_next); + mb < AT91_MB_RX_LAST + 1 && quota > 0; reg_sr = at91_read(priv, AT91_SR), - mb = find_next_bit(addr, AT91_MB_RX_NUM, ++priv->rx_next)) { + mb = find_next_bit(addr, AT91_MB_RX_LAST + 1, ++priv->rx_next)) { at91_read_msg(dev, mb); /* reactivate mailboxes */ @@ -610,8 +636,8 @@ static int at91_poll_rx(struct net_device *dev, int quota) /* upper group completed, look again in lower */ if (priv->rx_next > AT91_MB_RX_LOW_LAST && - quota > 0 && mb >= AT91_MB_RX_NUM) { - priv->rx_next = 0; + quota > 0 && mb > AT91_MB_RX_LAST) { + priv->rx_next = AT91_MB_RX_FIRST; goto again; } @@ -1037,6 +1063,64 @@ static const struct net_device_ops at91_netdev_ops = { .ndo_start_xmit = at91_start_xmit, }; +static ssize_t at91_sysfs_show_mb0_id(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct at91_priv *priv = netdev_priv(to_net_dev(dev)); + + if (priv->mb0_id & CAN_EFF_FLAG) + return snprintf(buf, PAGE_SIZE, "0x%08x\n", priv->mb0_id); + else + return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id); +} + +static ssize_t at91_sysfs_set_mb0_id(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct net_device *ndev = to_net_dev(dev); + struct at91_priv *priv = netdev_priv(ndev); + unsigned long can_id; + ssize_t ret; + int err; + + rtnl_lock(); + + if (ndev->flags & IFF_UP) { + ret = -EBUSY; + goto out; + } + + err = strict_strtoul(buf, 0, &can_id); + if (err) { + ret = err; + goto out; + } + + if (can_id & CAN_EFF_FLAG) + can_id &= CAN_EFF_MASK | CAN_EFF_FLAG; + else + can_id &= CAN_SFF_MASK; + + priv->mb0_id = can_id; + ret = count; + + out: + rtnl_unlock(); + return ret; +} + +static DEVICE_ATTR(mb0_id, S_IWUGO | S_IRUGO, + at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id); + +static struct attribute *at91_sysfs_attrs[] = { + &dev_attr_mb0_id.attr, + NULL, +}; + +static struct attribute_group at91_sysfs_attr_group = { + .attrs = at91_sysfs_attrs, +}; + static int __devinit at91_can_probe(struct platform_device *pdev) { struct net_device *dev; @@ -1082,6 +1166,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev) dev->netdev_ops = &at91_netdev_ops; dev->irq = irq; dev->flags |= IFF_ECHO; + dev->sysfs_groups[0] = &at91_sysfs_attr_group; priv = netdev_priv(dev); priv->can.clock.freq = clk_get_rate(clk); @@ -1093,6 +1178,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev) priv->dev = dev; priv->clk = clk; priv->pdata = pdev->dev.platform_data; + priv->mb0_id = 0x7ff; netif_napi_add(dev, &priv->napi, at91_poll, AT91_NAPI_WEIGHT); diff --git a/drivers/net/can/softing/Kconfig b/drivers/net/can/softing/Kconfig new file mode 100644 index 000000000000..92bd6bdde5e3 --- /dev/null +++ b/drivers/net/can/softing/Kconfig @@ -0,0 +1,30 @@ +config CAN_SOFTING + tristate "Softing Gmbh CAN generic support" + depends on CAN_DEV + ---help--- + Support for CAN cards from Softing Gmbh & some cards + from Vector Gmbh. + Softing Gmbh CAN cards come with 1 or 2 physical busses. + Those cards typically use Dual Port RAM to communicate + with the host CPU. The interface is then identical for PCI + and PCMCIA cards. This driver operates on a platform device, + which has been created by softing_cs or softing_pci driver. + Warning: + The API of the card does not allow fine control per bus, but + controls the 2 busses on the card together. + As such, some actions (start/stop/busoff recovery) on 1 bus + must bring down the other bus too temporarily. + +config CAN_SOFTING_CS + tristate "Softing Gmbh CAN pcmcia cards" + depends on PCMCIA + select CAN_SOFTING + ---help--- + Support for PCMCIA cards from Softing Gmbh & some cards + from Vector Gmbh. + You need firmware for these, which you can get at + http://developer.berlios.de/projects/socketcan/ + This version of the driver is written against + firmware version 4.6 (softing-fw-4.6-binaries.tar.gz) + In order to use the card as CAN device, you need the Softing generic + support too. diff --git a/drivers/net/can/softing/Makefile b/drivers/net/can/softing/Makefile new file mode 100644 index 000000000000..c5e5016c742e --- /dev/null +++ b/drivers/net/can/softing/Makefile @@ -0,0 +1,6 @@ + +softing-y := softing_main.o softing_fw.o +obj-$(CONFIG_CAN_SOFTING) += softing.o +obj-$(CONFIG_CAN_SOFTING_CS) += softing_cs.o + +ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG diff --git a/drivers/net/can/softing/softing.h b/drivers/net/can/softing/softing.h new file mode 100644 index 000000000000..7ec9f4db3d52 --- /dev/null +++ b/drivers/net/can/softing/softing.h @@ -0,0 +1,167 @@ +/* + * softing common interfaces + * + * by Kurt Van Dijck, 2008-2010 + */ + +#include <linux/atomic.h> +#include <linux/netdevice.h> +#include <linux/ktime.h> +#include <linux/mutex.h> +#include <linux/spinlock.h> +#include <linux/can.h> +#include <linux/can/dev.h> + +#include "softing_platform.h" + +struct softing; + +struct softing_priv { + struct can_priv can; /* must be the first member! */ + struct net_device *netdev; + struct softing *card; + struct { + int pending; + /* variables wich hold the circular buffer */ + int echo_put; + int echo_get; + } tx; + struct can_bittiming_const btr_const; + int index; + uint8_t output; + uint16_t chip; +}; +#define netdev2softing(netdev) ((struct softing_priv *)netdev_priv(netdev)) + +struct softing { + const struct softing_platform_data *pdat; + struct platform_device *pdev; + struct net_device *net[2]; + spinlock_t spin; /* protect this structure & DPRAM access */ + ktime_t ts_ref; + ktime_t ts_overflow; /* timestamp overflow value, in ktime */ + + struct { + /* indication of firmware status */ + int up; + /* protection of the 'up' variable */ + struct mutex lock; + } fw; + struct { + int nr; + int requested; + int svc_count; + unsigned int dpram_position; + } irq; + struct { + int pending; + int last_bus; + /* + * keep the bus that last tx'd a message, + * in order to let every netdev queue resume + */ + } tx; + __iomem uint8_t *dpram; + unsigned long dpram_phys; + unsigned long dpram_size; + struct { + uint16_t fw_version, hw_version, license, serial; + uint16_t chip[2]; + unsigned int freq; /* remote cpu's operating frequency */ + } id; +}; + +extern int softing_default_output(struct net_device *netdev); + +extern ktime_t softing_raw2ktime(struct softing *card, u32 raw); + +extern int softing_chip_poweron(struct softing *card); + +extern int softing_bootloader_command(struct softing *card, int16_t cmd, + const char *msg); + +/* Load firmware after reset */ +extern int softing_load_fw(const char *file, struct softing *card, + __iomem uint8_t *virt, unsigned int size, int offset); + +/* Load final application firmware after bootloader */ +extern int softing_load_app_fw(const char *file, struct softing *card); + +/* + * enable or disable irq + * only called with fw.lock locked + */ +extern int softing_enable_irq(struct softing *card, int enable); + +/* start/stop 1 bus on card */ +extern int softing_startstop(struct net_device *netdev, int up); + +/* netif_rx() */ +extern int softing_netdev_rx(struct net_device *netdev, + const struct can_frame *msg, ktime_t ktime); + +/* SOFTING DPRAM mappings */ +#define DPRAM_RX 0x0000 + #define DPRAM_RX_SIZE 32 + #define DPRAM_RX_CNT 16 +#define DPRAM_RX_RD 0x0201 /* uint8_t */ +#define DPRAM_RX_WR 0x0205 /* uint8_t */ +#define DPRAM_RX_LOST 0x0207 /* uint8_t */ + +#define DPRAM_FCT_PARAM 0x0300 /* int16_t [20] */ +#define DPRAM_FCT_RESULT 0x0328 /* int16_t */ +#define DPRAM_FCT_HOST 0x032b /* uint16_t */ + +#define DPRAM_INFO_BUSSTATE 0x0331 /* uint16_t */ +#define DPRAM_INFO_BUSSTATE2 0x0335 /* uint16_t */ +#define DPRAM_INFO_ERRSTATE 0x0339 /* uint16_t */ +#define DPRAM_INFO_ERRSTATE2 0x033d /* uint16_t */ +#define DPRAM_RESET 0x0341 /* uint16_t */ +#define DPRAM_CLR_RECV_FIFO 0x0345 /* uint16_t */ +#define DPRAM_RESET_TIME 0x034d /* uint16_t */ +#define DPRAM_TIME 0x0350 /* uint64_t */ +#define DPRAM_WR_START 0x0358 /* uint8_t */ +#define DPRAM_WR_END 0x0359 /* uint8_t */ +#define DPRAM_RESET_RX_FIFO 0x0361 /* uint16_t */ +#define DPRAM_RESET_TX_FIFO 0x0364 /* uint8_t */ +#define DPRAM_READ_FIFO_LEVEL 0x0365 /* uint8_t */ +#define DPRAM_RX_FIFO_LEVEL 0x0366 /* uint16_t */ +#define DPRAM_TX_FIFO_LEVEL 0x0366 /* uint16_t */ + +#define DPRAM_TX 0x0400 /* uint16_t */ + #define DPRAM_TX_SIZE 16 + #define DPRAM_TX_CNT 32 +#define DPRAM_TX_RD 0x0601 /* uint8_t */ +#define DPRAM_TX_WR 0x0605 /* uint8_t */ + +#define DPRAM_COMMAND 0x07e0 /* uint16_t */ +#define DPRAM_RECEIPT 0x07f0 /* uint16_t */ +#define DPRAM_IRQ_TOHOST 0x07fe /* uint8_t */ +#define DPRAM_IRQ_TOCARD 0x07ff /* uint8_t */ + +#define DPRAM_V2_RESET 0x0e00 /* uint8_t */ +#define DPRAM_V2_IRQ_TOHOST 0x0e02 /* uint8_t */ + +#define TXMAX (DPRAM_TX_CNT - 1) + +/* DPRAM return codes */ +#define RES_NONE 0 +#define RES_OK 1 +#define RES_NOK 2 +#define RES_UNKNOWN 3 +/* DPRAM flags */ +#define CMD_TX 0x01 +#define CMD_ACK 0x02 +#define CMD_XTD 0x04 +#define CMD_RTR 0x08 +#define CMD_ERR 0x10 +#define CMD_BUS2 0x80 + +/* returned fifo entry bus state masks */ +#define SF_MASK_BUSOFF 0x80 +#define SF_MASK_EPASSIVE 0x60 + +/* bus states */ +#define STATE_BUSOFF 2 +#define STATE_EPASSIVE 1 +#define STATE_EACTIVE 0 diff --git a/drivers/net/can/softing/softing_cs.c b/drivers/net/can/softing/softing_cs.c new file mode 100644 index 000000000000..300fe75dd1a7 --- /dev/null +++ b/drivers/net/can/softing/softing_cs.c @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2008-2010 + * + * - Kurt Van Dijck, EIA Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/module.h> +#include <linux/kernel.h> + +#include <pcmcia/cistpl.h> +#include <pcmcia/ds.h> + +#include "softing_platform.h" + +static int softingcs_index; +static spinlock_t softingcs_index_lock; + +static int softingcs_reset(struct platform_device *pdev, int v); +static int softingcs_enable_irq(struct platform_device *pdev, int v); + +/* + * platform_data descriptions + */ +#define MHZ (1000*1000) +static const struct softing_platform_data softingcs_platform_data[] = { +{ + .name = "CANcard", + .manf = 0x0168, .prod = 0x001, + .generation = 1, + .nbus = 2, + .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "CANcard-NEC", + .manf = 0x0168, .prod = 0x002, + .generation = 1, + .nbus = 2, + .freq = 16 * MHZ, .max_brp = 32, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "CANcard-SJA", + .manf = 0x0168, .prod = 0x004, + .generation = 1, + .nbus = 2, + .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "CANcard-2", + .manf = 0x0168, .prod = 0x005, + .generation = 2, + .nbus = 2, + .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, + .dpram_size = 0x1000, + .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, + .reset = softingcs_reset, + .enable_irq = NULL, +}, { + .name = "Vector-CANcard", + .manf = 0x0168, .prod = 0x081, + .generation = 1, + .nbus = 2, + .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "Vector-CANcard-SJA", + .manf = 0x0168, .prod = 0x084, + .generation = 1, + .nbus = 2, + .freq = 20 * MHZ, .max_brp = 32, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cansja.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "Vector-CANcard-2", + .manf = 0x0168, .prod = 0x085, + .generation = 2, + .nbus = 2, + .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, + .dpram_size = 0x1000, + .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, + .reset = softingcs_reset, + .enable_irq = NULL, +}, { + .name = "EDICcard-NEC", + .manf = 0x0168, .prod = 0x102, + .generation = 1, + .nbus = 2, + .freq = 16 * MHZ, .max_brp = 64, .max_sjw = 4, + .dpram_size = 0x0800, + .boot = {0x0000, 0x000000, fw_dir "bcard.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancard.bin",}, + .reset = softingcs_reset, + .enable_irq = softingcs_enable_irq, +}, { + .name = "EDICcard-2", + .manf = 0x0168, .prod = 0x105, + .generation = 2, + .nbus = 2, + .freq = 24 * MHZ, .max_brp = 64, .max_sjw = 4, + .dpram_size = 0x1000, + .boot = {0x0000, 0x000000, fw_dir "bcard2.bin",}, + .load = {0x0120, 0x00f600, fw_dir "ldcard2.bin",}, + .app = {0x0010, 0x0d0000, fw_dir "cancrd2.bin",}, + .reset = softingcs_reset, + .enable_irq = NULL, +}, { + 0, 0, +}, +}; + +MODULE_FIRMWARE(fw_dir "bcard.bin"); +MODULE_FIRMWARE(fw_dir "ldcard.bin"); +MODULE_FIRMWARE(fw_dir "cancard.bin"); +MODULE_FIRMWARE(fw_dir "cansja.bin"); + +MODULE_FIRMWARE(fw_dir "bcard2.bin"); +MODULE_FIRMWARE(fw_dir "ldcard2.bin"); +MODULE_FIRMWARE(fw_dir "cancrd2.bin"); + +static __devinit const struct softing_platform_data +*softingcs_find_platform_data(unsigned int manf, unsigned int prod) +{ + const struct softing_platform_data *lp; + + for (lp = softingcs_platform_data; lp->manf; ++lp) { + if ((lp->manf == manf) && (lp->prod == prod)) + return lp; + } + return NULL; +} + +/* + * platformdata callbacks + */ +static int softingcs_reset(struct platform_device *pdev, int v) +{ + struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); + + dev_dbg(&pdev->dev, "pcmcia config [2] %02x\n", v ? 0 : 0x20); + return pcmcia_write_config_byte(pcmcia, 2, v ? 0 : 0x20); +} + +static int softingcs_enable_irq(struct platform_device *pdev, int v) +{ + struct pcmcia_device *pcmcia = to_pcmcia_dev(pdev->dev.parent); + + dev_dbg(&pdev->dev, "pcmcia config [0] %02x\n", v ? 0x60 : 0); + return pcmcia_write_config_byte(pcmcia, 0, v ? 0x60 : 0); +} + +/* + * pcmcia check + */ +static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia, + void *priv_data) +{ + struct softing_platform_data *pdat = priv_data; + struct resource *pres; + int memspeed = 0; + + WARN_ON(!pdat); + pres = pcmcia->resource[PCMCIA_IOMEM_0]; + if (resource_size(pres) < 0x1000) + return -ERANGE; + + pres->flags |= WIN_MEMORY_TYPE_CM | WIN_ENABLE; + if (pdat->generation < 2) { + pres->flags |= WIN_USE_WAIT | WIN_DATA_WIDTH_8; + memspeed = 3; + } else { + pres->flags |= WIN_DATA_WIDTH_16; + } + return pcmcia_request_window(pcmcia, pres, memspeed); +} + +static __devexit void softingcs_remove(struct pcmcia_device *pcmcia) +{ + struct platform_device *pdev = pcmcia->priv; + + /* free bits */ + platform_device_unregister(pdev); + /* release pcmcia stuff */ + pcmcia_disable_device(pcmcia); +} + +/* + * platform_device wrapper + * pdev->resource has 2 entries: io & irq + */ +static void softingcs_pdev_release(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + kfree(pdev); +} + +static __devinit int softingcs_probe(struct pcmcia_device *pcmcia) +{ + int ret; + struct platform_device *pdev; + const struct softing_platform_data *pdat; + struct resource *pres; + struct dev { + struct platform_device pdev; + struct resource res[2]; + } *dev; + + /* find matching platform_data */ + pdat = softingcs_find_platform_data(pcmcia->manf_id, pcmcia->card_id); + if (!pdat) + return -ENOTTY; + + /* setup pcmcia device */ + pcmcia->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IOMEM | + CONF_AUTO_SET_VPP | CONF_AUTO_CHECK_VCC; + ret = pcmcia_loop_config(pcmcia, softingcs_probe_config, (void *)pdat); + if (ret) + goto pcmcia_failed; + + ret = pcmcia_enable_device(pcmcia); + if (ret < 0) + goto pcmcia_failed; + + pres = pcmcia->resource[PCMCIA_IOMEM_0]; + if (!pres) { + ret = -EBADF; + goto pcmcia_bad; + } + + /* create softing platform device */ + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) { + ret = -ENOMEM; + goto mem_failed; + } + dev->pdev.resource = dev->res; + dev->pdev.num_resources = ARRAY_SIZE(dev->res); + dev->pdev.dev.release = softingcs_pdev_release; + + pdev = &dev->pdev; + pdev->dev.platform_data = (void *)pdat; + pdev->dev.parent = &pcmcia->dev; + pcmcia->priv = pdev; + + /* platform device resources */ + pdev->resource[0].flags = IORESOURCE_MEM; + pdev->resource[0].start = pres->start; + pdev->resource[0].end = pres->end; + + pdev->resource[1].flags = IORESOURCE_IRQ; + pdev->resource[1].start = pcmcia->irq; + pdev->resource[1].end = pdev->resource[1].start; + + /* platform device setup */ + spin_lock(&softingcs_index_lock); + pdev->id = softingcs_index++; + spin_unlock(&softingcs_index_lock); + pdev->name = "softing"; + dev_set_name(&pdev->dev, "softingcs.%i", pdev->id); + ret = platform_device_register(pdev); + if (ret < 0) + goto platform_failed; + + dev_info(&pcmcia->dev, "created %s\n", dev_name(&pdev->dev)); + return 0; + +platform_failed: + kfree(dev); +mem_failed: +pcmcia_bad: +pcmcia_failed: + pcmcia_disable_device(pcmcia); + pcmcia->priv = NULL; + return ret ?: -ENODEV; +} + +static /*const*/ struct pcmcia_device_id softingcs_ids[] = { + /* softing */ + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0001), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0002), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0004), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0005), + /* vector, manufacturer? */ + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0081), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0084), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0085), + /* EDIC */ + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0102), + PCMCIA_DEVICE_MANF_CARD(0x0168, 0x0105), + PCMCIA_DEVICE_NULL, +}; + +MODULE_DEVICE_TABLE(pcmcia, softingcs_ids); + +static struct pcmcia_driver softingcs_driver = { + .owner = THIS_MODULE, + .name = "softingcs", + .id_table = softingcs_ids, + .probe = softingcs_probe, + .remove = __devexit_p(softingcs_remove), +}; + +static int __init softingcs_start(void) +{ + spin_lock_init(&softingcs_index_lock); + return pcmcia_register_driver(&softingcs_driver); +} + +static void __exit softingcs_stop(void) +{ + pcmcia_unregister_driver(&softingcs_driver); +} + +module_init(softingcs_start); +module_exit(softingcs_stop); + +MODULE_DESCRIPTION("softing CANcard driver" + ", links PCMCIA card to softing driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/softing/softing_fw.c b/drivers/net/can/softing/softing_fw.c new file mode 100644 index 000000000000..b520784fb197 --- /dev/null +++ b/drivers/net/can/softing/softing_fw.c @@ -0,0 +1,691 @@ +/* + * Copyright (C) 2008-2010 + * + * - Kurt Van Dijck, EIA Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/firmware.h> +#include <linux/sched.h> +#include <asm/div64.h> + +#include "softing.h" + +/* + * low level DPRAM command. + * Make sure that card->dpram[DPRAM_FCT_HOST] is preset + */ +static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector, + const char *msg) +{ + int ret; + unsigned long stamp; + + iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]); + iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]); + iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]); + /* be sure to flush this to the card */ + wmb(); + stamp = jiffies + 1 * HZ; + /* wait for card */ + do { + /* DPRAM_FCT_HOST is _not_ aligned */ + ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) + + (ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8); + /* don't have any cached variables */ + rmb(); + if (ret == RES_OK) + /* read return-value now */ + return ioread16(&card->dpram[DPRAM_FCT_RESULT]); + + if ((ret != vector) || time_after(jiffies, stamp)) + break; + /* process context => relax */ + usleep_range(500, 10000); + } while (1); + + ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; + dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret); + return ret; +} + +static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg) +{ + int ret; + + ret = _softing_fct_cmd(card, cmd, 0, msg); + if (ret > 0) { + dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret); + ret = -EIO; + } + return ret; +} + +int softing_bootloader_command(struct softing *card, int16_t cmd, + const char *msg) +{ + int ret; + unsigned long stamp; + + iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]); + iowrite16(cmd, &card->dpram[DPRAM_COMMAND]); + /* be sure to flush this to the card */ + wmb(); + stamp = jiffies + 3 * HZ; + /* wait for card */ + do { + ret = ioread16(&card->dpram[DPRAM_RECEIPT]); + /* don't have any cached variables */ + rmb(); + if (ret == RES_OK) + return 0; + if (time_after(jiffies, stamp)) + break; + /* process context => relax */ + usleep_range(500, 10000); + } while (!signal_pending(current)); + + ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED; + dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret); + return ret; +} + +static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr, + uint16_t *plen, const uint8_t **pdat) +{ + uint16_t checksum[2]; + const uint8_t *mem; + const uint8_t *end; + + /* + * firmware records are a binary, unaligned stream composed of: + * uint16_t type; + * uint32_t addr; + * uint16_t len; + * uint8_t dat[len]; + * uint16_t checksum; + * all values in little endian. + * We could define a struct for this, with __attribute__((packed)), + * but would that solve the alignment in _all_ cases (cfr. the + * struct itself may be an odd address)? + * + * I chose to use leXX_to_cpup() since this solves both + * endianness & alignment. + */ + mem = *pmem; + *ptype = le16_to_cpup((void *)&mem[0]); + *paddr = le32_to_cpup((void *)&mem[2]); + *plen = le16_to_cpup((void *)&mem[6]); + *pdat = &mem[8]; + /* verify checksum */ + end = &mem[8 + *plen]; + checksum[0] = le16_to_cpup((void *)end); + for (checksum[1] = 0; mem < end; ++mem) + checksum[1] += *mem; + if (checksum[0] != checksum[1]) + return -EINVAL; + /* increment */ + *pmem += 10 + *plen; + return 0; +} + +int softing_load_fw(const char *file, struct softing *card, + __iomem uint8_t *dpram, unsigned int size, int offset) +{ + const struct firmware *fw; + int ret; + const uint8_t *mem, *end, *dat; + uint16_t type, len; + uint32_t addr; + uint8_t *buf = NULL; + int buflen = 0; + int8_t type_end = 0; + + ret = request_firmware(&fw, file, &card->pdev->dev); + if (ret < 0) + return ret; + dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes" + ", offset %c0x%04x\n", + card->pdat->name, file, (unsigned int)fw->size, + (offset >= 0) ? '+' : '-', (unsigned int)abs(offset)); + /* parse the firmware */ + mem = fw->data; + end = &mem[fw->size]; + /* look for header record */ + ret = fw_parse(&mem, &type, &addr, &len, &dat); + if (ret < 0) + goto failed; + if (type != 0xffff) + goto failed; + if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) { + ret = -EINVAL; + goto failed; + } + /* ok, we had a header */ + while (mem < end) { + ret = fw_parse(&mem, &type, &addr, &len, &dat); + if (ret < 0) + goto failed; + if (type == 3) { + /* start address, not used here */ + continue; + } else if (type == 1) { + /* eof */ + type_end = 1; + break; + } else if (type != 0) { + ret = -EINVAL; + goto failed; + } + + if ((addr + len + offset) > size) + goto failed; + memcpy_toio(&dpram[addr + offset], dat, len); + /* be sure to flush caches from IO space */ + mb(); + if (len > buflen) { + /* align buflen */ + buflen = (len + (1024-1)) & ~(1024-1); + buf = krealloc(buf, buflen, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto failed; + } + } + /* verify record data */ + memcpy_fromio(buf, &dpram[addr + offset], len); + if (memcmp(buf, dat, len)) { + /* is not ok */ + dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); + ret = -EIO; + goto failed; + } + } + if (!type_end) + /* no end record seen */ + goto failed; + ret = 0; +failed: + kfree(buf); + release_firmware(fw); + if (ret < 0) + dev_info(&card->pdev->dev, "firmware %s failed\n", file); + return ret; +} + +int softing_load_app_fw(const char *file, struct softing *card) +{ + const struct firmware *fw; + const uint8_t *mem, *end, *dat; + int ret, j; + uint16_t type, len; + uint32_t addr, start_addr = 0; + unsigned int sum, rx_sum; + int8_t type_end = 0, type_entrypoint = 0; + + ret = request_firmware(&fw, file, &card->pdev->dev); + if (ret) { + dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n", + file, ret); + return ret; + } + dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n", + file, (unsigned long)fw->size); + /* parse the firmware */ + mem = fw->data; + end = &mem[fw->size]; + /* look for header record */ + ret = fw_parse(&mem, &type, &addr, &len, &dat); + if (ret) + goto failed; + ret = -EINVAL; + if (type != 0xffff) { + dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n", + type); + goto failed; + } + if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) { + dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n", + len, dat); + goto failed; + } + /* ok, we had a header */ + while (mem < end) { + ret = fw_parse(&mem, &type, &addr, &len, &dat); + if (ret) + goto failed; + + if (type == 3) { + /* start address */ + start_addr = addr; + type_entrypoint = 1; + continue; + } else if (type == 1) { + /* eof */ + type_end = 1; + break; + } else if (type != 0) { + dev_alert(&card->pdev->dev, + "unknown record type 0x%04x\n", type); + ret = -EINVAL; + goto failed; + } + + /* regualar data */ + for (sum = 0, j = 0; j < len; ++j) + sum += dat[j]; + /* work in 16bit (target) */ + sum &= 0xffff; + + memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len); + iowrite32(card->pdat->app.offs + card->pdat->app.addr, + &card->dpram[DPRAM_COMMAND + 2]); + iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]); + iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]); + iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]); + ret = softing_bootloader_command(card, 1, "loading app."); + if (ret < 0) + goto failed; + /* verify checksum */ + rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]); + if (rx_sum != sum) { + dev_alert(&card->pdev->dev, "SRAM seems to be damaged" + ", wanted 0x%04x, got 0x%04x\n", sum, rx_sum); + ret = -EIO; + goto failed; + } + } + if (!type_end || !type_entrypoint) + goto failed; + /* start application in card */ + iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]); + iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]); + ret = softing_bootloader_command(card, 3, "start app."); + if (ret < 0) + goto failed; + ret = 0; +failed: + release_firmware(fw); + if (ret < 0) + dev_info(&card->pdev->dev, "firmware %s failed\n", file); + return ret; +} + +static int softing_reset_chip(struct softing *card) +{ + int ret; + + do { + /* reset chip */ + iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]); + iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]); + iowrite8(1, &card->dpram[DPRAM_RESET]); + iowrite8(0, &card->dpram[DPRAM_RESET+1]); + + ret = softing_fct_cmd(card, 0, "reset_can"); + if (!ret) + break; + if (signal_pending(current)) + /* don't wait any longer */ + break; + } while (1); + card->tx.pending = 0; + return ret; +} + +int softing_chip_poweron(struct softing *card) +{ + int ret; + /* sync */ + ret = _softing_fct_cmd(card, 99, 0x55, "sync-a"); + if (ret < 0) + goto failed; + + ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b"); + if (ret < 0) + goto failed; + + ret = softing_reset_chip(card); + if (ret < 0) + goto failed; + /* get_serial */ + ret = softing_fct_cmd(card, 43, "get_serial_number"); + if (ret < 0) + goto failed; + card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]); + /* get_version */ + ret = softing_fct_cmd(card, 12, "get_version"); + if (ret < 0) + goto failed; + card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]); + card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]); + card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]); + card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]); + card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]); + return 0; +failed: + return ret; +} + +static void softing_initialize_timestamp(struct softing *card) +{ + uint64_t ovf; + + card->ts_ref = ktime_get(); + + /* 16MHz is the reference */ + ovf = 0x100000000ULL * 16; + do_div(ovf, card->pdat->freq ?: 16); + + card->ts_overflow = ktime_add_us(ktime_set(0, 0), ovf); +} + +ktime_t softing_raw2ktime(struct softing *card, u32 raw) +{ + uint64_t rawl; + ktime_t now, real_offset; + ktime_t target; + ktime_t tmp; + + now = ktime_get(); + real_offset = ktime_sub(ktime_get_real(), now); + + /* find nsec from card */ + rawl = raw * 16; + do_div(rawl, card->pdat->freq ?: 16); + target = ktime_add_us(card->ts_ref, rawl); + /* test for overflows */ + tmp = ktime_add(target, card->ts_overflow); + while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) { + card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow); + target = tmp; + tmp = ktime_add(target, card->ts_overflow); + } + return ktime_add(target, real_offset); +} + +static inline int softing_error_reporting(struct net_device *netdev) +{ + struct softing_priv *priv = netdev_priv(netdev); + + return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + ? 1 : 0; +} + +int softing_startstop(struct net_device *dev, int up) +{ + int ret; + struct softing *card; + struct softing_priv *priv; + struct net_device *netdev; + int bus_bitmask_start; + int j, error_reporting; + struct can_frame msg; + const struct can_bittiming *bt; + + priv = netdev_priv(dev); + card = priv->card; + + if (!card->fw.up) + return -EIO; + + ret = mutex_lock_interruptible(&card->fw.lock); + if (ret) + return ret; + + bus_bitmask_start = 0; + if (dev && up) + /* prepare to start this bus as well */ + bus_bitmask_start |= (1 << priv->index); + /* bring netdevs down */ + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + netdev = card->net[j]; + if (!netdev) + continue; + priv = netdev_priv(netdev); + + if (dev != netdev) + netif_stop_queue(netdev); + + if (netif_running(netdev)) { + if (dev != netdev) + bus_bitmask_start |= (1 << j); + priv->tx.pending = 0; + priv->tx.echo_put = 0; + priv->tx.echo_get = 0; + /* + * this bus' may just have called open_candev() + * which is rather stupid to call close_candev() + * already + * but we may come here from busoff recovery too + * in which case the echo_skb _needs_ flushing too. + * just be sure to call open_candev() again + */ + close_candev(netdev); + } + priv->can.state = CAN_STATE_STOPPED; + } + card->tx.pending = 0; + + softing_enable_irq(card, 0); + ret = softing_reset_chip(card); + if (ret) + goto failed; + if (!bus_bitmask_start) + /* no busses to be brought up */ + goto card_done; + + if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2) + && (softing_error_reporting(card->net[0]) + != softing_error_reporting(card->net[1]))) { + dev_alert(&card->pdev->dev, + "err_reporting flag differs for busses\n"); + goto invalid; + } + error_reporting = 0; + if (bus_bitmask_start & 1) { + netdev = card->net[0]; + priv = netdev_priv(netdev); + error_reporting += softing_error_reporting(netdev); + /* init chip 1 */ + bt = &priv->can.bittiming; + iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); + iowrite16(bt->phase_seg1 + bt->prop_seg, + &card->dpram[DPRAM_FCT_PARAM + 6]); + iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); + iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, + &card->dpram[DPRAM_FCT_PARAM + 10]); + ret = softing_fct_cmd(card, 1, "initialize_chip[0]"); + if (ret < 0) + goto failed; + /* set mode */ + iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); + ret = softing_fct_cmd(card, 3, "set_mode[0]"); + if (ret < 0) + goto failed; + /* set filter */ + /* 11bit id & mask */ + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); + /* 29bit id.lo & mask.lo & id.hi & mask.hi */ + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); + iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); + iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); + ret = softing_fct_cmd(card, 7, "set_filter[0]"); + if (ret < 0) + goto failed; + /* set output control */ + iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); + ret = softing_fct_cmd(card, 5, "set_output[0]"); + if (ret < 0) + goto failed; + } + if (bus_bitmask_start & 2) { + netdev = card->net[1]; + priv = netdev_priv(netdev); + error_reporting += softing_error_reporting(netdev); + /* init chip2 */ + bt = &priv->can.bittiming; + iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); + iowrite16(bt->phase_seg1 + bt->prop_seg, + &card->dpram[DPRAM_FCT_PARAM + 6]); + iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); + iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, + &card->dpram[DPRAM_FCT_PARAM + 10]); + ret = softing_fct_cmd(card, 2, "initialize_chip[1]"); + if (ret < 0) + goto failed; + /* set mode2 */ + iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); + ret = softing_fct_cmd(card, 4, "set_mode[1]"); + if (ret < 0) + goto failed; + /* set filter2 */ + /* 11bit id & mask */ + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); + /* 29bit id.lo & mask.lo & id.hi & mask.hi */ + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); + iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); + iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); + iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); + ret = softing_fct_cmd(card, 8, "set_filter[1]"); + if (ret < 0) + goto failed; + /* set output control2 */ + iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); + ret = softing_fct_cmd(card, 6, "set_output[1]"); + if (ret < 0) + goto failed; + } + /* enable_error_frame */ + /* + * Error reporting is switched off at the moment since + * the receiving of them is not yet 100% verified + * This should be enabled sooner or later + * + if (error_reporting) { + ret = softing_fct_cmd(card, 51, "enable_error_frame"); + if (ret < 0) + goto failed; + } + */ + /* initialize interface */ + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]); + iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]); + ret = softing_fct_cmd(card, 17, "initialize_interface"); + if (ret < 0) + goto failed; + /* enable_fifo */ + ret = softing_fct_cmd(card, 36, "enable_fifo"); + if (ret < 0) + goto failed; + /* enable fifo tx ack */ + ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]"); + if (ret < 0) + goto failed; + /* enable fifo tx ack2 */ + ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]"); + if (ret < 0) + goto failed; + /* start_chip */ + ret = softing_fct_cmd(card, 11, "start_chip"); + if (ret < 0) + goto failed; + iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]); + iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]); + if (card->pdat->generation < 2) { + iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); + /* flush the DPRAM caches */ + wmb(); + } + + softing_initialize_timestamp(card); + + /* + * do socketcan notifications/status changes + * from here, no errors should occur, or the failed: part + * must be reviewed + */ + memset(&msg, 0, sizeof(msg)); + msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; + msg.can_dlc = CAN_ERR_DLC; + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + if (!(bus_bitmask_start & (1 << j))) + continue; + netdev = card->net[j]; + if (!netdev) + continue; + priv = netdev_priv(netdev); + priv->can.state = CAN_STATE_ERROR_ACTIVE; + open_candev(netdev); + if (dev != netdev) { + /* notify other busses on the restart */ + softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); + ++priv->can.can_stats.restarts; + } + netif_wake_queue(netdev); + } + + /* enable interrupts */ + ret = softing_enable_irq(card, 1); + if (ret) + goto failed; +card_done: + mutex_unlock(&card->fw.lock); + return 0; +invalid: + ret = -EINVAL; +failed: + softing_enable_irq(card, 0); + softing_reset_chip(card); + mutex_unlock(&card->fw.lock); + /* bring all other interfaces down */ + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + netdev = card->net[j]; + if (!netdev) + continue; + dev_close(netdev); + } + return ret; +} + +int softing_default_output(struct net_device *netdev) +{ + struct softing_priv *priv = netdev_priv(netdev); + struct softing *card = priv->card; + + switch (priv->chip) { + case 1000: + return (card->pdat->generation < 2) ? 0xfb : 0xfa; + case 5: + return 0x60; + default: + return 0x40; + } +} diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c new file mode 100644 index 000000000000..5157e15e96eb --- /dev/null +++ b/drivers/net/can/softing/softing_main.c @@ -0,0 +1,893 @@ +/* + * Copyright (C) 2008-2010 + * + * - Kurt Van Dijck, EIA Electronics + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the version 2 of the GNU General Public License + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/version.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/interrupt.h> + +#include "softing.h" + +#define TX_ECHO_SKB_MAX (((TXMAX+1)/2)-1) + +/* + * test is a specific CAN netdev + * is online (ie. up 'n running, not sleeping, not busoff + */ +static inline int canif_is_active(struct net_device *netdev) +{ + struct can_priv *can = netdev_priv(netdev); + + if (!netif_running(netdev)) + return 0; + return (can->state <= CAN_STATE_ERROR_PASSIVE); +} + +/* reset DPRAM */ +static inline void softing_set_reset_dpram(struct softing *card) +{ + if (card->pdat->generation >= 2) { + spin_lock_bh(&card->spin); + iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) & ~1, + &card->dpram[DPRAM_V2_RESET]); + spin_unlock_bh(&card->spin); + } +} + +static inline void softing_clr_reset_dpram(struct softing *card) +{ + if (card->pdat->generation >= 2) { + spin_lock_bh(&card->spin); + iowrite8(ioread8(&card->dpram[DPRAM_V2_RESET]) | 1, + &card->dpram[DPRAM_V2_RESET]); + spin_unlock_bh(&card->spin); + } +} + +/* trigger the tx queue-ing */ +static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct softing_priv *priv = netdev_priv(dev); + struct softing *card = priv->card; + int ret; + uint8_t *ptr; + uint8_t fifo_wr, fifo_rd; + struct can_frame *cf = (struct can_frame *)skb->data; + uint8_t buf[DPRAM_TX_SIZE]; + + if (can_dropped_invalid_skb(dev, skb)) + return NETDEV_TX_OK; + + spin_lock(&card->spin); + + ret = NETDEV_TX_BUSY; + if (!card->fw.up || + (card->tx.pending >= TXMAX) || + (priv->tx.pending >= TX_ECHO_SKB_MAX)) + goto xmit_done; + fifo_wr = ioread8(&card->dpram[DPRAM_TX_WR]); + fifo_rd = ioread8(&card->dpram[DPRAM_TX_RD]); + if (fifo_wr == fifo_rd) + /* fifo full */ + goto xmit_done; + memset(buf, 0, sizeof(buf)); + ptr = buf; + *ptr = CMD_TX; + if (cf->can_id & CAN_RTR_FLAG) + *ptr |= CMD_RTR; + if (cf->can_id & CAN_EFF_FLAG) + *ptr |= CMD_XTD; + if (priv->index) + *ptr |= CMD_BUS2; + ++ptr; + *ptr++ = cf->can_dlc; + *ptr++ = (cf->can_id >> 0); + *ptr++ = (cf->can_id >> 8); + if (cf->can_id & CAN_EFF_FLAG) { + *ptr++ = (cf->can_id >> 16); + *ptr++ = (cf->can_id >> 24); + } else { + /* increment 1, not 2 as you might think */ + ptr += 1; + } + if (!(cf->can_id & CAN_RTR_FLAG)) + memcpy(ptr, &cf->data[0], cf->can_dlc); + memcpy_toio(&card->dpram[DPRAM_TX + DPRAM_TX_SIZE * fifo_wr], + buf, DPRAM_TX_SIZE); + if (++fifo_wr >= DPRAM_TX_CNT) + fifo_wr = 0; + iowrite8(fifo_wr, &card->dpram[DPRAM_TX_WR]); + card->tx.last_bus = priv->index; + ++card->tx.pending; + ++priv->tx.pending; + can_put_echo_skb(skb, dev, priv->tx.echo_put); + ++priv->tx.echo_put; + if (priv->tx.echo_put >= TX_ECHO_SKB_MAX) + priv->tx.echo_put = 0; + /* can_put_echo_skb() saves the skb, safe to return TX_OK */ + ret = NETDEV_TX_OK; +xmit_done: + spin_unlock(&card->spin); + if (card->tx.pending >= TXMAX) { + int j; + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + if (card->net[j]) + netif_stop_queue(card->net[j]); + } + } + if (ret != NETDEV_TX_OK) + netif_stop_queue(dev); + + return ret; +} + +/* + * shortcut for skb delivery + */ +int softing_netdev_rx(struct net_device *netdev, const struct can_frame *msg, + ktime_t ktime) +{ + struct sk_buff *skb; + struct can_frame *cf; + + skb = alloc_can_skb(netdev, &cf); + if (!skb) + return -ENOMEM; + memcpy(cf, msg, sizeof(*msg)); + skb->tstamp = ktime; + return netif_rx(skb); +} + +/* + * softing_handle_1 + * pop 1 entry from the DPRAM queue, and process + */ +static int softing_handle_1(struct softing *card) +{ + struct net_device *netdev; + struct softing_priv *priv; + ktime_t ktime; + struct can_frame msg; + int cnt = 0, lost_msg; + uint8_t fifo_rd, fifo_wr, cmd; + uint8_t *ptr; + uint32_t tmp_u32; + uint8_t buf[DPRAM_RX_SIZE]; + + memset(&msg, 0, sizeof(msg)); + /* test for lost msgs */ + lost_msg = ioread8(&card->dpram[DPRAM_RX_LOST]); + if (lost_msg) { + int j; + /* reset condition */ + iowrite8(0, &card->dpram[DPRAM_RX_LOST]); + /* prepare msg */ + msg.can_id = CAN_ERR_FLAG | CAN_ERR_CRTL; + msg.can_dlc = CAN_ERR_DLC; + msg.data[1] = CAN_ERR_CRTL_RX_OVERFLOW; + /* + * service to all busses, we don't know which it was applicable + * but only service busses that are online + */ + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + netdev = card->net[j]; + if (!netdev) + continue; + if (!canif_is_active(netdev)) + /* a dead bus has no overflows */ + continue; + ++netdev->stats.rx_over_errors; + softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); + } + /* prepare for other use */ + memset(&msg, 0, sizeof(msg)); + ++cnt; + } + + fifo_rd = ioread8(&card->dpram[DPRAM_RX_RD]); + fifo_wr = ioread8(&card->dpram[DPRAM_RX_WR]); + + if (++fifo_rd >= DPRAM_RX_CNT) + fifo_rd = 0; + if (fifo_wr == fifo_rd) + return cnt; + + memcpy_fromio(buf, &card->dpram[DPRAM_RX + DPRAM_RX_SIZE*fifo_rd], + DPRAM_RX_SIZE); + mb(); + /* trigger dual port RAM */ + iowrite8(fifo_rd, &card->dpram[DPRAM_RX_RD]); + + ptr = buf; + cmd = *ptr++; + if (cmd == 0xff) + /* not quite usefull, probably the card has got out */ + return 0; + netdev = card->net[0]; + if (cmd & CMD_BUS2) + netdev = card->net[1]; + priv = netdev_priv(netdev); + + if (cmd & CMD_ERR) { + uint8_t can_state, state; + + state = *ptr++; + + msg.can_id = CAN_ERR_FLAG; + msg.can_dlc = CAN_ERR_DLC; + + if (state & SF_MASK_BUSOFF) { + can_state = CAN_STATE_BUS_OFF; + msg.can_id |= CAN_ERR_BUSOFF; + state = STATE_BUSOFF; + } else if (state & SF_MASK_EPASSIVE) { + can_state = CAN_STATE_ERROR_PASSIVE; + msg.can_id |= CAN_ERR_CRTL; + msg.data[1] = CAN_ERR_CRTL_TX_PASSIVE; + state = STATE_EPASSIVE; + } else { + can_state = CAN_STATE_ERROR_ACTIVE; + msg.can_id |= CAN_ERR_CRTL; + state = STATE_EACTIVE; + } + /* update DPRAM */ + iowrite8(state, &card->dpram[priv->index ? + DPRAM_INFO_BUSSTATE2 : DPRAM_INFO_BUSSTATE]); + /* timestamp */ + tmp_u32 = le32_to_cpup((void *)ptr); + ptr += 4; + ktime = softing_raw2ktime(card, tmp_u32); + + ++netdev->stats.rx_errors; + /* update internal status */ + if (can_state != priv->can.state) { + priv->can.state = can_state; + if (can_state == CAN_STATE_ERROR_PASSIVE) + ++priv->can.can_stats.error_passive; + else if (can_state == CAN_STATE_BUS_OFF) { + /* this calls can_close_cleanup() */ + can_bus_off(netdev); + netif_stop_queue(netdev); + } + /* trigger socketcan */ + softing_netdev_rx(netdev, &msg, ktime); + } + + } else { + if (cmd & CMD_RTR) + msg.can_id |= CAN_RTR_FLAG; + msg.can_dlc = get_can_dlc(*ptr++); + if (cmd & CMD_XTD) { + msg.can_id |= CAN_EFF_FLAG; + msg.can_id |= le32_to_cpup((void *)ptr); + ptr += 4; + } else { + msg.can_id |= le16_to_cpup((void *)ptr); + ptr += 2; + } + /* timestamp */ + tmp_u32 = le32_to_cpup((void *)ptr); + ptr += 4; + ktime = softing_raw2ktime(card, tmp_u32); + if (!(msg.can_id & CAN_RTR_FLAG)) + memcpy(&msg.data[0], ptr, 8); + ptr += 8; + /* update socket */ + if (cmd & CMD_ACK) { + /* acknowledge, was tx msg */ + struct sk_buff *skb; + skb = priv->can.echo_skb[priv->tx.echo_get]; + if (skb) + skb->tstamp = ktime; + can_get_echo_skb(netdev, priv->tx.echo_get); + ++priv->tx.echo_get; + if (priv->tx.echo_get >= TX_ECHO_SKB_MAX) + priv->tx.echo_get = 0; + if (priv->tx.pending) + --priv->tx.pending; + if (card->tx.pending) + --card->tx.pending; + ++netdev->stats.tx_packets; + if (!(msg.can_id & CAN_RTR_FLAG)) + netdev->stats.tx_bytes += msg.can_dlc; + } else { + int ret; + + ret = softing_netdev_rx(netdev, &msg, ktime); + if (ret == NET_RX_SUCCESS) { + ++netdev->stats.rx_packets; + if (!(msg.can_id & CAN_RTR_FLAG)) + netdev->stats.rx_bytes += msg.can_dlc; + } else { + ++netdev->stats.rx_dropped; + } + } + } + ++cnt; + return cnt; +} + +/* + * real interrupt handler + */ +static irqreturn_t softing_irq_thread(int irq, void *dev_id) +{ + struct softing *card = (struct softing *)dev_id; + struct net_device *netdev; + struct softing_priv *priv; + int j, offset, work_done; + + work_done = 0; + spin_lock_bh(&card->spin); + while (softing_handle_1(card) > 0) { + ++card->irq.svc_count; + ++work_done; + } + spin_unlock_bh(&card->spin); + /* resume tx queue's */ + offset = card->tx.last_bus; + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + if (card->tx.pending >= TXMAX) + break; + netdev = card->net[(j + offset + 1) % card->pdat->nbus]; + if (!netdev) + continue; + priv = netdev_priv(netdev); + if (!canif_is_active(netdev)) + /* it makes no sense to wake dead busses */ + continue; + if (priv->tx.pending >= TX_ECHO_SKB_MAX) + continue; + ++work_done; + netif_wake_queue(netdev); + } + return work_done ? IRQ_HANDLED : IRQ_NONE; +} + +/* + * interrupt routines: + * schedule the 'real interrupt handler' + */ +static irqreturn_t softing_irq_v2(int irq, void *dev_id) +{ + struct softing *card = (struct softing *)dev_id; + uint8_t ir; + + ir = ioread8(&card->dpram[DPRAM_V2_IRQ_TOHOST]); + iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); + return (1 == ir) ? IRQ_WAKE_THREAD : IRQ_NONE; +} + +static irqreturn_t softing_irq_v1(int irq, void *dev_id) +{ + struct softing *card = (struct softing *)dev_id; + uint8_t ir; + + ir = ioread8(&card->dpram[DPRAM_IRQ_TOHOST]); + iowrite8(0, &card->dpram[DPRAM_IRQ_TOHOST]); + return ir ? IRQ_WAKE_THREAD : IRQ_NONE; +} + +/* + * netdev/candev inter-operability + */ +static int softing_netdev_open(struct net_device *ndev) +{ + int ret; + + /* check or determine and set bittime */ + ret = open_candev(ndev); + if (!ret) + ret = softing_startstop(ndev, 1); + return ret; +} + +static int softing_netdev_stop(struct net_device *ndev) +{ + int ret; + + netif_stop_queue(ndev); + + /* softing cycle does close_candev() */ + ret = softing_startstop(ndev, 0); + return ret; +} + +static int softing_candev_set_mode(struct net_device *ndev, enum can_mode mode) +{ + int ret; + + switch (mode) { + case CAN_MODE_START: + /* softing_startstop does close_candev() */ + ret = softing_startstop(ndev, 1); + return ret; + case CAN_MODE_STOP: + case CAN_MODE_SLEEP: + return -EOPNOTSUPP; + } + return 0; +} + +/* + * Softing device management helpers + */ +int softing_enable_irq(struct softing *card, int enable) +{ + int ret; + + if (!card->irq.nr) { + return 0; + } else if (card->irq.requested && !enable) { + free_irq(card->irq.nr, card); + card->irq.requested = 0; + } else if (!card->irq.requested && enable) { + ret = request_threaded_irq(card->irq.nr, + (card->pdat->generation >= 2) ? + softing_irq_v2 : softing_irq_v1, + softing_irq_thread, IRQF_SHARED, + dev_name(&card->pdev->dev), card); + if (ret) { + dev_alert(&card->pdev->dev, + "request_threaded_irq(%u) failed\n", + card->irq.nr); + return ret; + } + card->irq.requested = 1; + } + return 0; +} + +static void softing_card_shutdown(struct softing *card) +{ + int fw_up = 0; + + if (mutex_lock_interruptible(&card->fw.lock)) + /* return -ERESTARTSYS */; + fw_up = card->fw.up; + card->fw.up = 0; + + if (card->irq.requested && card->irq.nr) { + free_irq(card->irq.nr, card); + card->irq.requested = 0; + } + if (fw_up) { + if (card->pdat->enable_irq) + card->pdat->enable_irq(card->pdev, 0); + softing_set_reset_dpram(card); + if (card->pdat->reset) + card->pdat->reset(card->pdev, 1); + } + mutex_unlock(&card->fw.lock); +} + +static __devinit int softing_card_boot(struct softing *card) +{ + int ret, j; + static const uint8_t stream[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, }; + unsigned char back[sizeof(stream)]; + + if (mutex_lock_interruptible(&card->fw.lock)) + return -ERESTARTSYS; + if (card->fw.up) { + mutex_unlock(&card->fw.lock); + return 0; + } + /* reset board */ + if (card->pdat->enable_irq) + card->pdat->enable_irq(card->pdev, 1); + /* boot card */ + softing_set_reset_dpram(card); + if (card->pdat->reset) + card->pdat->reset(card->pdev, 1); + for (j = 0; (j + sizeof(stream)) < card->dpram_size; + j += sizeof(stream)) { + + memcpy_toio(&card->dpram[j], stream, sizeof(stream)); + /* flush IO cache */ + mb(); + memcpy_fromio(back, &card->dpram[j], sizeof(stream)); + + if (!memcmp(back, stream, sizeof(stream))) + continue; + /* memory is not equal */ + dev_alert(&card->pdev->dev, "dpram failed at 0x%04x\n", j); + ret = -EIO; + goto failed; + } + wmb(); + /* load boot firmware */ + ret = softing_load_fw(card->pdat->boot.fw, card, card->dpram, + card->dpram_size, + card->pdat->boot.offs - card->pdat->boot.addr); + if (ret < 0) + goto failed; + /* load loader firmware */ + ret = softing_load_fw(card->pdat->load.fw, card, card->dpram, + card->dpram_size, + card->pdat->load.offs - card->pdat->load.addr); + if (ret < 0) + goto failed; + + if (card->pdat->reset) + card->pdat->reset(card->pdev, 0); + softing_clr_reset_dpram(card); + ret = softing_bootloader_command(card, 0, "card boot"); + if (ret < 0) + goto failed; + ret = softing_load_app_fw(card->pdat->app.fw, card); + if (ret < 0) + goto failed; + + ret = softing_chip_poweron(card); + if (ret < 0) + goto failed; + + card->fw.up = 1; + mutex_unlock(&card->fw.lock); + return 0; +failed: + card->fw.up = 0; + if (card->pdat->enable_irq) + card->pdat->enable_irq(card->pdev, 0); + softing_set_reset_dpram(card); + if (card->pdat->reset) + card->pdat->reset(card->pdev, 1); + mutex_unlock(&card->fw.lock); + return ret; +} + +/* + * netdev sysfs + */ +static ssize_t show_channel(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct net_device *ndev = to_net_dev(dev); + struct softing_priv *priv = netdev2softing(ndev); + + return sprintf(buf, "%i\n", priv->index); +} + +static ssize_t show_chip(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct net_device *ndev = to_net_dev(dev); + struct softing_priv *priv = netdev2softing(ndev); + + return sprintf(buf, "%i\n", priv->chip); +} + +static ssize_t show_output(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct net_device *ndev = to_net_dev(dev); + struct softing_priv *priv = netdev2softing(ndev); + + return sprintf(buf, "0x%02x\n", priv->output); +} + +static ssize_t store_output(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct net_device *ndev = to_net_dev(dev); + struct softing_priv *priv = netdev2softing(ndev); + struct softing *card = priv->card; + unsigned long val; + int ret; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + val &= 0xFF; + + ret = mutex_lock_interruptible(&card->fw.lock); + if (ret) + return -ERESTARTSYS; + if (netif_running(ndev)) { + mutex_unlock(&card->fw.lock); + return -EBUSY; + } + priv->output = val; + mutex_unlock(&card->fw.lock); + return count; +} + +static const DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); +static const DEVICE_ATTR(chip, S_IRUGO, show_chip, NULL); +static const DEVICE_ATTR(output, S_IRUGO | S_IWUSR, show_output, store_output); + +static const struct attribute *const netdev_sysfs_attrs[] = { + &dev_attr_channel.attr, + &dev_attr_chip.attr, + &dev_attr_output.attr, + NULL, +}; +static const struct attribute_group netdev_sysfs_group = { + .name = NULL, + .attrs = (struct attribute **)netdev_sysfs_attrs, +}; + +static const struct net_device_ops softing_netdev_ops = { + .ndo_open = softing_netdev_open, + .ndo_stop = softing_netdev_stop, + .ndo_start_xmit = softing_netdev_start_xmit, +}; + +static const struct can_bittiming_const softing_btr_const = { + .tseg1_min = 1, + .tseg1_max = 16, + .tseg2_min = 1, + .tseg2_max = 8, + .sjw_max = 4, /* overruled */ + .brp_min = 1, + .brp_max = 32, /* overruled */ + .brp_inc = 1, +}; + + +static __devinit struct net_device *softing_netdev_create(struct softing *card, + uint16_t chip_id) +{ + struct net_device *netdev; + struct softing_priv *priv; + + netdev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX); + if (!netdev) { + dev_alert(&card->pdev->dev, "alloc_candev failed\n"); + return NULL; + } + priv = netdev_priv(netdev); + priv->netdev = netdev; + priv->card = card; + memcpy(&priv->btr_const, &softing_btr_const, sizeof(priv->btr_const)); + priv->btr_const.brp_max = card->pdat->max_brp; + priv->btr_const.sjw_max = card->pdat->max_sjw; + priv->can.bittiming_const = &priv->btr_const; + priv->can.clock.freq = 8000000; + priv->chip = chip_id; + priv->output = softing_default_output(netdev); + SET_NETDEV_DEV(netdev, &card->pdev->dev); + + netdev->flags |= IFF_ECHO; + netdev->netdev_ops = &softing_netdev_ops; + priv->can.do_set_mode = softing_candev_set_mode; + priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; + + return netdev; +} + +static __devinit int softing_netdev_register(struct net_device *netdev) +{ + int ret; + + netdev->sysfs_groups[0] = &netdev_sysfs_group; + ret = register_candev(netdev); + if (ret) { + dev_alert(&netdev->dev, "register failed\n"); + return ret; + } + return 0; +} + +static void softing_netdev_cleanup(struct net_device *netdev) +{ + unregister_candev(netdev); + free_candev(netdev); +} + +/* + * sysfs for Platform device + */ +#define DEV_ATTR_RO(name, member) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct softing *card = platform_get_drvdata(to_platform_device(dev)); \ + return sprintf(buf, "%u\n", card->member); \ +} \ +static DEVICE_ATTR(name, 0444, show_##name, NULL) + +#define DEV_ATTR_RO_STR(name, member) \ +static ssize_t show_##name(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct softing *card = platform_get_drvdata(to_platform_device(dev)); \ + return sprintf(buf, "%s\n", card->member); \ +} \ +static DEVICE_ATTR(name, 0444, show_##name, NULL) + +DEV_ATTR_RO(serial, id.serial); +DEV_ATTR_RO_STR(firmware, pdat->app.fw); +DEV_ATTR_RO(firmware_version, id.fw_version); +DEV_ATTR_RO_STR(hardware, pdat->name); +DEV_ATTR_RO(hardware_version, id.hw_version); +DEV_ATTR_RO(license, id.license); +DEV_ATTR_RO(frequency, id.freq); +DEV_ATTR_RO(txpending, tx.pending); + +static struct attribute *softing_pdev_attrs[] = { + &dev_attr_serial.attr, + &dev_attr_firmware.attr, + &dev_attr_firmware_version.attr, + &dev_attr_hardware.attr, + &dev_attr_hardware_version.attr, + &dev_attr_license.attr, + &dev_attr_frequency.attr, + &dev_attr_txpending.attr, + NULL, +}; + +static const struct attribute_group softing_pdev_group = { + .name = NULL, + .attrs = softing_pdev_attrs, +}; + +/* + * platform driver + */ +static __devexit int softing_pdev_remove(struct platform_device *pdev) +{ + struct softing *card = platform_get_drvdata(pdev); + int j; + + /* first, disable card*/ + softing_card_shutdown(card); + + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + if (!card->net[j]) + continue; + softing_netdev_cleanup(card->net[j]); + card->net[j] = NULL; + } + sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group); + + iounmap(card->dpram); + kfree(card); + return 0; +} + +static __devinit int softing_pdev_probe(struct platform_device *pdev) +{ + const struct softing_platform_data *pdat = pdev->dev.platform_data; + struct softing *card; + struct net_device *netdev; + struct softing_priv *priv; + struct resource *pres; + int ret; + int j; + + if (!pdat) { + dev_warn(&pdev->dev, "no platform data\n"); + return -EINVAL; + } + if (pdat->nbus > ARRAY_SIZE(card->net)) { + dev_warn(&pdev->dev, "%u nets??\n", pdat->nbus); + return -EINVAL; + } + + card = kzalloc(sizeof(*card), GFP_KERNEL); + if (!card) + return -ENOMEM; + card->pdat = pdat; + card->pdev = pdev; + platform_set_drvdata(pdev, card); + mutex_init(&card->fw.lock); + spin_lock_init(&card->spin); + + ret = -EINVAL; + pres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!pres) + goto platform_resource_failed;; + card->dpram_phys = pres->start; + card->dpram_size = pres->end - pres->start + 1; + card->dpram = ioremap_nocache(card->dpram_phys, card->dpram_size); + if (!card->dpram) { + dev_alert(&card->pdev->dev, "dpram ioremap failed\n"); + goto ioremap_failed; + } + + pres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (pres) + card->irq.nr = pres->start; + + /* reset card */ + ret = softing_card_boot(card); + if (ret < 0) { + dev_alert(&pdev->dev, "failed to boot\n"); + goto boot_failed; + } + + /* only now, the chip's are known */ + card->id.freq = card->pdat->freq; + + ret = sysfs_create_group(&pdev->dev.kobj, &softing_pdev_group); + if (ret < 0) { + dev_alert(&card->pdev->dev, "sysfs failed\n"); + goto sysfs_failed; + } + + ret = -ENOMEM; + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + card->net[j] = netdev = + softing_netdev_create(card, card->id.chip[j]); + if (!netdev) { + dev_alert(&pdev->dev, "failed to make can[%i]", j); + goto netdev_failed; + } + priv = netdev_priv(card->net[j]); + priv->index = j; + ret = softing_netdev_register(netdev); + if (ret) { + free_candev(netdev); + card->net[j] = NULL; + dev_alert(&card->pdev->dev, + "failed to register can[%i]\n", j); + goto netdev_failed; + } + } + dev_info(&card->pdev->dev, "%s ready.\n", card->pdat->name); + return 0; + +netdev_failed: + for (j = 0; j < ARRAY_SIZE(card->net); ++j) { + if (!card->net[j]) + continue; + softing_netdev_cleanup(card->net[j]); + } + sysfs_remove_group(&pdev->dev.kobj, &softing_pdev_group); +sysfs_failed: + softing_card_shutdown(card); +boot_failed: + iounmap(card->dpram); +ioremap_failed: +platform_resource_failed: + kfree(card); + return ret; +} + +static struct platform_driver softing_driver = { + .driver = { + .name = "softing", + .owner = THIS_MODULE, + }, + .probe = softing_pdev_probe, + .remove = __devexit_p(softing_pdev_remove), +}; + +MODULE_ALIAS("platform:softing"); + +static int __init softing_start(void) +{ + return platform_driver_register(&softing_driver); +} + +static void __exit softing_stop(void) +{ + platform_driver_unregister(&softing_driver); +} + +module_init(softing_start); +module_exit(softing_stop); + +MODULE_DESCRIPTION("Softing DPRAM CAN driver"); +MODULE_AUTHOR("Kurt Van Dijck <kurt.van.dijck@eia.be>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/softing/softing_platform.h b/drivers/net/can/softing/softing_platform.h new file mode 100644 index 000000000000..ebbf69815623 --- /dev/null +++ b/drivers/net/can/softing/softing_platform.h @@ -0,0 +1,40 @@ + +#include <linux/platform_device.h> + +#ifndef _SOFTING_DEVICE_H_ +#define _SOFTING_DEVICE_H_ + +/* softing firmware directory prefix */ +#define fw_dir "softing-4.6/" + +struct softing_platform_data { + unsigned int manf; + unsigned int prod; + /* + * generation + * 1st with NEC or SJA1000 + * 8bit, exclusive interrupt, ... + * 2nd only SJA1000 + * 16bit, shared interrupt + */ + int generation; + int nbus; /* # busses on device */ + unsigned int freq; /* operating frequency in Hz */ + unsigned int max_brp; + unsigned int max_sjw; + unsigned long dpram_size; + const char *name; + struct { + unsigned long offs; + unsigned long addr; + const char *fw; + } boot, load, app; + /* + * reset() function + * bring pdev in or out of reset, depending on value + */ + int (*reset)(struct platform_device *pdev, int value); + int (*enable_irq)(struct platform_device *pdev, int value); +}; + +#endif diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 263a2944566f..7ff170cbc7dc 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -699,13 +699,13 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma) static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma) { int i; - u32 *page_table = dma->pgtbl; + __le32 *page_table = (__le32 *) dma->pgtbl; for (i = 0; i < dma->num_pages; i++) { /* Each entry needs to be in big endian format. */ - *page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32); + *page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32); page_table++; - *page_table = (u32) dma->pg_map_arr[i]; + *page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff); page_table++; } } @@ -713,13 +713,13 @@ static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma) static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma) { int i; - u32 *page_table = dma->pgtbl; + __le32 *page_table = (__le32 *) dma->pgtbl; for (i = 0; i < dma->num_pages; i++) { /* Each entry needs to be in little endian format. */ - *page_table = dma->pg_map_arr[i] & 0xffffffff; + *page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff); page_table++; - *page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32); + *page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32); page_table++; } } diff --git a/drivers/net/cxgb4/cxgb4_main.c b/drivers/net/cxgb4/cxgb4_main.c index 059c1eec8c3f..ec35d458102c 100644 --- a/drivers/net/cxgb4/cxgb4_main.c +++ b/drivers/net/cxgb4/cxgb4_main.c @@ -2710,6 +2710,8 @@ static int cxgb_open(struct net_device *dev) struct port_info *pi = netdev_priv(dev); struct adapter *adapter = pi->adapter; + netif_carrier_off(dev); + if (!(adapter->flags & FULL_INIT_DONE)) { err = cxgb_up(adapter); if (err < 0) @@ -3661,7 +3663,6 @@ static int __devinit init_one(struct pci_dev *pdev, pi->xact_addr_filt = -1; pi->rx_offload = RX_CSO; pi->port_id = i; - netif_carrier_off(netdev); netdev->irq = pdev->irq; netdev->features |= NETIF_F_SG | TSO_FLAGS; diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c index d7355306a738..1bf12339441b 100644 --- a/drivers/net/pch_gbe/pch_gbe_main.c +++ b/drivers/net/pch_gbe/pch_gbe_main.c @@ -2247,7 +2247,7 @@ static void pch_gbe_remove(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct pch_gbe_adapter *adapter = netdev_priv(netdev); - flush_scheduled_work(); + cancel_work_sync(&adapter->reset_task); unregister_netdev(netdev); pch_gbe_hal_phy_hw_reset(&adapter->hw); diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7841a8f69998..93b32d366611 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -60,12 +60,6 @@ #define BAR_0 0 #define BAR_2 2 -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -#define TG3_VLAN_TAG_USED 1 -#else -#define TG3_VLAN_TAG_USED 0 -#endif - #include "tg3.h" #define DRV_MODULE_NAME "tg3" @@ -134,9 +128,6 @@ TG3_TX_RING_SIZE) #define NEXT_TX(N) (((N) + 1) & (TG3_TX_RING_SIZE - 1)) -#define TG3_RX_DMA_ALIGN 16 -#define TG3_RX_HEADROOM ALIGN(VLAN_HLEN, TG3_RX_DMA_ALIGN) - #define TG3_DMA_BYTE_ENAB 64 #define TG3_RX_STD_DMA_SZ 1536 @@ -4722,8 +4713,6 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) struct sk_buff *skb; dma_addr_t dma_addr; u32 opaque_key, desc_idx, *post_ptr; - bool hw_vlan __maybe_unused = false; - u16 vtag __maybe_unused = 0; desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK; opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK; @@ -4782,12 +4771,12 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) tg3_recycle_rx(tnapi, tpr, opaque_key, desc_idx, *post_ptr); - copy_skb = netdev_alloc_skb(tp->dev, len + VLAN_HLEN + + copy_skb = netdev_alloc_skb(tp->dev, len + TG3_RAW_IP_ALIGN); if (copy_skb == NULL) goto drop_it_no_recycle; - skb_reserve(copy_skb, TG3_RAW_IP_ALIGN + VLAN_HLEN); + skb_reserve(copy_skb, TG3_RAW_IP_ALIGN); skb_put(copy_skb, len); pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE); skb_copy_from_linear_data(skb, copy_skb->data, len); @@ -4814,30 +4803,11 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget) } if (desc->type_flags & RXD_FLAG_VLAN && - !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) { - vtag = desc->err_vlan & RXD_VLAN_MASK; -#if TG3_VLAN_TAG_USED - if (tp->vlgrp) - hw_vlan = true; - else -#endif - { - struct vlan_ethhdr *ve = (struct vlan_ethhdr *) - __skb_push(skb, VLAN_HLEN); - - memmove(ve, skb->data + VLAN_HLEN, - ETH_ALEN * 2); - ve->h_vlan_proto = htons(ETH_P_8021Q); - ve->h_vlan_TCI = htons(vtag); - } - } + !(tp->rx_mode & RX_MODE_KEEP_VLAN_TAG)) + __vlan_hwaccel_put_tag(skb, + desc->err_vlan & RXD_VLAN_MASK); -#if TG3_VLAN_TAG_USED - if (hw_vlan) - vlan_gro_receive(&tnapi->napi, tp->vlgrp, vtag, skb); - else -#endif - napi_gro_receive(&tnapi->napi, skb); + napi_gro_receive(&tnapi->napi, skb); received++; budget--; @@ -5740,11 +5710,9 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, base_flags |= TXD_FLAG_TCPUDP_CSUM; } -#if TG3_VLAN_TAG_USED if (vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | (vlan_tx_tag_get(skb) << 16)); -#endif len = skb_headlen(skb); @@ -5986,11 +5954,10 @@ static netdev_tx_t tg3_start_xmit_dma_bug(struct sk_buff *skb, } } } -#if TG3_VLAN_TAG_USED + if (vlan_tx_tag_present(skb)) base_flags |= (TXD_FLAG_VLAN | (vlan_tx_tag_get(skb) << 16)); -#endif if ((tp->tg3_flags3 & TG3_FLG3_USE_JUMBO_BDFLAG) && !mss && skb->len > VLAN_ETH_FRAME_LEN) @@ -9532,17 +9499,10 @@ static void __tg3_set_rx_mode(struct net_device *dev) rx_mode = tp->rx_mode & ~(RX_MODE_PROMISC | RX_MODE_KEEP_VLAN_TAG); +#if !defined(CONFIG_VLAN_8021Q) && !defined(CONFIG_VLAN_8021Q_MODULE) /* When ASF is in use, we always keep the RX_MODE_KEEP_VLAN_TAG * flag clear. */ -#if TG3_VLAN_TAG_USED - if (!tp->vlgrp && - !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) - rx_mode |= RX_MODE_KEEP_VLAN_TAG; -#else - /* By definition, VLAN is disabled always in this - * case. - */ if (!(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) rx_mode |= RX_MODE_KEEP_VLAN_TAG; #endif @@ -11230,31 +11190,6 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EOPNOTSUPP; } -#if TG3_VLAN_TAG_USED -static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -{ - struct tg3 *tp = netdev_priv(dev); - - if (!netif_running(dev)) { - tp->vlgrp = grp; - return; - } - - tg3_netif_stop(tp); - - tg3_full_lock(tp, 0); - - tp->vlgrp = grp; - - /* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */ - __tg3_set_rx_mode(dev); - - tg3_netif_start(tp); - - tg3_full_unlock(tp); -} -#endif - static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec) { struct tg3 *tp = netdev_priv(dev); @@ -13066,9 +13001,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *); static void inline vlan_features_add(struct net_device *dev, unsigned long flags) { -#if TG3_VLAN_TAG_USED dev->vlan_features |= flags; -#endif } static inline u32 tg3_rx_ret_ring_size(struct tg3 *tp) @@ -13861,11 +13794,11 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) else tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES; - tp->rx_offset = NET_IP_ALIGN + TG3_RX_HEADROOM; + tp->rx_offset = NET_IP_ALIGN; tp->rx_copy_thresh = TG3_RX_COPY_THRESHOLD; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 && (tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0) { - tp->rx_offset -= NET_IP_ALIGN; + tp->rx_offset = 0; #ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS tp->rx_copy_thresh = ~(u16)0; #endif @@ -14629,9 +14562,6 @@ static const struct net_device_ops tg3_netdev_ops = { .ndo_do_ioctl = tg3_ioctl, .ndo_tx_timeout = tg3_tx_timeout, .ndo_change_mtu = tg3_change_mtu, -#if TG3_VLAN_TAG_USED - .ndo_vlan_rx_register = tg3_vlan_rx_register, -#endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tg3_poll_controller, #endif @@ -14648,9 +14578,6 @@ static const struct net_device_ops tg3_netdev_ops_dma_bug = { .ndo_do_ioctl = tg3_ioctl, .ndo_tx_timeout = tg3_tx_timeout, .ndo_change_mtu = tg3_change_mtu, -#if TG3_VLAN_TAG_USED - .ndo_vlan_rx_register = tg3_vlan_rx_register, -#endif #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = tg3_poll_controller, #endif @@ -14700,9 +14627,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, SET_NETDEV_DEV(dev, &pdev->dev); -#if TG3_VLAN_TAG_USED dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#endif tp = netdev_priv(dev); tp->pdev = pdev; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index d62c8d937c82..f528243e1a4f 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2808,9 +2808,6 @@ struct tg3 { u32 rx_std_max_post; u32 rx_offset; u32 rx_pkt_map_sz; -#if TG3_VLAN_TAG_USED - struct vlan_group *vlgrp; -#endif /* begin "everything else" cacheline(s) section */ diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index 5e98643a4a21..7dc84971f26f 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -406,6 +406,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) { err("Firmware too big: %zu", fw->size); + release_firmware(fw); return -ENOSPC; } data_len = fw->size; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 1afb8bb85756..9f01e50d5cda 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -369,6 +369,9 @@ static void ath9k_hw_init_config(struct ath_hw *ah) else ah->config.ht_enable = 0; + /* PAPRD needs some more work to be enabled */ + ah->config.paprd_disable = 1; + ah->config.rx_intr_mitigation = true; ah->config.pcieSerDesWrite = true; @@ -1933,7 +1936,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->rx_status_len = sizeof(struct ar9003_rxs); pCap->tx_desc_len = sizeof(struct ar9003_txc); pCap->txs_len = sizeof(struct ar9003_txs); - if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) + if (!ah->config.paprd_disable && + ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) pCap->hw_caps |= ATH9K_HW_CAP_PAPRD; } else { pCap->tx_desc_len = sizeof(struct ath_desc); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 5a3dfec45e96..ea9fde670646 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -225,6 +225,7 @@ struct ath9k_ops_config { u32 pcie_waen; u8 analog_shiftreg; u8 ht_enable; + u8 paprd_disable; u32 ofdm_trig_low; u32 ofdm_trig_high; u32 cck_trig_high; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f90a6ca94a76..c79c97be6cd4 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -592,14 +592,12 @@ void ath9k_tasklet(unsigned long data) u32 status = sc->intrstatus; u32 rxmask; - ath9k_ps_wakeup(sc); - if (status & ATH9K_INT_FATAL) { ath_reset(sc, true); - ath9k_ps_restore(sc); return; } + ath9k_ps_wakeup(sc); spin_lock(&sc->sc_pcu_lock); if (!ath9k_hw_check_alive(ah)) @@ -969,6 +967,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Stop ANI */ del_timer_sync(&common->ani.timer); + ath9k_ps_wakeup(sc); spin_lock_bh(&sc->sc_pcu_lock); ieee80211_stop_queues(hw); @@ -1015,6 +1014,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) /* Start ANI */ ath_start_ani(common); + ath9k_ps_restore(sc); return r; } @@ -1701,7 +1701,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) skip_chan_change: if (changed & IEEE80211_CONF_CHANGE_POWER) { sc->config.txpowlimit = 2 * conf->power_level; + ath9k_ps_wakeup(sc); ath_update_txpow(sc); + ath9k_ps_restore(sc); } spin_lock_bh(&sc->wiphy_lock); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 332d1feb5c18..33a37edbaf79 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2113,9 +2113,7 @@ static void ath_tx_complete_poll_work(struct work_struct *work) if (needreset) { ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET, "tx hung, resetting the chip\n"); - ath9k_ps_wakeup(sc); ath_reset(sc, true); - ath9k_ps_restore(sc); } ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3f1e5f1bf847..91a9f5253469 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2624,6 +2624,7 @@ struct iwl_cfg iwl4965_agn_cfg = { .fw_name_pre = IWL4965_FW_PRE, .ucode_api_max = IWL4965_UCODE_API_MAX, .ucode_api_min = IWL4965_UCODE_API_MIN, + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_ABC, .eeprom_ver = EEPROM_4965_EEPROM_VERSION, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c index 14ceb4df72f6..27b5a3eec9dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -152,11 +152,14 @@ int iwl_eeprom_check_sku(struct iwl_priv *priv) eeprom_sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP); - priv->cfg->sku = ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> + if (!priv->cfg->sku) { + /* not using sku overwrite */ + priv->cfg->sku = + ((eeprom_sku & EEPROM_SKU_CAP_BAND_SELECTION) >> EEPROM_SKU_CAP_BAND_POS); - if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) - priv->cfg->sku |= IWL_SKU_N; - + if (eeprom_sku & EEPROM_SKU_CAP_11N_ENABLE) + priv->cfg->sku |= IWL_SKU_N; + } if (!priv->cfg->sku) { IWL_ERR(priv, "Invalid device sku\n"); return -EINVAL; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 0b4e8590cbb7..029be3c6c030 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2446,6 +2446,7 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, + { USB_DEVICE(0x0812, 0x3101), USB_DEVICE_DATA(&rt73usb_ops) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 0fa36aa6701a..1758d4463247 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -619,6 +619,13 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) struct sk_buff *uskb = NULL; u8 *pdata; uskb = dev_alloc_skb(skb->len + 128); + if (!uskb) { + RT_TRACE(rtlpriv, + (COMP_INTR | COMP_RECV), + DBG_EMERG, + ("can't alloc rx skb\n")); + goto done; + } memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); @@ -641,7 +648,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) new_skb = dev_alloc_skb(rtlpci->rxbuffersize); if (unlikely(!new_skb)) { RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV), - DBG_DMESG, + DBG_EMERG, ("can't alloc skb for rx\n")); goto done; } @@ -1066,9 +1073,9 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) struct sk_buff *skb = dev_alloc_skb(rtlpci->rxbuffersize); u32 bufferaddress; - entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; if (!skb) return 0; + entry = &rtlpci->rx_ring[rx_queue_idx].desc[i]; /*skb->dev = dev; */ diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index f374c5961b32..a91d510a798b 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -26,7 +26,6 @@ #include <linux/sfi.h> #include <asm/mrst.h> #include <asm/intel_scu_ipc.h> -#include <asm/mrst.h> /* IPC defines the following message types */ #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */ diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c index 0e298dba9fc8..29b8ab44ea47 100644 --- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c +++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c @@ -360,8 +360,8 @@ int PSSendOps(void *arg) status = 1; goto complete; } - len = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size; - memcpy(config_bdaddr, firmware->data,len); + len = min(firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1); + memcpy(config_bdaddr, firmware->data, len); config_bdaddr[len] = '\0'; write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); A_RELEASE_FIRMWARE(firmware); diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c b/drivers/staging/brcm80211/sys/wl_mac80211.c index bdd629d72a75..f1235884cc5d 100644 --- a/drivers/staging/brcm80211/sys/wl_mac80211.c +++ b/drivers/staging/brcm80211/sys/wl_mac80211.c @@ -209,11 +209,8 @@ static void wl_ops_stop(struct ieee80211_hw *hw) struct wl_info *wl = hw->priv; ASSERT(wl); WL_LOCK(wl); - wl_down(wl); ieee80211_stop_queues(hw); WL_UNLOCK(wl); - - return; } static int @@ -246,7 +243,14 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static void wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - return; + struct wl_info *wl; + + wl = HW_TO_WL(hw); + + /* put driver in down state */ + WL_LOCK(wl); + wl_down(wl); + WL_UNLOCK(wl); } static int @@ -779,7 +783,7 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs, wl_found++; return wl; - fail: +fail: wl_free(wl); fail1: return NULL; @@ -1090,7 +1094,6 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; } -#ifdef LINUXSTA_PS static int wl_suspend(struct pci_dev *pdev, pm_message_t state) { struct wl_info *wl; @@ -1105,11 +1108,12 @@ static int wl_suspend(struct pci_dev *pdev, pm_message_t state) return -ENODEV; } + /* only need to flag hw is down for proper resume */ WL_LOCK(wl); - wl_down(wl); wl->pub->hw_up = false; WL_UNLOCK(wl); - pci_save_state(pdev, wl->pci_psstate); + + pci_save_state(pdev); pci_disable_device(pdev); return pci_set_power_state(pdev, PCI_D3hot); } @@ -1133,7 +1137,7 @@ static int wl_resume(struct pci_dev *pdev) if (err) return err; - pci_restore_state(pdev, wl->pci_psstate); + pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) @@ -1145,13 +1149,12 @@ static int wl_resume(struct pci_dev *pdev) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - WL_LOCK(wl); - err = wl_up(wl); - WL_UNLOCK(wl); - + /* + * done. driver will be put in up state + * in wl_ops_add_interface() call. + */ return err; } -#endif /* LINUXSTA_PS */ static void wl_remove(struct pci_dev *pdev) { @@ -1184,14 +1187,12 @@ static void wl_remove(struct pci_dev *pdev) } static struct pci_driver wl_pci_driver = { - .name = "brcm80211", - .probe = wl_pci_probe, -#ifdef LINUXSTA_PS - .suspend = wl_suspend, - .resume = wl_resume, -#endif /* LINUXSTA_PS */ - .remove = __devexit_p(wl_remove), - .id_table = wl_id_table, + .name = "brcm80211", + .probe = wl_pci_probe, + .suspend = wl_suspend, + .resume = wl_resume, + .remove = __devexit_p(wl_remove), + .id_table = wl_id_table, }; /** diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.c b/drivers/staging/brcm80211/sys/wlc_mac80211.c index 1d5d01ac0a9b..a1303863686c 100644 --- a/drivers/staging/brcm80211/sys/wlc_mac80211.c +++ b/drivers/staging/brcm80211/sys/wlc_mac80211.c @@ -5126,7 +5126,6 @@ wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu, fifo = prio2fifo[prio]; ASSERT((uint) skb_headroom(sdu) >= TXOFF); - ASSERT(!(sdu->cloned)); ASSERT(!(sdu->next)); ASSERT(!(sdu->prev)); ASSERT(fifo < NFIFO); diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 4d1868d04bac..0728c3c0cb0e 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -575,7 +575,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, /* grab our IRQ */ if (irq) { isr_flags = 0; - if (thisboard->bustype == pci_bustype) + if (thisboard->bustype == pci_bustype + || thisboard->bustype == pcmcia_bustype) isr_flags |= IRQF_SHARED; if (request_irq(irq, labpc_interrupt, isr_flags, driver_labpc.driver_name, dev)) { diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index b3d05fcfe6d2..4fb809485d9e 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -368,6 +368,7 @@ static int blkvsc_probe(struct device *device) blkdev->gd->first_minor = 0; blkdev->gd->fops = &block_ops; blkdev->gd->private_data = blkdev; + blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum); blkvsc_do_inquiry(blkdev); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index df9cd131e953..0edbe7483a4c 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -1279,7 +1279,7 @@ static void netvsc_channel_cb(void *context) /* ASSERT(device); */ packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), - GFP_KERNEL); + GFP_ATOMIC); if (!packet) return; buffer = packet; diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 0147b407512c..54706a16dc0a 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -358,7 +358,6 @@ static int netvsc_probe(struct device *device) /* Set initial state */ netif_carrier_off(net); - netif_stop_queue(net); net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = device_ctx; diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index deb68c8a6e18..b8b54da67c63 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -68,7 +68,7 @@ static ssize_t ad7476_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7476_show_scale, NULL, 0); diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 685908995d49..5d85efab658c 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -68,7 +68,7 @@ static ssize_t ad7887_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7887_show_scale, NULL, 0); diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 6309d521a864..89ccf375a188 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -432,7 +432,7 @@ static ssize_t ad799x_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad799x_show_scale, NULL, 0); diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index e3387cd31145..0f87ecac82fc 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -87,7 +87,7 @@ static ssize_t ad5446_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0); diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c index 701561d6b6fd..236dd36d349a 100644 --- a/drivers/staging/rt2860/rt_main_dev.c +++ b/drivers/staging/rt2860/rt_main_dev.c @@ -484,8 +484,6 @@ struct net_device *RtmpPhyNetDevInit(struct rt_rtmp_adapter *pAd, net_dev->ml_priv = (void *)pAd; pAd->net_dev = net_dev; - netif_stop_queue(net_dev); - return net_dev; } diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index ee68d51caa4e..322bf49ee906 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -106,6 +106,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x0411, 0x016f)}, /* MelCo.,Inc. WLI-UC-G301N */ {USB_DEVICE(0x1737, 0x0070)}, /* Linksys WUSB100 */ {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ + {USB_DEVICE(0x1737, 0x0078)}, /* Linksys WUSB100v2 */ {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 32088a641eba..84be383abec3 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -128,12 +128,13 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) u8 *ptmpchar = NULL, *ppayload, *ptr; struct tx_desc *ptx_desc; u32 txdscp_sz = sizeof(struct tx_desc); + u8 ret = _FAIL; ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw); if (pmappedfw && (ulfilelength > 0)) { update_fwhdr(&fwhdr, pmappedfw); if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) - goto exit_fail; + goto firmware_rel; fill_fwpriv(padapter, &fwhdr.fwpriv); /* firmware check ok */ maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? @@ -141,7 +142,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) maxlen += txdscp_sz; ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ); if (ptmpchar == NULL) - return _FAIL; + goto firmware_rel; ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ - ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1))); @@ -273,11 +274,13 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) goto exit_fail; } else goto exit_fail; - return _SUCCESS; + ret = _SUCCESS; exit_fail: kfree(ptmpchar); - return _FAIL; +firmware_rel: + release_firmware((struct firmware *)phfwfile_hdl); + return ret; } uint rtl8712_hal_init(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index a692ee88b9e9..21ce2af447b5 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -47,54 +47,123 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, static void r871xu_dev_remove(struct usb_interface *pusb_intf); static struct usb_device_id rtl871x_usb_id_tbl[] = { - /*92SU - * Realtek */ - {USB_DEVICE(0x0bda, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8172)}, + +/* RTL8188SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8171)}, {USB_DEVICE(0x0bda, 0x8173)}, - {USB_DEVICE(0x0bda, 0x8174)}, {USB_DEVICE(0x0bda, 0x8712)}, {USB_DEVICE(0x0bda, 0x8713)}, {USB_DEVICE(0x0bda, 0xC512)}, - /* Abocom */ + /* Abocom */ {USB_DEVICE(0x07B8, 0x8188)}, + /* ASUS */ + {USB_DEVICE(0x0B05, 0x1786)}, + {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ + /* Belkin */ + {USB_DEVICE(0x050D, 0x945A)}, /* Corega */ - {USB_DEVICE(0x07aa, 0x0047)}, - /* Dlink */ - {USB_DEVICE(0x07d1, 0x3303)}, - {USB_DEVICE(0x07d1, 0x3302)}, - {USB_DEVICE(0x07d1, 0x3300)}, - /* Dlink for Skyworth */ - {USB_DEVICE(0x14b2, 0x3300)}, - {USB_DEVICE(0x14b2, 0x3301)}, - {USB_DEVICE(0x14b2, 0x3302)}, + {USB_DEVICE(0x07AA, 0x0047)}, + /* D-Link */ + {USB_DEVICE(0x2001, 0x3306)}, + {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */ + /* Edimax */ + {USB_DEVICE(0x7392, 0x7611)}, /* EnGenius */ {USB_DEVICE(0x1740, 0x9603)}, - {USB_DEVICE(0x1740, 0x9605)}, + /* Hawking */ + {USB_DEVICE(0x0E66, 0x0016)}, + /* Hercules */ + {USB_DEVICE(0x06F8, 0xE034)}, + {USB_DEVICE(0x06F8, 0xE032)}, + /* Logitec */ + {USB_DEVICE(0x0789, 0x0167)}, + /* PCI */ + {USB_DEVICE(0x2019, 0xAB28)}, + {USB_DEVICE(0x2019, 0xED16)}, + /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x0057)}, + {USB_DEVICE(0x0DF6, 0x0045)}, + {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */ + {USB_DEVICE(0x0DF6, 0x004B)}, + {USB_DEVICE(0x0DF6, 0x0063)}, + /* Sweex */ + {USB_DEVICE(0x177F, 0x0154)}, + /* Thinkware */ + {USB_DEVICE(0x0BDA, 0x5077)}, + /* Toshiba */ + {USB_DEVICE(0x1690, 0x0752)}, + /* - */ + {USB_DEVICE(0x20F4, 0x646B)}, + {USB_DEVICE(0x083A, 0xC512)}, + +/* RTL8191SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8172)}, + /* Amigo */ + {USB_DEVICE(0x0EB0, 0x9061)}, + /* ASUS/EKB */ + {USB_DEVICE(0x0BDA, 0x8172)}, + {USB_DEVICE(0x13D3, 0x3323)}, + {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3342)}, + /* ASUS/EKBLenovo */ + {USB_DEVICE(0x13D3, 0x3333)}, + {USB_DEVICE(0x13D3, 0x3334)}, + {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */ + /* ASUS/Media BOX */ + {USB_DEVICE(0x13D3, 0x3309)}, /* Belkin */ - {USB_DEVICE(0x050d, 0x815F)}, - {USB_DEVICE(0x050d, 0x945A)}, - {USB_DEVICE(0x050d, 0x845A)}, - /* Guillemot */ - {USB_DEVICE(0x06f8, 0xe031)}, + {USB_DEVICE(0x050D, 0x815F)}, + /* D-Link */ + {USB_DEVICE(0x07D1, 0x3302)}, + {USB_DEVICE(0x07D1, 0x3300)}, + {USB_DEVICE(0x07D1, 0x3303)}, /* Edimax */ - {USB_DEVICE(0x7392, 0x7611)}, {USB_DEVICE(0x7392, 0x7612)}, - {USB_DEVICE(0x7392, 0x7622)}, - /* Sitecom */ - {USB_DEVICE(0x0DF6, 0x0045)}, + /* EnGenius */ + {USB_DEVICE(0x1740, 0x9605)}, + /* Guillemot */ + {USB_DEVICE(0x06F8, 0xE031)}, /* Hawking */ {USB_DEVICE(0x0E66, 0x0015)}, - {USB_DEVICE(0x0E66, 0x0016)}, - {USB_DEVICE(0x0b05, 0x1786)}, - {USB_DEVICE(0x0b05, 0x1791)}, /* 11n mode disable */ - + /* Mediao */ {USB_DEVICE(0x13D3, 0x3306)}, - {USB_DEVICE(0x13D3, 0x3309)}, + /* PCI */ + {USB_DEVICE(0x2019, 0xED18)}, + {USB_DEVICE(0x2019, 0x4901)}, + /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x0058)}, + {USB_DEVICE(0x0DF6, 0x0049)}, + {USB_DEVICE(0x0DF6, 0x004C)}, + {USB_DEVICE(0x0DF6, 0x0064)}, + /* Skyworth */ + {USB_DEVICE(0x14b2, 0x3300)}, + {USB_DEVICE(0x14b2, 0x3301)}, + {USB_DEVICE(0x14B2, 0x3302)}, + /* - */ + {USB_DEVICE(0x04F2, 0xAFF2)}, + {USB_DEVICE(0x04F2, 0xAFF5)}, + {USB_DEVICE(0x04F2, 0xAFF6)}, + {USB_DEVICE(0x13D3, 0x3339)}, + {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */ {USB_DEVICE(0x13D3, 0x3310)}, - {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */ {USB_DEVICE(0x13D3, 0x3325)}, - {USB_DEVICE(0x083A, 0xC512)}, + +/* RTL8192SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8174)}, + {USB_DEVICE(0x0BDA, 0x8174)}, + /* Belkin */ + {USB_DEVICE(0x050D, 0x845A)}, + /* Corega */ + {USB_DEVICE(0x07AA, 0x0051)}, + /* Edimax */ + {USB_DEVICE(0x7392, 0x7622)}, + /* NEC */ + {USB_DEVICE(0x0409, 0x02B6)}, {} }; @@ -103,8 +172,20 @@ MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl); static struct specific_device_id specific_device_id_tbl[] = { {.idVendor = 0x0b05, .idProduct = 0x1791, .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x0df6, .idProduct = 0x0059, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3306, + .flags = SPEC_DEV_ID_DISABLE_HT}, {.idVendor = 0x13D3, .idProduct = 0x3311, .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3335, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3336, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3340, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3341, + .flags = SPEC_DEV_ID_DISABLE_HT}, {} }; diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 408bb9b3303e..07a7f5432597 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -332,7 +332,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, unsigned long flags; len = strlen(buf); - if (len > 0 || len < 3) { + if (len > 0 && len < 3) { ch = buf[0]; if (ch == '\n') ch = '0'; diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c index e8f047e86a32..80183a7e6624 100644 --- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c +++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c @@ -986,12 +986,6 @@ static int __devinit synaptics_rmi4_probe input_set_abs_params(rmi4_data->input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0); - retval = input_register_device(rmi4_data->input_dev); - if (retval) { - dev_err(&client->dev, "%s:input register failed\n", __func__); - goto err_input_register; - } - /* Clear interrupts */ synaptics_rmi4_i2c_block_read(rmi4_data, rmi4_data->fn01_data_base_addr + 1, intr_status, @@ -1003,15 +997,20 @@ static int __devinit synaptics_rmi4_probe if (retval) { dev_err(&client->dev, "%s:Unable to get attn irq %d\n", __func__, platformdata->irq_number); - goto err_request_irq; + goto err_unset_clientdata; + } + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(&client->dev, "%s:input register failed\n", __func__); + goto err_free_irq; } return retval; -err_request_irq: +err_free_irq: free_irq(platformdata->irq_number, rmi4_data); - input_unregister_device(rmi4_data->input_dev); -err_input_register: +err_unset_clientdata: i2c_set_clientdata(client, NULL); err_query_dev: if (platformdata->regulator_en) { diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index 571864555ddd..27e0aa81a584 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -949,7 +949,7 @@ func_end: * Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then * schedules a DPC to dispatch I/O. */ -void io_mbox_msg(u32 msg) +int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg) { struct io_mgr *pio_mgr; struct dev_object *dev_obj; @@ -959,9 +959,9 @@ void io_mbox_msg(u32 msg) dev_get_io_mgr(dev_obj, &pio_mgr); if (!pio_mgr) - return; + return NOTIFY_BAD; - pio_mgr->intr_val = (u16)msg; + pio_mgr->intr_val = (u16)((u32)msg); if (pio_mgr->intr_val & MBX_PM_CLASS) io_dispatch_pm(pio_mgr); @@ -973,7 +973,7 @@ void io_mbox_msg(u32 msg) spin_unlock_irqrestore(&pio_mgr->dpc_lock, flags); tasklet_schedule(&pio_mgr->dpc_tasklet); } - return; + return NOTIFY_OK; } /* diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index a3b0a183d570..a3f69f6f505f 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -223,6 +223,10 @@ static struct bridge_drv_interface drv_interface_fxns = { bridge_msg_set_queue_id, }; +static struct notifier_block dsp_mbox_notifier = { + .notifier_call = io_mbox_msg, +}; + static inline void flush_all(struct bridge_dev_context *dev_context) { if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION || @@ -553,7 +557,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, * Enable Mailbox events and also drain any pending * stale messages. */ - dev_context->mbox = omap_mbox_get("dsp"); + dev_context->mbox = omap_mbox_get("dsp", &dsp_mbox_notifier); if (IS_ERR(dev_context->mbox)) { dev_context->mbox = NULL; pr_err("%s: Failed to get dsp mailbox handle\n", @@ -563,8 +567,6 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, } if (!status) { - dev_context->mbox->rxq->callback = (int (*)(void *))io_mbox_msg; - /*PM_IVA2GRPSEL_PER = 0xC0;*/ temp = readl(resources->dw_per_pm_base + 0xA8); temp = (temp & 0xFFFFFF30) | 0xC0; @@ -685,7 +687,7 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt) /* Disable the mailbox interrupts */ if (dev_context->mbox) { omap_mbox_disable_irq(dev_context->mbox, IRQ_RX); - omap_mbox_put(dev_context->mbox); + omap_mbox_put(dev_context->mbox, &dsp_mbox_notifier); dev_context->mbox = NULL; } /* Reset IVA2 clocks*/ @@ -786,10 +788,7 @@ static int bridge_dev_create(struct bridge_dev_context pt_attrs = kzalloc(sizeof(struct pg_table_attrs), GFP_KERNEL); if (pt_attrs != NULL) { - /* Assuming that we use only DSP's memory map - * until 0x4000:0000 , we would need only 1024 - * L1 enties i.e L1 size = 4K */ - pt_attrs->l1_size = 0x1000; + pt_attrs->l1_size = SZ_16K; /* 4096 entries of 32 bits */ align_size = pt_attrs->l1_size; /* Align sizes are expected to be power of 2 */ /* we like to get aligned on L1 table size */ diff --git a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h index 18aec55d8647..8242c70e09dd 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h +++ b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h @@ -72,22 +72,17 @@ extern void io_dpc(unsigned long ref_data); /* * ======== io_mbox_msg ======== * Purpose: - * Main interrupt handler for the shared memory Bridge channel manager. - * Calls the Bridge's chnlsm_isr to determine if this interrupt is ours, - * then schedules a DPC to dispatch I/O. + * Main message handler for the shared memory Bridge channel manager. + * Determine if this message is ours, then schedules a DPC to + * dispatch I/O. * Parameters: - * ref_data: Pointer to the channel manager object for this board. - * Set in an initial call to ISR_Install(). + * self: Pointer to its own notifier_block struct. + * len: Length of message. + * msg: Message code received. * Returns: - * TRUE if interrupt handled; FALSE otherwise. - * Requires: - * Must be in locked memory if executing in kernel mode. - * Must only call functions which are in locked memory if Kernel mode. - * Must only call asynchronous services. - * Interrupts are disabled and EOI for this interrupt has been sent. - * Ensures: + * NOTIFY_OK if handled; NOTIFY_BAD otherwise. */ -void io_mbox_msg(u32 msg); +int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg); /* * ======== io_request_chnl ======== diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h index 30dbfb6d16f2..d73267961ef4 100644 --- a/drivers/staging/usbip/stub.h +++ b/drivers/staging/usbip/stub.h @@ -32,6 +32,7 @@ struct stub_device { struct usb_interface *interface; + struct usb_device *udev; struct list_head list; struct usbip_device ud; diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index b186b5fed2b9..a7ce51cc8909 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -258,10 +258,11 @@ static void stub_shutdown_connection(struct usbip_device *ud) static void stub_device_reset(struct usbip_device *ud) { struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; int ret; usbip_udbg("device reset"); + ret = usb_lock_device_for_reset(udev, sdev->interface); if (ret < 0) { dev_err(&udev->dev, "lock for reset\n"); @@ -309,7 +310,8 @@ static void stub_device_unusable(struct usbip_device *ud) * * Allocates and initializes a new stub_device struct. */ -static struct stub_device *stub_device_alloc(struct usb_interface *interface) +static struct stub_device *stub_device_alloc(struct usb_device *udev, + struct usb_interface *interface) { struct stub_device *sdev; int busnum = interface_to_busnum(interface); @@ -324,7 +326,8 @@ static struct stub_device *stub_device_alloc(struct usb_interface *interface) return NULL; } - sdev->interface = interface; + sdev->interface = usb_get_intf(interface); + sdev->udev = usb_get_dev(udev); /* * devid is defined with devnum when this driver is first allocated. @@ -450,11 +453,12 @@ static int stub_probe(struct usb_interface *interface, return err; } + usb_get_intf(interface); return 0; } /* ok. this is my device. */ - sdev = stub_device_alloc(interface); + sdev = stub_device_alloc(udev, interface); if (!sdev) return -ENOMEM; @@ -476,6 +480,8 @@ static int stub_probe(struct usb_interface *interface, dev_err(&interface->dev, "create sysfs files for %s\n", udev_busid); usb_set_intfdata(interface, NULL); + usb_put_intf(interface); + busid_priv->interf_count = 0; busid_priv->sdev = NULL; @@ -545,6 +551,7 @@ static void stub_disconnect(struct usb_interface *interface) if (busid_priv->interf_count > 1) { busid_priv->interf_count--; shutdown_busid(busid_priv); + usb_put_intf(interface); return; } @@ -554,6 +561,9 @@ static void stub_disconnect(struct usb_interface *interface) /* 1. shutdown the current connection */ shutdown_busid(busid_priv); + usb_put_dev(sdev->udev); + usb_put_intf(interface); + /* 3. free sdev */ busid_priv->sdev = NULL; stub_device_free(sdev); diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 3de6fd2539dc..ae6ac82754a4 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -364,7 +364,7 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, static int get_pipe(struct stub_device *sdev, int epnum, int dir) { - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; @@ -484,7 +484,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, int ret; struct stub_priv *priv; struct usbip_device *ud = &sdev->ud; - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 41a1fe5138f4..afc3b1a71881 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -100,9 +100,6 @@ struct vhci_hcd { * But, the index of this array begins from 0. */ struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; }; @@ -119,6 +116,9 @@ void rh_port_disconnect(int rhport); void vhci_rx_loop(struct usbip_task *ut); void vhci_tx_loop(struct usbip_task *ut); +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, + __u32 seqnum); + #define hardware (&the_controller->pdev.dev) static inline struct vhci_device *port_to_vdev(__u32 port) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 08bd26a245d5..a35fe61268de 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -138,8 +138,6 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) * the_controller->vdev[rhport].ud.status = VDEV_CONNECT; * spin_unlock(&the_controller->vdev[rhport].ud.lock); */ - the_controller->pending_port = rhport; - spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); @@ -559,6 +557,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; unsigned long flags; + struct vhci_device *vdev; usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); @@ -574,6 +573,18 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return urb->status; } + vdev = port_to_vdev(urb->dev->portnum-1); + + /* refuse enqueue for dead connection */ + spin_lock(&vdev->ud.lock); + if (vdev->ud.status == VDEV_ST_NULL || vdev->ud.status == VDEV_ST_ERROR) { + usbip_uerr("enqueue for inactive port %d\n", vdev->rhport); + spin_unlock(&vdev->ud.lock); + spin_unlock_irqrestore(&the_controller->lock, flags); + return -ENODEV; + } + spin_unlock(&vdev->ud.lock); + ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto no_need_unlink; @@ -592,8 +603,6 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, __u8 type = usb_pipetype(urb->pipe); struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = - port_to_vdev(the_controller->pending_port); if (type != PIPE_CONTROL || !ctrlreq) { dev_err(dev, "invalid request to devnum 0\n"); @@ -607,7 +616,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, dev_info(dev, "SetAddress Request (%d) to port %d\n", ctrlreq->wValue, vdev->rhport); - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); spin_lock(&vdev->ud.lock); vdev->ud.status = VDEV_ST_USED; @@ -627,8 +638,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, "Get_Descriptor to device 0 " "(get max pipe size)\n"); - /* FIXME: reference count? (usb_get_dev()) */ - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); goto out; default: @@ -805,7 +817,6 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) return 0; } - static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; @@ -813,11 +824,34 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { + usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum); list_del(&unlink->list); kfree(unlink); } list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { + struct urb *urb; + + /* give back URB of unanswered unlink request */ + usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum); + + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + if (!urb) { + usbip_uinfo("the urb (seqnum %lu) was already given back\n", + unlink->unlink_seqnum); + list_del(&unlink->list); + kfree(unlink); + continue; + } + + urb->status = -ENODEV; + + spin_lock(&the_controller->lock); + usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); + spin_unlock(&the_controller->lock); + + usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); + list_del(&unlink->list); kfree(unlink); } @@ -887,6 +921,10 @@ static void vhci_device_reset(struct usbip_device *ud) vdev->speed = 0; vdev->devid = 0; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = NULL; + ud->tcp_socket = NULL; ud->status = VDEV_ST_NULL; diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 8147d7202b2d..bf6991470941 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -23,16 +23,14 @@ #include "vhci.h" -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, +/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */ +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) { struct vhci_priv *priv, *tmp; struct urb *urb = NULL; int status; - spin_lock(&vdev->priv_lock); - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { if (priv->seqnum == seqnum) { urb = priv->urb; @@ -63,8 +61,6 @@ static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, } } - spin_unlock(&vdev->priv_lock); - return urb; } @@ -74,9 +70,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_device *ud = &vdev->ud; struct urb *urb; + spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); + spin_unlock(&vdev->priv_lock); if (!urb) { usbip_uerr("cannot find a urb of seqnum %u\n", @@ -161,7 +159,12 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } + spin_lock(&vdev->priv_lock); + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + + spin_unlock(&vdev->priv_lock); + if (!urb) { /* * I get the result of a unlink request. But, it seems that I @@ -190,6 +193,19 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } +static int vhci_priv_tx_empty(struct vhci_device *vdev) +{ + int empty = 0; + + spin_lock(&vdev->priv_lock); + + empty = list_empty(&vdev->priv_rx); + + spin_unlock(&vdev->priv_lock); + + return empty; +} + /* recv a pdu */ static void vhci_rx_pdu(struct usbip_device *ud) { @@ -202,11 +218,29 @@ static void vhci_rx_pdu(struct usbip_device *ud) memset(&pdu, 0, sizeof(pdu)); - /* 1. receive a pdu header */ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); + if (ret < 0) { + if (ret == -ECONNRESET) + usbip_uinfo("connection reset by peer\n"); + else if (ret == -EAGAIN) { + /* ignore if connection was idle */ + if (vhci_priv_tx_empty(vdev)) + return; + usbip_uinfo("connection timed out with pending urbs\n"); + } else if (ret != -ERESTARTSYS) + usbip_uinfo("xmit failed %d\n", ret); + + usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); + return; + } + if (ret == 0) { + usbip_uinfo("connection closed"); + usbip_event_add(ud, VDEV_EVENT_DOWN); + return; + } if (ret != sizeof(pdu)) { - usbip_uerr("receiving pdu failed! size is %d, should be %d\n", + usbip_uerr("received pdu size is %d, should be %d\n", ret, (unsigned int)sizeof(pdu)); usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return; diff --git a/drivers/staging/vme/bridges/Module.symvers b/drivers/staging/vme/bridges/Module.symvers deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/drivers/staging/vme/bridges/Module.symvers +++ /dev/null diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 7016fdd2509f..e19b932492e1 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -3954,8 +3954,8 @@ void XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) { - if ((((pVBInfo->VBInfo & SetCRT2ToLCD) | SetCRT2ToLCDA)) - && (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ + if ((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) && + (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ return 1; return 0; @@ -8773,7 +8773,7 @@ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { CRT2Index = CRT2Index >> 6; /* for LCD */ - if (((pVBInfo->VBInfo & SetCRT2ToLCD) | SetCRT2ToLCDA)) { /*301b*/ + if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/ if (pVBInfo->LCDResInfo != Panel1024x768) VCLKIndex = LCDXlat2VCLK[CRT2Index]; else diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 47d32281032c..52fc0c9a6364 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -581,8 +581,9 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, __u8 __user *buf, size_t nr) { struct n_hdlc *n_hdlc = tty2n_hdlc(tty); - int ret; + int ret = 0; struct n_hdlc_buf *rbuf; + DECLARE_WAITQUEUE(wait, current); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); @@ -598,57 +599,55 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, return -EFAULT; } - tty_lock(); + add_wait_queue(&tty->read_wait, &wait); for (;;) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - tty_unlock(); - return -EIO; + ret = -EIO; + break; } + if (tty_hung_up_p(file)) + break; - n_hdlc = tty2n_hdlc (tty); - if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || - tty != n_hdlc->tty) { - tty_unlock(); - return 0; - } + set_current_state(TASK_INTERRUPTIBLE); rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); - if (rbuf) + if (rbuf) { + if (rbuf->count > nr) { + /* too large for caller's buffer */ + ret = -EOVERFLOW; + } else { + if (copy_to_user(buf, rbuf->buf, rbuf->count)) + ret = -EFAULT; + else + ret = rbuf->count; + } + + if (n_hdlc->rx_free_buf_list.count > + DEFAULT_RX_BUF_COUNT) + kfree(rbuf); + else + n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); break; + } /* no data */ if (file->f_flags & O_NONBLOCK) { - tty_unlock(); - return -EAGAIN; + ret = -EAGAIN; + break; } - - interruptible_sleep_on (&tty->read_wait); + + schedule(); + if (signal_pending(current)) { - tty_unlock(); - return -EINTR; + ret = -EINTR; + break; } } - - if (rbuf->count > nr) - /* frame too large for caller's buffer (discard frame) */ - ret = -EOVERFLOW; - else { - /* Copy the data to the caller's buffer */ - if (copy_to_user(buf, rbuf->buf, rbuf->count)) - ret = -EFAULT; - else - ret = rbuf->count; - } - - /* return HDLC buffer to free list unless the free list */ - /* count has exceeded the default value, in which case the */ - /* buffer is freed back to the OS to conserve memory */ - if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) - kfree(rbuf); - else - n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); - tty_unlock(); + + remove_wait_queue(&tty->read_wait, &wait); + __set_current_state(TASK_RUNNING); + return ret; } /* end of n_hdlc_tty_read() */ @@ -691,14 +690,15 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, count = maxframe; } - tty_lock(); - add_wait_queue(&tty->write_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); - /* Allocate transmit buffer */ - /* sleep until transmit buffer available */ - while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { + tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); + if (tbuf) + break; + if (file->f_flags & O_NONBLOCK) { error = -EAGAIN; break; @@ -719,7 +719,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, } } - set_current_state(TASK_RUNNING); + __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (!error) { @@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); n_hdlc_send_frames(n_hdlc,tty); } - tty_unlock(); + return error; } /* end of n_hdlc_tty_write() */ diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index b25e6e490530..3975df6f7fdb 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -236,7 +236,8 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 128, .tx_loadsz = 128, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + /* UART_CAP_EFR breaks billionon CF bluetooth card. */ + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, }, [PORT_16654] = { .name = "ST16654", diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b1682d7f1d8a..2b8334601c8b 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1518,6 +1518,7 @@ config SERIAL_BCM63XX_CONSOLE config SERIAL_GRLIB_GAISLER_APBUART tristate "GRLIB APBUART serial support" depends on OF + select SERIAL_CORE ---help--- Add support for the GRLIB APBUART serial port. diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6158eae0f64a..0065da4b11c1 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3257,7 +3257,7 @@ static ssize_t show_cons_active(struct device *dev, ssize_t count = 0; console_lock(); - for (c = console_drivers; c; c = c->next) { + for_each_console(c) { if (!c->device) continue; if (!c->write) @@ -3306,7 +3306,7 @@ int __init tty_init(void) if (IS_ERR(consdev)) consdev = NULL; else - device_create_file(consdev, &dev_attr_active); + WARN_ON(device_create_file(consdev, &dev_attr_active) < 0); #ifdef CONFIG_VT vty_init(&console_fops); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b230bd3f056f..147ede3423df 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2994,7 +2994,7 @@ int __init vty_init(const struct file_operations *console_fops) if (IS_ERR(tty0dev)) tty0dev = NULL; else - device_create_file(tty0dev, &dev_attr_active); + WARN_ON(device_create_file(tty0dev, &dev_attr_active) < 0); vcs_init(); @@ -3545,7 +3545,7 @@ int register_con_driver(const struct consw *csw, int first, int last) /* already registered */ if (con_driver->con == csw) - retval = -EINVAL; + retval = -EBUSY; } if (retval) @@ -3656,7 +3656,12 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt) int err; err = register_con_driver(csw, first, last); - + /* if we get an busy error we still want to bind the console driver + * and return success, as we may have unbound the console driver + * but not unregistered it. + */ + if (err == -EBUSY) + err = 0; if (!err) bind_con_driver(csw, first, last, deflt); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6ee4451bfe2d..47085e5879ab 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -342,7 +342,7 @@ static ssize_t wdm_write goto outnp; } - if (!file->f_flags && O_NONBLOCK) + if (!(file->f_flags & O_NONBLOCK)) r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); else diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 9da250563027..df502a98d0df 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -192,12 +192,12 @@ int usb_create_ep_devs(struct device *parent, ep_dev->dev.parent = parent; ep_dev->dev.release = ep_device_release; dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); - device_enable_async_suspend(&ep_dev->dev); retval = device_register(&ep_dev->dev); if (retval) goto error_register; + device_enable_async_suspend(&ep_dev->dev); endpoint->ep_dev = ep_dev; return retval; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index b55d46070a25..f71e8e307e0f 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -405,7 +405,12 @@ static int suspend_common(struct device *dev, bool do_wakeup) return retval; } - synchronize_irq(pci_dev->irq); + /* If MSI-X is enabled, the driver will have synchronized all vectors + * in pci_suspend(). If MSI or legacy PCI is enabled, that will be + * synchronized here. + */ + if (!hcd->msix_enabled) + synchronize_irq(pci_dev->irq); /* Downstream ports from this root hub should already be quiesced, so * there will be no DMA activity. Now we can shut down the upstream diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b98efae6a1cf..4310cc4b1cb5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -676,6 +676,8 @@ static void hub_init_func3(struct work_struct *ws); static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) { struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd; + int ret; int port1; int status; bool need_debounce_delay = false; @@ -714,6 +716,25 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) usb_autopm_get_interface_no_resume( to_usb_interface(hub->intfdev)); return; /* Continues at init2: below */ + } else if (type == HUB_RESET_RESUME) { + /* The internal host controller state for the hub device + * may be gone after a host power loss on system resume. + * Update the device's info so the HW knows it's a hub. + */ + hcd = bus_to_hcd(hdev->bus); + if (hcd->driver->update_hub_device) { + ret = hcd->driver->update_hub_device(hcd, hdev, + &hub->tt, GFP_NOIO); + if (ret < 0) { + dev_err(hub->intfdev, "Host not " + "accepting hub info " + "update.\n"); + dev_err(hub->intfdev, "LS/FS devices " + "and hubs may not work " + "under this hub\n."); + } + } + hub_power_on(hub, true); } else { hub_power_on(hub, true); } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1dc9739277b4..06bb9d4587e9 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -509,7 +509,7 @@ config USB_LANGWELL select USB_GADGET_SELECTED config USB_GADGET_EG20T - boolean "Intel EG20T(Topcliff) USB Device controller" + boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC" depends on PCI select USB_GADGET_DUALSPEED help @@ -525,6 +525,11 @@ config USB_GADGET_EG20T This driver dose not support interrupt transfer or isochronous transfer modes. + This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is + for IVI(In-Vehicle Infotainment) use. + ML7213 is companion chip for Intel Atom E6xx series. + ML7213 is completely compatible for Intel EG20T PCH. + config USB_EG20T tristate depends on USB_GADGET_EG20T diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 31656a2b4ab4..a1c67ae1572a 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -76,10 +76,21 @@ static DEFINE_SPINLOCK(udc_lock); /* control endpoint description */ static const struct usb_endpoint_descriptor -ctrl_endpt_desc = { +ctrl_endpt_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), +}; + +static const struct usb_endpoint_descriptor +ctrl_endpt_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), }; @@ -265,10 +276,10 @@ static int hw_device_init(void __iomem *base) hw_bank.size /= sizeof(u32); reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); - if (reg == 0 || reg > ENDPT_MAX) - return -ENODEV; + hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */ - hw_ep_max = reg; /* cache hw ENDPT_MAX */ + if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX) + return -ENODEV; /* setup lock mode ? */ @@ -1197,16 +1208,17 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, } spin_lock_irqsave(udc->lock, flags); - for (i = 0; i < hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < hw_ep_max/2; i++) { + struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i]; + struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2]; n += scnprintf(buf + n, PAGE_SIZE - n, "EP=%02i: RX=%08X TX=%08X\n", - i, (u32)mEp->qh[RX].dma, (u32)mEp->qh[TX].dma); + i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) { n += scnprintf(buf + n, PAGE_SIZE - n, " %04X: %08X %08X\n", j, - *((u32 *)mEp->qh[RX].ptr + j), - *((u32 *)mEp->qh[TX].ptr + j)); + *((u32 *)mEpRx->qh.ptr + j), + *((u32 *)mEpTx->qh.ptr + j)); } } spin_unlock_irqrestore(udc->lock, flags); @@ -1293,7 +1305,7 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr, unsigned long flags; struct list_head *ptr = NULL; struct ci13xxx_req *req = NULL; - unsigned i, j, k, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); + unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); dbg_trace("[%s] %p\n", __func__, buf); if (attr == NULL || buf == NULL) { @@ -1303,22 +1315,20 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr, spin_lock_irqsave(udc->lock, flags); for (i = 0; i < hw_ep_max; i++) - for (k = RX; k <= TX; k++) - list_for_each(ptr, &udc->ci13xxx_ep[i].qh[k].queue) - { - req = list_entry(ptr, - struct ci13xxx_req, queue); + list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) + { + req = list_entry(ptr, struct ci13xxx_req, queue); + + n += scnprintf(buf + n, PAGE_SIZE - n, + "EP=%02i: TD=%08X %s\n", + i % hw_ep_max/2, (u32)req->dma, + ((i < hw_ep_max/2) ? "RX" : "TX")); + for (j = 0; j < qSize; j++) n += scnprintf(buf + n, PAGE_SIZE - n, - "EP=%02i: TD=%08X %s\n", - i, (u32)req->dma, - ((k == RX) ? "RX" : "TX")); - - for (j = 0; j < qSize; j++) - n += scnprintf(buf + n, PAGE_SIZE - n, - " %04X: %08X\n", j, - *((u32 *)req->ptr + j)); - } + " %04X: %08X\n", j, + *((u32 *)req->ptr + j)); + } spin_unlock_irqrestore(udc->lock, flags); return n; @@ -1467,12 +1477,12 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) * At this point it's guaranteed exclusive access to qhead * (endpt is not primed) so it's no need to use tripwire */ - mEp->qh[mEp->dir].ptr->td.next = mReq->dma; /* TERMINATE = 0 */ - mEp->qh[mEp->dir].ptr->td.token &= ~TD_STATUS; /* clear status */ + mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */ + mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */ if (mReq->req.zero == 0) - mEp->qh[mEp->dir].ptr->cap |= QH_ZLT; + mEp->qh.ptr->cap |= QH_ZLT; else - mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; + mEp->qh.ptr->cap &= ~QH_ZLT; wmb(); /* synchronize before ep prime */ @@ -1542,11 +1552,11 @@ __acquires(mEp->lock) hw_ep_flush(mEp->num, mEp->dir); - while (!list_empty(&mEp->qh[mEp->dir].queue)) { + while (!list_empty(&mEp->qh.queue)) { /* pop oldest request */ struct ci13xxx_req *mReq = \ - list_entry(mEp->qh[mEp->dir].queue.next, + list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); list_del_init(&mReq->queue); mReq->req.status = -ESHUTDOWN; @@ -1571,8 +1581,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) { struct usb_ep *ep; struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); - struct ci13xxx_ep *mEp = container_of(gadget->ep0, - struct ci13xxx_ep, ep); trace("%p", gadget); @@ -1583,7 +1591,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) gadget_for_each_ep(ep, gadget) { usb_ep_fifo_flush(ep); } - usb_ep_fifo_flush(gadget->ep0); + usb_ep_fifo_flush(&udc->ep0out.ep); + usb_ep_fifo_flush(&udc->ep0in.ep); udc->driver->disconnect(gadget); @@ -1591,11 +1600,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) gadget_for_each_ep(ep, gadget) { usb_ep_disable(ep); } - usb_ep_disable(gadget->ep0); + usb_ep_disable(&udc->ep0out.ep); + usb_ep_disable(&udc->ep0in.ep); - if (mEp->status != NULL) { - usb_ep_free_request(gadget->ep0, mEp->status); - mEp->status = NULL; + if (udc->status != NULL) { + usb_ep_free_request(&udc->ep0in.ep, udc->status); + udc->status = NULL; } return 0; @@ -1614,7 +1624,6 @@ static void isr_reset_handler(struct ci13xxx *udc) __releases(udc->lock) __acquires(udc->lock) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[0]; int retval; trace("%p", udc); @@ -1635,11 +1644,15 @@ __acquires(udc->lock) if (retval) goto done; - retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); + retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc); + if (retval) + goto done; + + retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc); if (!retval) { - mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC); - if (mEp->status == NULL) { - usb_ep_disable(&mEp->ep); + udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC); + if (udc->status == NULL) { + usb_ep_disable(&udc->ep0out.ep); retval = -ENOMEM; } } @@ -1672,16 +1685,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) /** * isr_get_status_response: get_status request response - * @ep: endpoint + * @udc: udc struct * @setup: setup request packet * * This function returns an error code */ -static int isr_get_status_response(struct ci13xxx_ep *mEp, +static int isr_get_status_response(struct ci13xxx *udc, struct usb_ctrlrequest *setup) __releases(mEp->lock) __acquires(mEp->lock) { + struct ci13xxx_ep *mEp = &udc->ep0in; struct usb_request *req = NULL; gfp_t gfp_flags = GFP_ATOMIC; int dir, num, retval; @@ -1736,27 +1750,23 @@ __acquires(mEp->lock) /** * isr_setup_status_phase: queues the status phase of a setup transation - * @mEp: endpoint + * @udc: udc struct * * This function returns an error code */ -static int isr_setup_status_phase(struct ci13xxx_ep *mEp) +static int isr_setup_status_phase(struct ci13xxx *udc) __releases(mEp->lock) __acquires(mEp->lock) { int retval; + struct ci13xxx_ep *mEp; - trace("%p", mEp); - - /* mEp is always valid & configured */ - - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + trace("%p", udc); - mEp->status->no_interrupt = 1; + mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in; spin_unlock(mEp->lock); - retval = usb_ep_queue(&mEp->ep, mEp->status, GFP_ATOMIC); + retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC); spin_lock(mEp->lock); return retval; @@ -1778,11 +1788,11 @@ __acquires(mEp->lock) trace("%p", mEp); - if (list_empty(&mEp->qh[mEp->dir].queue)) + if (list_empty(&mEp->qh.queue)) return -EINVAL; /* pop oldest request */ - mReq = list_entry(mEp->qh[mEp->dir].queue.next, + mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); list_del_init(&mReq->queue); @@ -1794,10 +1804,10 @@ __acquires(mEp->lock) dbg_done(_usb_addr(mEp), mReq->ptr->token, retval); - if (!list_empty(&mEp->qh[mEp->dir].queue)) { + if (!list_empty(&mEp->qh.queue)) { struct ci13xxx_req* mReqEnq; - mReqEnq = list_entry(mEp->qh[mEp->dir].queue.next, + mReqEnq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); _hardware_enqueue(mEp, mReqEnq); } @@ -1836,16 +1846,14 @@ __acquires(udc->lock) int type, num, err = -EINVAL; struct usb_ctrlrequest req; - if (mEp->desc == NULL) continue; /* not configured */ - if ((mEp->dir == RX && hw_test_and_clear_complete(i)) || - (mEp->dir == TX && hw_test_and_clear_complete(i + 16))) { + if (hw_test_and_clear_complete(i)) { err = isr_tr_complete_low(mEp); if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { if (err > 0) /* needs status phase */ - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); if (err < 0) { dbg_event(_usb_addr(mEp), "ERROR", err); @@ -1866,15 +1874,22 @@ __acquires(udc->lock) continue; } + /* + * Flush data and handshake transactions of previous + * setup packet. + */ + _ep_nuke(&udc->ep0out); + _ep_nuke(&udc->ep0in); + /* read_setup_packet */ do { hw_test_and_set_setup_guard(); - memcpy(&req, &mEp->qh[RX].ptr->setup, sizeof(req)); + memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); } while (!hw_test_and_clear_setup_guard()); type = req.bRequestType; - mEp->dir = (type & USB_DIR_IN) ? TX : RX; + udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX; dbg_setup(_usb_addr(mEp), &req); @@ -1895,7 +1910,7 @@ __acquires(udc->lock) if (err) break; } - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; case USB_REQ_GET_STATUS: if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && @@ -1905,7 +1920,7 @@ __acquires(udc->lock) if (le16_to_cpu(req.wLength) != 2 || le16_to_cpu(req.wValue) != 0) break; - err = isr_get_status_response(mEp, &req); + err = isr_get_status_response(udc, &req); break; case USB_REQ_SET_ADDRESS: if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) @@ -1916,7 +1931,7 @@ __acquires(udc->lock) err = hw_usb_set_address((u8)le16_to_cpu(req.wValue)); if (err) break; - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; case USB_REQ_SET_FEATURE: if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) && @@ -1932,12 +1947,12 @@ __acquires(udc->lock) spin_lock(udc->lock); if (err) break; - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; default: delegate: if (req.wLength == 0) /* no data phase */ - mEp->dir = TX; + udc->ep0_dir = TX; spin_unlock(udc->lock); err = udc->driver->setup(&udc->gadget, &req); @@ -1968,7 +1983,7 @@ static int ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - int direction, retval = 0; + int retval = 0; unsigned long flags; trace("%p, %p", ep, desc); @@ -1982,7 +1997,7 @@ static int ep_enable(struct usb_ep *ep, mEp->desc = desc; - if (!list_empty(&mEp->qh[mEp->dir].queue)) + if (!list_empty(&mEp->qh.queue)) warn("enabling a non-empty endpoint!"); mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; @@ -1991,29 +2006,22 @@ static int ep_enable(struct usb_ep *ep, mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); - direction = mEp->dir; - do { - dbg_event(_usb_addr(mEp), "ENABLE", 0); + dbg_event(_usb_addr(mEp), "ENABLE", 0); - mEp->qh[mEp->dir].ptr->cap = 0; + mEp->qh.ptr->cap = 0; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->qh[mEp->dir].ptr->cap |= QH_IOS; - else if (mEp->type == USB_ENDPOINT_XFER_ISOC) - mEp->qh[mEp->dir].ptr->cap &= ~QH_MULT; - else - mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; - - mEp->qh[mEp->dir].ptr->cap |= - (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; - mEp->qh[mEp->dir].ptr->td.next |= TD_TERMINATE; /* needed? */ - - retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); + if (mEp->type == USB_ENDPOINT_XFER_CONTROL) + mEp->qh.ptr->cap |= QH_IOS; + else if (mEp->type == USB_ENDPOINT_XFER_ISOC) + mEp->qh.ptr->cap &= ~QH_MULT; + else + mEp->qh.ptr->cap &= ~QH_ZLT; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + mEp->qh.ptr->cap |= + (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; + mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */ - } while (mEp->dir != direction); + retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); spin_unlock_irqrestore(mEp->lock, flags); return retval; @@ -2146,7 +2154,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, spin_lock_irqsave(mEp->lock, flags); if (mEp->type == USB_ENDPOINT_XFER_CONTROL && - !list_empty(&mEp->qh[mEp->dir].queue)) { + !list_empty(&mEp->qh.queue)) { _ep_nuke(mEp); retval = -EOVERFLOW; warn("endpoint ctrl %X nuked", _usb_addr(mEp)); @@ -2170,9 +2178,9 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, /* push request */ mReq->req.status = -EINPROGRESS; mReq->req.actual = 0; - list_add_tail(&mReq->queue, &mEp->qh[mEp->dir].queue); + list_add_tail(&mReq->queue, &mEp->qh.queue); - if (list_is_singular(&mEp->qh[mEp->dir].queue)) + if (list_is_singular(&mEp->qh.queue)) retval = _hardware_enqueue(mEp, mReq); if (retval == -EALREADY) { @@ -2199,7 +2207,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL || mEp->desc == NULL || - list_empty(&mReq->queue) || list_empty(&mEp->qh[mEp->dir].queue)) + list_empty(&mReq->queue) || list_empty(&mEp->qh.queue)) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2244,7 +2252,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) #ifndef STALL_IN /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && - !list_empty(&mEp->qh[mEp->dir].queue)) { + !list_empty(&mEp->qh.queue)) { spin_unlock_irqrestore(mEp->lock, flags); return -EAGAIN; } @@ -2355,7 +2363,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) if (is_active) { pm_runtime_get_sync(&_gadget->dev); hw_device_reset(udc); - hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); + hw_device_state(udc->ep0out.qh.dma); } else { hw_device_state(0); if (udc->udc_driver->notify_event) @@ -2390,7 +2398,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)) { struct ci13xxx *udc = _udc; - unsigned long i, k, flags; + unsigned long flags; + int i, j; int retval = -ENOMEM; trace("%p", driver); @@ -2427,45 +2436,46 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, info("hw_ep_max = %d", hw_ep_max); - udc->driver = driver; udc->gadget.dev.driver = NULL; retval = 0; - for (i = 0; i < hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < hw_ep_max/2; i++) { + for (j = RX; j <= TX; j++) { + int k = i + j * hw_ep_max/2; + struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; - scnprintf(mEp->name, sizeof(mEp->name), "ep%i", (int)i); + scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, + (j == TX) ? "in" : "out"); - mEp->lock = udc->lock; - mEp->device = &udc->gadget.dev; - mEp->td_pool = udc->td_pool; + mEp->lock = udc->lock; + mEp->device = &udc->gadget.dev; + mEp->td_pool = udc->td_pool; - mEp->ep.name = mEp->name; - mEp->ep.ops = &usb_ep_ops; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; + mEp->ep.name = mEp->name; + mEp->ep.ops = &usb_ep_ops; + mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; - /* this allocation cannot be random */ - for (k = RX; k <= TX; k++) { - INIT_LIST_HEAD(&mEp->qh[k].queue); + INIT_LIST_HEAD(&mEp->qh.queue); spin_unlock_irqrestore(udc->lock, flags); - mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, - GFP_KERNEL, - &mEp->qh[k].dma); + mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, + &mEp->qh.dma); spin_lock_irqsave(udc->lock, flags); - if (mEp->qh[k].ptr == NULL) + if (mEp->qh.ptr == NULL) retval = -ENOMEM; else - memset(mEp->qh[k].ptr, 0, - sizeof(*mEp->qh[k].ptr)); - } - if (i == 0) - udc->gadget.ep0 = &mEp->ep; - else + memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr)); + + /* skip ep0 out and in endpoints */ + if (i == 0) + continue; + list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); + } } if (retval) goto done; + udc->gadget.ep0 = &udc->ep0in.ep; /* bind gadget */ driver->driver.bus = NULL; udc->gadget.dev.driver = &driver->driver; @@ -2479,6 +2489,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, goto done; } + udc->driver = driver; pm_runtime_get_sync(&udc->gadget.dev); if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { if (udc->vbus_active) { @@ -2490,14 +2501,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, } } - retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); + retval = hw_device_state(udc->ep0out.qh.dma); if (retval) pm_runtime_put_sync(&udc->gadget.dev); done: spin_unlock_irqrestore(udc->lock, flags); - if (retval) - usb_gadget_unregister_driver(driver); return retval; } EXPORT_SYMBOL(usb_gadget_probe_driver); @@ -2510,7 +2519,7 @@ EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { struct ci13xxx *udc = _udc; - unsigned long i, k, flags; + unsigned long i, flags; trace("%p", driver); @@ -2546,17 +2555,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) for (i = 0; i < hw_ep_max; i++) { struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; - if (i == 0) - udc->gadget.ep0 = NULL; - else if (!list_empty(&mEp->ep.ep_list)) + if (!list_empty(&mEp->ep.ep_list)) list_del_init(&mEp->ep.ep_list); - for (k = RX; k <= TX; k++) - if (mEp->qh[k].ptr != NULL) - dma_pool_free(udc->qh_pool, - mEp->qh[k].ptr, mEp->qh[k].dma); + if (mEp->qh.ptr != NULL) + dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); } + udc->gadget.ep0 = NULL; udc->driver = NULL; spin_unlock_irqrestore(udc->lock, flags); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index f61fed07f76b..a2492b65f98c 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -20,7 +20,7 @@ * DEFINE *****************************************************************************/ #define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ -#define ENDPT_MAX (16) +#define ENDPT_MAX (32) #define CTRL_PAYLOAD_MAX (64) #define RX (0) /* similar to USB_DIR_OUT but can be used as an index */ #define TX (1) /* similar to USB_DIR_IN but can be used as an index */ @@ -88,8 +88,7 @@ struct ci13xxx_ep { struct list_head queue; struct ci13xxx_qh *ptr; dma_addr_t dma; - } qh[2]; - struct usb_request *status; + } qh; int wedge; /* global resources */ @@ -119,9 +118,13 @@ struct ci13xxx { struct dma_pool *qh_pool; /* DMA pool for queue heads */ struct dma_pool *td_pool; /* DMA pool for transfer descs */ + struct usb_request *status; /* ep0 status request */ struct usb_gadget gadget; /* USB slave device */ struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ + u32 ep0_dir; /* ep0 direction */ +#define ep0out ci13xxx_ep[0] +#define ep0in ci13xxx_ep[16] struct usb_gadget_driver *driver; /* 3rd party gadget driver */ struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index f6ff8456d52d..1ba4befe336b 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -928,8 +928,9 @@ unknown: */ switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: - if (cdev->config) - f = cdev->config->interface[intf]; + if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; break; case USB_RECIP_ENDPOINT: diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 0c8dd81dddca..b120dbb64d0f 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -198,10 +198,10 @@ #define PCH_UDC_BRLEN 0x0F /* Burst length */ #define PCH_UDC_THLEN 0x1F /* Threshold length */ /* Value of EP Buffer Size */ -#define UDC_EP0IN_BUFF_SIZE 64 -#define UDC_EPIN_BUFF_SIZE 512 -#define UDC_EP0OUT_BUFF_SIZE 64 -#define UDC_EPOUT_BUFF_SIZE 512 +#define UDC_EP0IN_BUFF_SIZE 16 +#define UDC_EPIN_BUFF_SIZE 256 +#define UDC_EP0OUT_BUFF_SIZE 16 +#define UDC_EPOUT_BUFF_SIZE 256 /* Value of EP maximum packet size */ #define UDC_EP0IN_MAX_PKT_SIZE 64 #define UDC_EP0OUT_MAX_PKT_SIZE 64 @@ -351,7 +351,7 @@ struct pch_udc_dev { struct pci_pool *data_requests; struct pci_pool *stp_requests; dma_addr_t dma_addr; - unsigned long ep0out_buf[64]; + void *ep0out_buf; struct usb_ctrlrequest setup_data; unsigned long phys_addr; void __iomem *base_addr; @@ -361,6 +361,8 @@ struct pch_udc_dev { #define PCH_UDC_PCI_BAR 1 #define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 +#define PCI_VENDOR_ID_ROHM 0x10DB +#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D static const char ep0_string[] = "ep0in"; static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */ @@ -1219,11 +1221,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, dev = ep->dev; if (req->dma_mapped) { if (ep->in) - pci_unmap_single(dev->pdev, req->req.dma, - req->req.length, PCI_DMA_TODEVICE); + dma_unmap_single(&dev->pdev->dev, req->req.dma, + req->req.length, DMA_TO_DEVICE); else - pci_unmap_single(dev->pdev, req->req.dma, - req->req.length, PCI_DMA_FROMDEVICE); + dma_unmap_single(&dev->pdev->dev, req->req.dma, + req->req.length, DMA_FROM_DEVICE); req->dma_mapped = 0; req->req.dma = DMA_ADDR_INVALID; } @@ -1414,7 +1416,6 @@ static void pch_udc_start_rxrequest(struct pch_udc_ep *ep, pch_udc_clear_dma(ep->dev, DMA_DIR_RX); td_data = req->td_data; - ep->td_data = req->td_data; /* Set the status bits for all descriptors */ while (1) { td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) | @@ -1613,15 +1614,19 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, if (usbreq->length && ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) { if (ep->in) - usbreq->dma = pci_map_single(dev->pdev, usbreq->buf, - usbreq->length, PCI_DMA_TODEVICE); + usbreq->dma = dma_map_single(&dev->pdev->dev, + usbreq->buf, + usbreq->length, + DMA_TO_DEVICE); else - usbreq->dma = pci_map_single(dev->pdev, usbreq->buf, - usbreq->length, PCI_DMA_FROMDEVICE); + usbreq->dma = dma_map_single(&dev->pdev->dev, + usbreq->buf, + usbreq->length, + DMA_FROM_DEVICE); req->dma_mapped = 1; } if (usbreq->length > 0) { - retval = prepare_dma(ep, req, gfp); + retval = prepare_dma(ep, req, GFP_ATOMIC); if (retval) goto probe_end; } @@ -1646,7 +1651,6 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, pch_udc_wait_ep_stall(ep); pch_udc_ep_clear_nak(ep); pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num)); - pch_udc_set_dma(dev, DMA_DIR_TX); } } /* Now add this request to the ep's pending requests */ @@ -1926,6 +1930,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep) PCH_UDC_BS_DMA_DONE) return; pch_udc_clear_dma(ep->dev, DMA_DIR_RX); + pch_udc_ep_set_ddptr(ep, 0); if ((req->td_data_last->status & PCH_UDC_RXTX_STS) != PCH_UDC_RTS_SUCC) { dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) " @@ -1963,7 +1968,7 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num) u32 epsts; struct pch_udc_ep *ep; - ep = &dev->ep[2*ep_num]; + ep = &dev->ep[UDC_EPIN_IDX(ep_num)]; epsts = ep->epsts; ep->epsts = 0; @@ -2008,7 +2013,7 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) struct pch_udc_ep *ep; struct pch_udc_request *req = NULL; - ep = &dev->ep[2*ep_num + 1]; + ep = &dev->ep[UDC_EPOUT_IDX(ep_num)]; epsts = ep->epsts; ep->epsts = 0; @@ -2025,10 +2030,11 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) } if (epsts & UDC_EPSTS_HE) return; - if (epsts & UDC_EPSTS_RSS) + if (epsts & UDC_EPSTS_RSS) { pch_udc_ep_set_stall(ep); pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); + } if (epsts & UDC_EPSTS_RCS) { if (!dev->prot_stall) { pch_udc_ep_clear_stall(ep); @@ -2060,8 +2066,10 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev) { u32 epsts; struct pch_udc_ep *ep; + struct pch_udc_ep *ep_out; ep = &dev->ep[UDC_EP0IN_IDX]; + ep_out = &dev->ep[UDC_EP0OUT_IDX]; epsts = ep->epsts; ep->epsts = 0; @@ -2073,8 +2081,16 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev) return; if (epsts & UDC_EPSTS_HE) return; - if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) + if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) { pch_udc_complete_transfer(ep); + pch_udc_clear_dma(dev, DMA_DIR_RX); + ep_out->td_data->status = (ep_out->td_data->status & + ~PCH_UDC_BUFF_STS) | + PCH_UDC_BS_HST_RDY; + pch_udc_ep_clear_nak(ep_out); + pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_ep_set_rrdy(ep_out); + } /* On IN interrupt, provide data if we have any */ if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) && !(epsts & UDC_EPSTS_TXEMPTY)) @@ -2102,11 +2118,9 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->stall = 0; dev->ep[UDC_EP0IN_IDX].halted = 0; dev->ep[UDC_EP0OUT_IDX].halted = 0; - /* In data not ready */ - pch_udc_ep_set_nak(&(dev->ep[UDC_EP0IN_IDX])); dev->setup_data = ep->td_stp->request; pch_udc_init_setup_buff(ep->td_stp); - pch_udc_clear_dma(dev, DMA_DIR_TX); + pch_udc_clear_dma(dev, DMA_DIR_RX); pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]), dev->ep[UDC_EP0IN_IDX].in); if ((dev->setup_data.bRequestType & USB_DIR_IN)) @@ -2122,14 +2136,23 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) setup_supported = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + + if (dev->setup_data.bRequestType & USB_DIR_IN) { + ep->td_data->status = (ep->td_data->status & + ~PCH_UDC_BUFF_STS) | + PCH_UDC_BS_HST_RDY; + pch_udc_ep_set_ddptr(ep, ep->td_data_phys); + } /* ep0 in returns data on IN phase */ if (setup_supported >= 0 && setup_supported < UDC_EP0IN_MAX_PKT_SIZE) { pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX])); /* Gadget would have queued a request when * we called the setup */ - pch_udc_set_dma(dev, DMA_DIR_RX); - pch_udc_ep_clear_nak(ep); + if (!(dev->setup_data.bRequestType & USB_DIR_IN)) { + pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_ep_clear_nak(ep); + } } else if (setup_supported < 0) { /* if unsupported request, then stall */ pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX])); @@ -2142,22 +2165,13 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) } } else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) == UDC_EPSTS_OUT_DATA) && !dev->stall) { - if (list_empty(&ep->queue)) { - dev_err(&dev->pdev->dev, "%s: No request\n", __func__); - ep->td_data->status = (ep->td_data->status & - ~PCH_UDC_BUFF_STS) | - PCH_UDC_BS_HST_RDY; - pch_udc_set_dma(dev, DMA_DIR_RX); - } else { - /* control write */ - /* next function will pickuo an clear the status */ + pch_udc_clear_dma(dev, DMA_DIR_RX); + pch_udc_ep_set_ddptr(ep, 0); + if (!list_empty(&ep->queue)) { ep->epsts = stat; - - pch_udc_svc_data_out(dev, 0); - /* re-program desc. pointer for possible ZLPs */ - pch_udc_ep_set_ddptr(ep, ep->td_data_phys); - pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_svc_data_out(dev, PCH_UDC_EP0); } + pch_udc_set_dma(dev, DMA_DIR_RX); } pch_udc_ep_set_rrdy(ep); } @@ -2174,7 +2188,7 @@ static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num) struct pch_udc_ep *ep; struct pch_udc_request *req; - ep = &dev->ep[2*ep_num]; + ep = &dev->ep[UDC_EPIN_IDX(ep_num)]; if (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct pch_udc_request, queue); pch_udc_enable_ep_interrupts(ep->dev, @@ -2196,13 +2210,13 @@ static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr) for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) { /* IN */ if (ep_intr & (0x1 << i)) { - ep = &dev->ep[2*i]; + ep = &dev->ep[UDC_EPIN_IDX(i)]; ep->epsts = pch_udc_read_ep_status(ep); pch_udc_clear_ep_status(ep, ep->epsts); } /* OUT */ if (ep_intr & (0x10000 << i)) { - ep = &dev->ep[2*i+1]; + ep = &dev->ep[UDC_EPOUT_IDX(i)]; ep->epsts = pch_udc_read_ep_status(ep); pch_udc_clear_ep_status(ep, ep->epsts); } @@ -2563,9 +2577,6 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE; dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE; - dev->dma_addr = pci_map_single(dev->pdev, dev->ep0out_buf, 256, - PCI_DMA_FROMDEVICE); - /* remove ep0 in and out from the list. They have own pointer */ list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list); list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list); @@ -2637,6 +2648,13 @@ static int init_dma_pools(struct pch_udc_dev *dev) dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0; dev->ep[UDC_EP0IN_IDX].td_data = NULL; dev->ep[UDC_EP0IN_IDX].td_data_phys = 0; + + dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL); + if (!dev->ep0out_buf) + return -ENOMEM; + dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf, + UDC_EP0OUT_BUFF_SIZE * 4, + DMA_FROM_DEVICE); return 0; } @@ -2700,7 +2718,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); - /* Assues that there are no pending requets with this driver */ + /* Assures that there are no pending requests with this driver */ + driver->disconnect(&dev->gadget); driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; dev->driver = NULL; @@ -2750,6 +2769,11 @@ static void pch_udc_remove(struct pci_dev *pdev) pci_pool_destroy(dev->stp_requests); } + if (dev->dma_addr) + dma_unmap_single(&dev->pdev->dev, dev->dma_addr, + UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); + kfree(dev->ep0out_buf); + pch_udc_exit(dev); if (dev->irq_registered) @@ -2792,11 +2816,7 @@ static int pch_udc_resume(struct pci_dev *pdev) int ret; pci_set_power_state(pdev, PCI_D0); - ret = pci_restore_state(pdev); - if (ret) { - dev_err(&pdev->dev, "%s: pci_restore_state failed\n", __func__); - return ret; - } + pci_restore_state(pdev); ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__); @@ -2914,6 +2934,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, .class_mask = 0xffffffff, }, + { + PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC), + .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, + .class_mask = 0xffffffff, + }, { 0 }, }; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 2fc8636316c5..12ff6cffedc9 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -131,31 +131,31 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort __initdata idVendor; +static ushort idVendor; module_param(idVendor, ushort, S_IRUGO); MODULE_PARM_DESC(idVendor, "USB Vendor ID"); -static ushort __initdata idProduct; +static ushort idProduct; module_param(idProduct, ushort, S_IRUGO); MODULE_PARM_DESC(idProduct, "USB Product ID"); -static ushort __initdata bcdDevice; +static ushort bcdDevice; module_param(bcdDevice, ushort, S_IRUGO); MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); -static char *__initdata iManufacturer; +static char *iManufacturer; module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); -static char *__initdata iProduct; +static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); -static char *__initdata iSerialNum; +static char *iSerialNum; module_param(iSerialNum, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); -static char *__initdata iPNPstring; +static char *iPNPstring; module_param(iPNPstring, charp, S_IRUGO); MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"); @@ -1596,13 +1596,12 @@ cleanup(void) int status; mutex_lock(&usb_printer_gadget.lock_printer_io); - class_destroy(usb_gadget_class); - unregister_chrdev_region(g_printer_devno, 2); - status = usb_gadget_unregister_driver(&printer_driver); if (status) ERROR(dev, "usb_gadget_unregister_driver %x\n", status); + unregister_chrdev_region(g_printer_devno, 2); + class_destroy(usb_gadget_class); mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 86e42892016d..5c761df7fa83 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -52,7 +52,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, struct resource *res; int irq; int retval; - unsigned int temp; pr_debug("initializing FSL-SOC USB Controller\n"); @@ -126,18 +125,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, goto err3; } - /* - * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs - * flag for 83xx or 8536 system interface registers. - */ - if (pdata->big_endian_mmio) - temp = in_be32(hcd->regs + FSL_SOC_USB_ID); - else - temp = in_le32(hcd->regs + FSL_SOC_USB_ID); - - if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) - pdata->have_sysif_regs = 1; - /* Enable USB controller, 83xx or 8536 */ if (pdata->have_sysif_regs) setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 2c8353795226..3fabed33d940 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -19,9 +19,6 @@ #define _EHCI_FSL_H /* offsets for the non-ehci registers in the FSL SOC USB controller */ -#define FSL_SOC_USB_ID 0x0 -#define ID_MSK 0x3f -#define NID_MSK 0x3f00 #define FSL_SOC_USB_ULPIVP 0x170 #define FSL_SOC_USB_PORTSC1 0x184 #define PORT_PTS_MSK (3<<30) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 6fee3cd58efe..74dcf49bd015 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -572,6 +572,8 @@ static int ehci_init(struct usb_hcd *hcd) ehci->iaa_watchdog.function = ehci_iaa_watchdog; ehci->iaa_watchdog.data = (unsigned long) ehci; + hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -579,11 +581,20 @@ static int ehci_init(struct usb_hcd *hcd) ehci->periodic_size = DEFAULT_I_TDPS; INIT_LIST_HEAD(&ehci->cached_itd_list); INIT_LIST_HEAD(&ehci->cached_sitd_list); + + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + switch (EHCI_TUNE_FLS) { + case 0: ehci->periodic_size = 1024; break; + case 1: ehci->periodic_size = 512; break; + case 2: ehci->periodic_size = 256; break; + default: BUG(); + } + } if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 2 + 8; else // N microframes cached @@ -637,12 +648,6 @@ static int ehci_init(struct usb_hcd *hcd) /* periodic schedule size can be smaller than default */ temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); - switch (EHCI_TUNE_FLS) { - case 0: ehci->periodic_size = 1024; break; - case 1: ehci->periodic_size = 512; break; - case 2: ehci->periodic_size = 256; break; - default: BUG(); - } } if (HCC_LPM(hcc_params)) { /* support link power management EHCI 1.1 addendum */ diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index fa59b26fc5bc..c8e360d7d975 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -21,10 +21,13 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/usb/otg.h> +#include <linux/usb/ulpi.h> #include <linux/slab.h> #include <mach/mxc_ehci.h> +#include <asm/mach-types.h> + #define ULPI_VIEWPORT_OFFSET 0x170 struct ehci_mxc_priv { @@ -114,6 +117,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct resource *res; int irq, ret; + unsigned int flags; struct ehci_mxc_priv *priv; struct device *dev = &pdev->dev; struct ehci_hcd *ehci; @@ -177,8 +181,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) clk_enable(priv->ahbclk); } - /* "dr" device has its own clock */ - if (pdev->id == 0) { + /* "dr" device has its own clock on i.MX51 */ + if (cpu_is_mx51() && (pdev->id == 0)) { priv->phy1clk = clk_get(dev, "usb_phy1"); if (IS_ERR(priv->phy1clk)) { ret = PTR_ERR(priv->phy1clk); @@ -240,6 +244,23 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (ret) goto err_add; + if (pdata->otg) { + /* + * efikamx and efikasb have some hardware bug which is + * preventing usb to work unless CHRGVBUS is set. + * It's in violation of USB specs + */ + if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { + flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL); + flags |= ULPI_OTG_CTRL_CHRGVBUS; + ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL); + if (ret) { + dev_err(dev, "unable to set CHRVBUS\n"); + goto err_add; + } + } + } + return 0; err_add: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 76179c39c0e3..bed07d4aab06 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -44,28 +44,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } -static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) +static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci) { struct pci_dev *amd_smbus_dev; u8 rev = 0; amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); - if (!amd_smbus_dev) - return 0; - - pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); - if (rev < 0x40) { - pci_dev_put(amd_smbus_dev); - amd_smbus_dev = NULL; - return 0; + if (amd_smbus_dev) { + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x40) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } + } else { + amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL); + if (!amd_smbus_dev) + return 0; + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x11 || rev > 0x18) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } } if (!amd_nb_dev) amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (!amd_nb_dev) - ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); - ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); + ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n"); pci_dev_put(amd_smbus_dev); amd_smbus_dev = NULL; @@ -131,7 +138,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (ehci_quirk_amd_SB800(ehci)) + if (ehci_quirk_amd_hudson(ehci)) ehci->amd_l1_fix = 1; retval = ehci_halt(ehci); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 574b99ea0700..79a66d622f9c 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -262,19 +262,24 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev) } } -struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { +static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { .big_endian_desc = 1, .big_endian_mmio = 1, .es = 1, + .have_sysif_regs = 0, .le_setup_buf = 1, .init = fsl_usb2_mpc5121_init, .exit = fsl_usb2_mpc5121_exit, }; #endif /* CONFIG_PPC_MPC512x */ +static struct fsl_usb2_platform_data fsl_usb2_mpc8xxx_pd = { + .have_sysif_regs = 1, +}; + static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { - { .compatible = "fsl-usb2-mph", }, - { .compatible = "fsl-usb2-dr", }, + { .compatible = "fsl-usb2-mph", .data = &fsl_usb2_mpc8xxx_pd, }, + { .compatible = "fsl-usb2-dr", .data = &fsl_usb2_mpc8xxx_pd, }, #ifdef CONFIG_PPC_MPC512x { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, }, #endif diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index df558f6f84e3..3e8211c1ce5a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -308,11 +308,8 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { - u32 temp; - xhci_dbg(xhci, "// Ding dong!\n"); - temp = xhci_readl(xhci, &xhci->dba->doorbell[0]) & DB_MASK; - xhci_writel(xhci, temp | DB_TARGET_HOST, &xhci->dba->doorbell[0]); + xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ xhci_readl(xhci, &xhci->dba->doorbell[0]); } @@ -322,26 +319,24 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int ep_index, unsigned int stream_id) { - struct xhci_virt_ep *ep; - unsigned int ep_state; - u32 field; __u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id]; + struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; + unsigned int ep_state = ep->ep_state; - ep = &xhci->devs[slot_id]->eps[ep_index]; - ep_state = ep->ep_state; /* Don't ring the doorbell for this endpoint if there are pending - * cancellations because the we don't want to interrupt processing. + * cancellations because we don't want to interrupt processing. * We don't want to restart any stream rings if there's a set dequeue * pointer command pending because the device can choose to start any * stream once the endpoint is on the HW schedule. * FIXME - check all the stream rings for pending cancellations. */ - if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING) - && !(ep_state & EP_HALTED)) { - field = xhci_readl(xhci, db_addr) & DB_MASK; - field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id); - xhci_writel(xhci, field, db_addr); - } + if ((ep_state & EP_HALT_PENDING) || (ep_state & SET_DEQ_PENDING) || + (ep_state & EP_HALTED)) + return; + xhci_writel(xhci, DB_VALUE(ep_index, stream_id), db_addr); + /* The CPU has better things to do at this point than wait for a + * write-posting flush. It'll get there soon enough. + */ } /* Ring the doorbell for any rings with pending URBs */ @@ -1188,7 +1183,7 @@ static void handle_port_status(struct xhci_hcd *xhci, addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1); temp = xhci_readl(xhci, addr); - if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) { + if (hcd->state == HC_STATE_SUSPENDED) { xhci_dbg(xhci, "resume root hub\n"); usb_hcd_resume_root_hub(hcd); } @@ -1710,8 +1705,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, /* Others already handled above */ break; } - dev_dbg(&td->urb->dev->dev, - "ep %#x - asked for %d bytes, " + xhci_dbg(xhci, "ep %#x - asked for %d bytes, " "%d bytes untransferred\n", td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, @@ -2389,7 +2383,8 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) } xhci_dbg(xhci, "\n"); if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %d, sglist used, num_trbs = %d\n", + xhci_dbg(xhci, "ep %#x - urb len = %d, sglist used, " + "num_trbs = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, num_trbs); @@ -2414,14 +2409,17 @@ static void check_trb_math(struct urb *urb, int num_trbs, int running_total) static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index, unsigned int stream_id, int start_cycle, - struct xhci_generic_trb *start_trb, struct xhci_td *td) + struct xhci_generic_trb *start_trb) { /* * Pass all the TRBs to the hardware at once and make sure this write * isn't reordered. */ wmb(); - start_trb->field[3] |= start_cycle; + if (start_cycle) + start_trb->field[3] |= start_cycle; + else + start_trb->field[3] &= ~0x1; xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } @@ -2449,7 +2447,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { - if (!printk_ratelimit()) + if (printk_ratelimit()) dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", @@ -2551,9 +2549,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u32 remainder = 0; /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) + if (first_trb) { first_trb = false; - else + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; /* Chain all the TRBs together; clear the chain bit in the last @@ -2625,7 +2625,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2671,7 +2671,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d), addr = %#llx, num_trbs = %d\n", + xhci_dbg(xhci, "ep %#x - urb len = %#x (%d), " + "addr = %#llx, num_trbs = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, urb->transfer_buffer_length, @@ -2711,9 +2712,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field = 0; /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) + if (first_trb) { first_trb = false; - else + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; /* Chain all the TRBs together; clear the chain bit in the last @@ -2757,7 +2760,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2818,13 +2821,17 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Queue setup TRB - see section 6.4.1.2.1 */ /* FIXME better way to translate setup_packet into two u32 fields? */ setup = (struct usb_ctrlrequest *) urb->setup_packet; + field = 0; + field |= TRB_IDT | TRB_TYPE(TRB_SETUP); + if (start_cycle == 0) + field |= 0x1; queue_trb(xhci, ep_ring, false, true, /* FIXME endianness is probably going to bite my ass here. */ setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16, setup->wIndex | setup->wLength << 16, TRB_LEN(8) | TRB_INTR_TARGET(0), /* Immediate data in pointer */ - TRB_IDT | TRB_TYPE(TRB_SETUP)); + field); /* If there's data, queue data TRBs */ field = 0; @@ -2859,7 +2866,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state); giveback_first_trb(xhci, slot_id, ep_index, 0, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2900,6 +2907,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int running_total, trb_buff_len, td_len, td_remain_len, ret; u64 start_addr, addr; int i, j; + bool more_trbs_coming; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; @@ -2910,7 +2918,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d)," + xhci_dbg(xhci, "ep %#x - urb len = %#x (%d)," " addr = %#llx, num_tds = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, @@ -2950,7 +2958,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field |= TRB_TYPE(TRB_ISOC); /* Assume URB_ISO_ASAP is set */ field |= TRB_SIA; - if (i > 0) + if (i == 0) { + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; first_trb = false; } else { @@ -2965,9 +2976,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, */ if (j < trbs_per_td - 1) { field |= TRB_CHAIN; + more_trbs_coming = true; } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; + more_trbs_coming = false; } /* Calculate TRB length */ @@ -2980,7 +2993,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, length_field = TRB_LEN(trb_buff_len) | remainder | TRB_INTR_TARGET(0); - queue_trb(xhci, ep_ring, false, false, + queue_trb(xhci, ep_ring, false, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), length_field, @@ -3003,10 +3016,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } } - wmb(); - start_trb->field[3] |= start_cycle; - - xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, + start_cycle, start_trb); return 0; } @@ -3064,7 +3075,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { - if (!printk_ratelimit()) + if (printk_ratelimit()) dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 45e4a3108cc3..34cf4e165877 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) static int xhci_setup_msix(struct xhci_hcd *xhci) { int i, ret = 0; - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); /* * calculate number of msi-x vectors supported. @@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) goto disable_msix; } + hcd->msix_enabled = 1; return ret; disable_msix: @@ -280,7 +282,8 @@ free_entries: /* Free any IRQs and disable MSI-X */ static void xhci_cleanup_msix(struct xhci_hcd *xhci) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); xhci_free_irq(xhci); @@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) pci_disable_msi(pdev); } + hcd->msix_enabled = 0; return; } @@ -508,9 +512,10 @@ void xhci_stop(struct usb_hcd *hcd) spin_lock_irq(&xhci->lock); xhci_halt(xhci); xhci_reset(xhci); - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); + #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING /* Tell the event ring poll function not to reschedule */ xhci->zombie = 1; @@ -544,9 +549,10 @@ void xhci_shutdown(struct usb_hcd *hcd) spin_lock_irq(&xhci->lock); xhci_halt(xhci); - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); + xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n", xhci_readl(xhci, &xhci->op_regs->status)); } @@ -647,6 +653,7 @@ int xhci_suspend(struct xhci_hcd *xhci) int rc = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + int i; spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -677,10 +684,15 @@ int xhci_suspend(struct xhci_hcd *xhci) spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } - /* step 5: remove core well power */ - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + /* step 5: remove core well power */ + /* synchronize irq when using MSI-X */ + if (xhci->msix_entries) { + for (i = 0; i < xhci->msix_count; i++) + synchronize_irq(xhci->msix_entries[i].vector); + } + return rc; } @@ -694,7 +706,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) { u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int old_state, retval; old_state = hcd->state; @@ -729,9 +740,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "Stop HCD\n"); xhci_halt(xhci); xhci_reset(xhci); - if (hibernated) - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING /* Tell the event ring poll function not to reschedule */ @@ -765,30 +775,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) return retval; } - spin_unlock_irq(&xhci->lock); - /* Re-setup MSI-X */ - if (hcd->irq) - free_irq(hcd->irq, hcd); - hcd->irq = -1; - - retval = xhci_setup_msix(xhci); - if (retval) - /* fall back to msi*/ - retval = xhci_setup_msi(xhci); - - if (retval) { - /* fall back to legacy interrupt*/ - retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, - hcd->irq_descr, hcd); - if (retval) { - xhci_err(xhci, "request interrupt %d failed\n", - pdev->irq); - return retval; - } - hcd->irq = pdev->irq; - } - - spin_lock_irq(&xhci->lock); /* step 4: set Run/Stop bit */ command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_RUN; @@ -2445,8 +2431,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_err(xhci, "Error while assigning device slot ID\n"); return 0; } - /* xhci_alloc_virt_device() does not touch rings; no need to lock */ - if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) { + /* xhci_alloc_virt_device() does not touch rings; no need to lock. + * Use GFP_NOIO, since this function can be called from + * xhci_discover_or_reset_device(), which may be called as part of + * mass storage driver error handling. + */ + if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) { /* Disable slot, if we can do it without mem alloc */ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); spin_lock_irqsave(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 170c367112d2..7f236fd22015 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -436,22 +436,18 @@ struct xhci_run_regs { /** * struct doorbell_array * + * Bits 0 - 7: Endpoint target + * Bits 8 - 15: RsvdZ + * Bits 16 - 31: Stream ID + * * Section 5.6 */ struct xhci_doorbell_array { u32 doorbell[256]; }; -#define DB_TARGET_MASK 0xFFFFFF00 -#define DB_STREAM_ID_MASK 0x0000FFFF -#define DB_TARGET_HOST 0x0 -#define DB_STREAM_ID_HOST 0x0 -#define DB_MASK (0xff << 8) - -/* Endpoint Target - bits 0:7 */ -#define EPI_TO_DB(p) (((p) + 1) & 0xff) -#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16) - +#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) +#define DB_VALUE_HOST 0x00000000 /** * struct xhci_protocol_caps diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 1732d9bc097e..1616ad1793a4 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -45,7 +45,7 @@ struct usb_led { static void change_color(struct usb_led *led) { - int retval; + int retval = 0; unsigned char *buffer; buffer = kmalloc(8, GFP_KERNEL); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 4ff21587ab03..f7a205738032 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -776,7 +776,6 @@ static const struct usb_device_id uss720_table[] = { { USB_DEVICE(0x0557, 0x2001) }, { USB_DEVICE(0x0729, 0x1284) }, { USB_DEVICE(0x1293, 0x0002) }, - { USB_DEVICE(0x1293, 0x0002) }, { USB_DEVICE(0x050d, 0x0002) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index e70014ab0976..8acf165fe13b 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -132,6 +132,8 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); + BLOCKING_INIT_NOTIFIER_HEAD(&nop->otg.notifier); + return 0; exit: kfree(nop); diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 059d9ac0ab5b..770d799d5afb 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -45,7 +45,7 @@ struct ulpi_info { /* ULPI hardcoded IDs, used for probing */ static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), - ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"), + ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), }; static int ulpi_set_otg_flags(struct otg_transceiver *otg) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 63f7cc45bcac..7b8815ddf368 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb) if (actual_length >= 4) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; + u8 prev_line_status = priv->line_status; spin_lock_irqsave(&priv->lock, flags); priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; if ((data[1] & CH341_MULT_STAT)) priv->multi_status_change = 1; spin_unlock_irqrestore(&priv->lock, flags); + + if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & CH341_BIT_DCD); + tty_kref_put(tty); + } + wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8d7731dbf478..735ea03157ab 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,7 +49,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); -static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; @@ -87,7 +86,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ - { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ @@ -110,7 +108,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ + { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ @@ -165,8 +165,7 @@ static struct usb_serial_driver cp210x_device = { .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, - .dtr_rts = cp210x_dtr_rts, - .carrier_raised = cp210x_carrier_raised + .dtr_rts = cp210x_dtr_rts }; /* Config request types */ @@ -765,15 +764,6 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) return result; } -static int cp210x_carrier_raised(struct usb_serial_port *p) -{ - unsigned int control; - cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1); - if (control & CONTROL_DCD) - return 1; - return 0; -} - static void cp210x_break_ctl (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b92070c103cd..666e5a6edd82 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,7 +455,6 @@ static int digi_write_room(struct tty_struct *tty); static int digi_chars_in_buffer(struct tty_struct *tty); static int digi_open(struct tty_struct *tty, struct usb_serial_port *port); static void digi_close(struct usb_serial_port *port); -static int digi_carrier_raised(struct usb_serial_port *port); static void digi_dtr_rts(struct usb_serial_port *port, int on); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); @@ -511,7 +510,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .open = digi_open, .close = digi_close, .dtr_rts = digi_dtr_rts, - .carrier_raised = digi_carrier_raised, .write = digi_write, .write_room = digi_write_room, .write_bulk_callback = digi_write_bulk_callback, @@ -1339,14 +1337,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on) digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); } -static int digi_carrier_raised(struct usb_serial_port *port) -{ - struct digi_port *priv = usb_get_serial_port_data(port); - if (priv->dp_modem_signals & TIOCM_CD) - return 1; - return 0; -} - static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) { int ret; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a2668d089260..4787c0cd063f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -676,7 +676,17 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, - { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index bf0867285481..ed160def8584 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -569,11 +569,23 @@ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* - * Icom ID-1 digital transceiver - */ - -#define ICOM_ID1_VID 0x0C26 -#define ICOM_ID1_PID 0x0004 + * Definitions for Icom Inc. devices + */ +#define ICOM_VID 0x0C26 /* Icom vendor ID */ +/* Note: ID-1 is a communications tranceiver for HAM-radio operators */ +#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */ +/* Note: OPC is an Optional cable to connect an Icom Tranceiver */ +#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */ +/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */ +#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */ +#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */ +#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/ +#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */ +#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */ +#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */ +#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */ +#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */ +#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */ /* * GN Otometrics (http://www.otometrics.com) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e6833e216fc9..e4db5ad2bc55 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -479,6 +479,26 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); +/** + * usb_serial_handle_dcd_change - handle a change of carrier detect state + * @port: usb_serial_port structure for the open port + * @tty: tty_struct structure for the port + * @status: new carrier detect status, nonzero if active + */ +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, unsigned int status) +{ + struct tty_port *port = &usb_port->port; + + dbg("%s - port %d, status %d", __func__, usb_port->number, status); + + if (status) + wake_up_interruptible(&port->open_wait); + else if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); +} +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); + int usb_serial_generic_resume(struct usb_serial *serial) { struct usb_serial_port *port; diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 6ab2a3f97fe8..178b22eb32b1 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -199,6 +199,7 @@ static struct usb_serial_driver epic_device = { .name = "epic", }, .description = "EPiC device", + .usb_driver = &io_driver, .id_table = Epic_port_id_table, .num_ports = 1, .open = edge_open, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 12ed594f5f80..99b97c04896f 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1275,6 +1275,7 @@ static struct usb_serial_driver iuu_device = { .name = "iuu_phoenix", }, .id_table = id_table, + .usb_driver = &iuu_driver, .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 2d8baf6ac472..ce134dc28ddf 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -546,6 +546,7 @@ static struct usb_serial_driver keyspan_pre_device = { .name = "keyspan_no_firm", }, .description = "Keyspan - (without firmware)", + .usb_driver = &keyspan_driver, .id_table = keyspan_pre_ids, .num_ports = 1, .attach = keyspan_fake_startup, @@ -557,6 +558,7 @@ static struct usb_serial_driver keyspan_1port_device = { .name = "keyspan_1", }, .description = "Keyspan 1 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_1port_ids, .num_ports = 1, .open = keyspan_open, @@ -579,6 +581,7 @@ static struct usb_serial_driver keyspan_2port_device = { .name = "keyspan_2", }, .description = "Keyspan 2 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_2port_ids, .num_ports = 2, .open = keyspan_open, @@ -601,6 +604,7 @@ static struct usb_serial_driver keyspan_4port_device = { .name = "keyspan_4", }, .description = "Keyspan 4 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_4port_ids, .num_ports = 4, .open = keyspan_open, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index a10dd5676ccc..554a8693a463 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -679,22 +679,6 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) } } -static int keyspan_pda_carrier_raised(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - unsigned char modembits; - - /* If we can read the modem status and the DCD is low then - carrier is not raised yet */ - if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) { - if (!(modembits & (1>>6))) - return 0; - } - /* Carrier raised, or we failed (eg disconnected) so - progress accordingly */ - return 1; -} - static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -881,7 +865,6 @@ static struct usb_serial_driver keyspan_pda_device = { .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, - .carrier_raised = keyspan_pda_carrier_raised, .open = keyspan_pda_open, .close = keyspan_pda_close, .write = keyspan_pda_write, diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index cf1718394e18..653465f61d4a 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -44,6 +44,7 @@ static struct usb_serial_driver moto_device = { .name = "moto-modem", }, .id_table = id_table, + .usb_driver = &moto_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 748778288d94..5f46838dfee5 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -382,7 +382,16 @@ static void option_instat_callback(struct urb *urb); #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 -#define CINTERION_VENDOR_ID 0x0681 +/* Cinterion (formerly Siemens) products */ +#define SIEMENS_VENDOR_ID 0x0681 +#define CINTERION_VENDOR_ID 0x1e2d +#define CINTERION_PRODUCT_HC25_MDM 0x0047 +#define CINTERION_PRODUCT_HC25_MDMNET 0x0040 +#define CINTERION_PRODUCT_HC28_MDM 0x004C +#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */ +#define CINTERION_PRODUCT_EU3_E 0x0051 +#define CINTERION_PRODUCT_EU3_P 0x0052 +#define CINTERION_PRODUCT_PH8 0x0053 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -944,7 +953,17 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, - { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, + /* Cinterion */ + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */ + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 5be866bb7a41..73613205be7a 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -157,6 +157,7 @@ static struct usb_serial_driver oti6858_device = { .name = "oti6858", }, .id_table = id_table, + .usb_driver = &oti6858_driver, .num_ports = 1, .open = oti6858_open, .close = oti6858_close, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8ae4c6cbc38a..08c9181b8e48 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -50,6 +50,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, @@ -677,9 +678,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port, { struct pl2303_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; + u8 prev_line_status; u16 idv, idp; idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); @@ -701,11 +704,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port, /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); + prev_line_status = priv->line_status; priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); wake_up_interruptible(&priv->delta_msr_wait); + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + if ((priv->line_status ^ prev_line_status) & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & UART_DCD); + tty_kref_put(tty); } static void pl2303_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 43eb9bdad422..1b025f75dafd 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -21,6 +21,7 @@ #define PL2303_PRODUCT_ID_MMX 0x0612 #define PL2303_PRODUCT_ID_GPRS 0x0609 #define PL2303_PRODUCT_ID_HCR331 0x331a +#define PL2303_PRODUCT_ID_MOTOROLA 0x0307 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 214a3e504292..30b73e68a904 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,6 +36,7 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 +#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -66,6 +67,7 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); @@ -84,6 +86,7 @@ static struct usb_serial_driver qcaux_device = { .name = "qcaux", }, .id_table = id_table, + .usb_driver = &qcaux_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index cb8195cabfde..74cd4ccdb3fc 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -42,6 +42,7 @@ static struct usb_serial_driver siemens_usb_mpi_device = { .name = "siemens_mpi", }, .id_table = id_table, + .usb_driver = &siemens_usb_mpi_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 765aa983bf58..cbfb70bffdd0 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -133,7 +133,7 @@ struct spcp8x5_usb_ctrl_arg { /* how come ??? */ #define UART_STATE 0x08 -#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_STATE_TRANSIENT_MASK 0x75 #define UART_DCD 0x01 #define UART_DSR 0x02 #define UART_BREAK_ERROR 0x04 @@ -525,6 +525,10 @@ static void spcp8x5_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + if (status & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & MSR_STATUS_LINE_DCD); } tty_insert_flip_string_fixed_flag(tty, data, tty_flag, @@ -645,6 +649,7 @@ static struct usb_serial_driver spcp8x5_device = { .name = "SPCP8x5", }, .id_table = id_table, + .usb_driver = &spcp8x5_driver, .num_ports = 1, .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6954de50c0ff..546a52179bec 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1344,11 +1344,15 @@ int usb_serial_register(struct usb_serial_driver *driver) return -ENODEV; fixup_generic(driver); - if (driver->usb_driver) - driver->usb_driver->supports_autosuspend = 1; if (!driver->description) driver->description = driver->driver.name; + if (!driver->usb_driver) { + WARN(1, "Serial driver %s has no usb_driver\n", + driver->description); + return -EINVAL; + } + driver->usb_driver->supports_autosuspend = 1; /* Add this device to our list of devices */ mutex_lock(&table_lock); diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index f2ed6a31be77..95a82148ee81 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -75,6 +75,7 @@ static struct usb_serial_driver debug_device = { .name = "debug", }, .id_table = id_table, + .usb_driver = &debug_driver, .num_ports = 1, .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, .break_ctl = usb_debug_break_ctl, diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index c854fdebe0ae..2c8553026222 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,4 +31,9 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, + "Super Top", + "USB 2.0 SATA BRIDGE", + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), + #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index fcc1e32ce256..24bd5d7c3deb 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1044,6 +1044,15 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BULK32), +/* Reported by <ttkspam@free.fr> + * The device reports a vendor-specific device class, requiring an + * explicit vendor/product match. + */ +UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002, + "MagicPixel", + "FW_Omega2", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), + /* Andrew Lunn <andrew@lunn.ch> * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL * on LUN 4. @@ -1872,6 +1881,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* Patch by Richard Schtz <r.schtz@t-online.de> + * This external hard drive enclosure uses a JMicron chip which + * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ +UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000, + "TrekStor GmbH & Co. KG", + "DataStation maxi g.u", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", "2A", |