diff options
Diffstat (limited to 'drivers')
227 files changed, 2508 insertions, 1555 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index e8eb91bd0d28..a2fc56d2e681 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -546,7 +546,8 @@ EXPORT_SYMBOL_GPL(amba_device_add); static struct amba_device * amba_aphb_device_add(struct device *parent, const char *name, resource_size_t base, size_t size, int irq1, int irq2, - void *pdata, unsigned int periphid, u64 dma_mask) + void *pdata, unsigned int periphid, u64 dma_mask, + struct resource *resbase) { struct amba_device *dev; int ret; @@ -563,7 +564,7 @@ amba_aphb_device_add(struct device *parent, const char *name, dev->dev.platform_data = pdata; dev->dev.parent = parent; - ret = amba_device_add(dev, &iomem_resource); + ret = amba_device_add(dev, resbase); if (ret) { amba_device_put(dev); return ERR_PTR(ret); @@ -578,7 +579,7 @@ amba_apb_device_add(struct device *parent, const char *name, void *pdata, unsigned int periphid) { return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, - periphid, 0); + periphid, 0, &iomem_resource); } EXPORT_SYMBOL_GPL(amba_apb_device_add); @@ -588,10 +589,33 @@ amba_ahb_device_add(struct device *parent, const char *name, void *pdata, unsigned int periphid) { return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, - periphid, ~0ULL); + periphid, ~0ULL, &iomem_resource); } EXPORT_SYMBOL_GPL(amba_ahb_device_add); +struct amba_device * +amba_apb_device_add_res(struct device *parent, const char *name, + resource_size_t base, size_t size, int irq1, + int irq2, void *pdata, unsigned int periphid, + struct resource *resbase) +{ + return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, + periphid, 0, resbase); +} +EXPORT_SYMBOL_GPL(amba_apb_device_add_res); + +struct amba_device * +amba_ahb_device_add_res(struct device *parent, const char *name, + resource_size_t base, size_t size, int irq1, + int irq2, void *pdata, unsigned int periphid, + struct resource *resbase) +{ + return amba_aphb_device_add(parent, name, base, size, irq1, irq2, pdata, + periphid, ~0ULL, resbase); +} +EXPORT_SYMBOL_GPL(amba_ahb_device_add_res); + + static void amba_device_initialize(struct amba_device *dev, const char *name) { device_initialize(&dev->dev); diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index b1ae48054dc5..b7078afddb74 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_suspend(struct device *dev) { struct ahci_platform_data *pdata = dev_get_platdata(dev); diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index fd9ecf74e631..5b0ba3f20edc 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c @@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, struct acpi_device *acpi_dev; struct acpi_device_power_state *states; - if (ap->flags & ATA_FLAG_ACPI_SATA) - ata_dev = &ap->link.device[sdev->channel]; - else + if (ap->flags & ATA_FLAG_ACPI_SATA) { + if (!sata_pmp_attached(ap)) + ata_dev = &ap->link.device[sdev->id]; + else + ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id]; + } + else { ata_dev = &ap->link.device[sdev->id]; + } *handle = ata_dev_acpi_handle(ata_dev); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 3cc7096cfda7..f46fbd3bd3fb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode) if (xfer_mode == t->mode) return t; + + WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n", + __func__, xfer_mode); + return NULL; } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index e3bda074fa12..a6df6a351d6e 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev) { sdev->use_10_for_rw = 1; sdev->use_10_for_ms = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; /* Schedule policy is determined by ->qc_defer() callback and * it needs to see every deferred qc. Set dev_blocked to 1 to diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 26201ebef3ca..371fd2c698b7 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev) return ret; } + ret = clk_set_rate(acdev->clk, 166000000); + if (ret) { + dev_warn(acdev->host->dev, "clock set rate failed"); + return ret; + } + spin_lock_irqsave(&acdev->host->lock, flags); /* configure CF interface clock */ writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk : @@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int arasan_cf_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 0d7c4c2cd26f..400bf1c3e982 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = { }; MODULE_DEVICE_TABLE(of, ahci_of_match); -static int __init ahci_highbank_probe(struct platform_device *pdev) +static int __devinit ahci_highbank_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct ahci_host_priv *hpriv; @@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int ahci_highbank_suspend(struct device *dev) { struct ata_host *host = dev_get_drvdata(dev); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 44a4256533e1..08608de87e4e 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 8727e9c5eea4..72c776f2a1f5 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource); */ int platform_get_irq(struct platform_device *dev, unsigned int num) { +#ifdef CONFIG_SPARC + /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ + if (!dev || num >= dev->archdata.num_irqs) + return -ENXIO; + return dev->archdata.irqs[num]; +#else struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); return r ? r->start : -ENXIO; +#endif } EXPORT_SYMBOL_GPL(platform_get_irq); diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 74a67e0019a2..fbbd4ed2edf2 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 3804a0af3ef1..9fe4f1865558 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail) /* cf. http://lkml.org/lkml/2006/10/31/28 */ if (!fastfail) - q->request_fn(q); + __blk_run_queue(q); } static void diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 1c49d7173966..2ddd64a9ffde 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4330,6 +4330,7 @@ out_unreg_region: out_unreg_blkdev: unregister_blkdev(FLOPPY_MAJOR, "fd"); out_put_disk: + destroy_workqueue(floppy_wq); for (drive = 0; drive < N_DRIVE; drive++) { if (!disks[drive]) break; @@ -4340,7 +4341,6 @@ out_put_disk: } put_disk(disks[drive]); } - destroy_workqueue(floppy_wq); return err; } @@ -4555,6 +4555,8 @@ static void __exit floppy_module_exit(void) unregister_blkdev(FLOPPY_MAJOR, "fd"); platform_driver_unregister(&floppy_driver); + destroy_workqueue(floppy_wq); + for (drive = 0; drive < N_DRIVE; drive++) { del_timer_sync(&motor_off_timer[drive]); @@ -4578,7 +4580,6 @@ static void __exit floppy_module_exit(void) cancel_delayed_work_sync(&fd_timeout); cancel_delayed_work_sync(&fd_timer); - destroy_workqueue(floppy_wq); if (atomic_read(&usage_count)) floppy_release_irq_and_dma(); diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index adc6f36564cf..9694dd99bbbc 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data) struct mtip_cmd *command; int tag, cmdto_cnt = 0; unsigned int bit, group; - unsigned int num_command_slots = port->dd->slot_groups * 32; + unsigned int num_command_slots; unsigned long to, tagaccum[SLOTBITS_IN_LONGS]; if (unlikely(!port)) @@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data) } /* clear the tag accumulator */ memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long)); + num_command_slots = port->dd->slot_groups * 32; for (tag = 0; tag < num_command_slots; tag++) { /* @@ -2218,8 +2219,8 @@ static int exec_drive_taskfile(struct driver_data *dd, fis.device); /* check for erase mode support during secure erase.*/ - if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) - && (outbuf[0] & MTIP_SEC_ERASE_MODE)) { + if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf && + (outbuf[0] & MTIP_SEC_ERASE_MODE)) { erasemode = 1; } @@ -2439,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * return value * None */ -static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, +static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector, int nsect, int nents, int tag, void *callback, void *data, int dir) { @@ -2447,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, struct mtip_port *port = dd->port; struct mtip_cmd *command = &port->commands[tag]; int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + u64 start = sector; /* Map the scatter list for DMA access */ nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir); @@ -2465,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, fis->opts = 1 << 7; fis->command = (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE); - *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF); - *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF); + fis->lba_low = start & 0xFF; + fis->lba_mid = (start >> 8) & 0xFF; + fis->lba_hi = (start >> 16) & 0xFF; + fis->lba_low_ex = (start >> 24) & 0xFF; + fis->lba_mid_ex = (start >> 32) & 0xFF; + fis->lba_hi_ex = (start >> 40) & 0xFF; fis->device = 1 << 6; fis->features = nsect & 0xFF; fis->features_ex = (nsect >> 8) & 0xFF; diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 5f4a917bd8bb..b1742640556a 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -34,7 +34,7 @@ #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET 0x48 /* check for erase mode support during secure erase */ -#define MTIP_SEC_ERASE_MODE 0x3 +#define MTIP_SEC_ERASE_MODE 0x2 /* # of times to retry timed out/failed IOs */ #define MTIP_MAX_RETRIES 2 @@ -155,14 +155,14 @@ enum { MTIP_DDF_REBUILD_FAILED_BIT = 8, }; -__packed struct smart_attr{ +struct smart_attr { u8 attr_id; u16 flags; u8 cur; u8 worst; u32 data; u8 res[3]; -}; +} __packed; /* Register Frame Information Structure (FIS), host to device. */ struct host_to_dev_fis { diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index fc2de5528dcc..b00000e8aef6 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, { USB_DEVICE(0x0489, 0xE03D) }, + { USB_DEVICE(0x0489, 0xE027) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index debda27df9b0..ee82f2fb65f0 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c index ff63560b8467..0c48b0e05ed6 100644 --- a/drivers/bus/omap-ocp2scp.c +++ b/drivers/bus/omap-ocp2scp.c @@ -22,6 +22,26 @@ #include <linux/pm_runtime.h> #include <linux/of.h> #include <linux/of_platform.h> +#include <linux/platform_data/omap_ocp2scp.h> + +/** + * _count_resources - count for the number of resources + * @res: struct resource * + * + * Count and return the number of resources populated for the device that is + * connected to ocp2scp. + */ +static unsigned _count_resources(struct resource *res) +{ + int cnt = 0; + + while (res->start != res->end) { + cnt++; + res++; + } + + return cnt; +} static int ocp2scp_remove_devices(struct device *dev, void *c) { @@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c) static int __devinit omap_ocp2scp_probe(struct platform_device *pdev) { - int ret; - struct device_node *np = pdev->dev.of_node; + int ret; + unsigned res_cnt, i; + struct device_node *np = pdev->dev.of_node; + struct platform_device *pdev_child; + struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data; + struct omap_ocp2scp_dev *dev; if (np) { ret = of_platform_populate(np, NULL, NULL, &pdev->dev); if (ret) { - dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n"); + dev_err(&pdev->dev, + "failed to add resources for ocp2scp child\n"); goto err0; } + } else if (pdata) { + for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++, + dev++) { + res_cnt = _count_resources(dev->res); + + pdev_child = platform_device_alloc(dev->drv_name, + PLATFORM_DEVID_AUTO); + if (!pdev_child) { + dev_err(&pdev->dev, + "failed to allocate mem for ocp2scp child\n"); + goto err0; + } + + ret = platform_device_add_resources(pdev_child, + dev->res, res_cnt); + if (ret) { + dev_err(&pdev->dev, + "failed to add resources for ocp2scp child\n"); + goto err1; + } + + pdev_child->dev.parent = &pdev->dev; + + ret = platform_device_add(pdev_child); + if (ret) { + dev_err(&pdev->dev, + "failed to register ocp2scp child device\n"); + goto err1; + } + } + } else { + dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n"); + return -EINVAL; } + pm_runtime_enable(&pdev->dev); return 0; +err1: + platform_device_put(pdev_child); + err0: device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices); diff --git a/drivers/clk/ux500/u8500_clk.c b/drivers/clk/ux500/u8500_clk.c index ca4a25ed844c..e2c17d187d98 100644 --- a/drivers/clk/ux500/u8500_clk.c +++ b/drivers/clk/ux500/u8500_clk.c @@ -40,7 +40,7 @@ void u8500_clk_init(void) CLK_IS_ROOT|CLK_IGNORE_UNUSED, 32768); clk_register_clkdev(clk, "clk32k", NULL); - clk_register_clkdev(clk, NULL, "rtc-pl031"); + clk_register_clkdev(clk, "apb_pclk", "rtc-pl031"); /* PRCMU clocks */ fw_version = prcmu_get_fw_version(); @@ -228,10 +228,17 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE, BIT(2), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1"); + clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE, BIT(3), 0); + clk_register_clkdev(clk, "apb_pclk", "msp0"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0"); + clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE, BIT(4), 0); + clk_register_clkdev(clk, "apb_pclk", "msp1"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1"); clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE, BIT(5), 0); @@ -239,6 +246,7 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE, BIT(6), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2"); clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE, BIT(7), 0); @@ -246,6 +254,7 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE, BIT(8), 0); + clk_register_clkdev(clk, "apb_pclk", "slimbus0"); clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE, BIT(9), 0); @@ -255,11 +264,16 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE, BIT(10), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4"); + clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE, BIT(11), 0); + clk_register_clkdev(clk, "apb_pclk", "msp3"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3"); clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE, BIT(0), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3"); clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE, BIT(1), 0); @@ -279,12 +293,13 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE, BIT(5), 0); + clk_register_clkdev(clk, "apb_pclk", "msp2"); + clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2"); clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE, BIT(6), 0); clk_register_clkdev(clk, "apb_pclk", "sdi1"); - clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE, BIT(7), 0); clk_register_clkdev(clk, "apb_pclk", "sdi3"); @@ -316,10 +331,15 @@ void u8500_clk_init(void) clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE, BIT(1), 0); + clk_register_clkdev(clk, "apb_pclk", "ssp0"); + clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE, BIT(2), 0); + clk_register_clkdev(clk, "apb_pclk", "ssp1"); + clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE, BIT(3), 0); + clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0"); clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE, BIT(4), 0); @@ -401,10 +421,17 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.1"); + clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk", U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp0"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0"); + clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk", U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp1"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1"); clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk", U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE); @@ -412,17 +439,25 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.2"); + clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk", - U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE); - /* FIXME: Redefinition of BIT(3). */ + U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "slimbus0"); + clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk", U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.4"); + clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk", U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp3"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3"); /* Periph2 */ clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk", U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.3"); clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk", U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE); @@ -430,6 +465,8 @@ void u8500_clk_init(void) clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk", U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "msp2"); + clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2"); clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk", U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE); @@ -450,10 +487,15 @@ void u8500_clk_init(void) /* Periph3 */ clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk", U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "ssp0"); + clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk", U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "ssp1"); + clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk", U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE); + clk_register_clkdev(clk, NULL, "nmk-i2c.0"); clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk", U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE); diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 8d4804732bac..8c4139647efc 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h @@ -33,7 +33,7 @@ * detection. The mods to Rev F required more family * information detection. * - * Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>: + * Changes/Fixes by Borislav Petkov <bp@alien8.de>: * - misc fixes and code cleanups * * This module is based on the following documents diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c index 6c86f6e54558..351945fa2ecd 100644 --- a/drivers/edac/edac_stub.c +++ b/drivers/edac/edac_stub.c @@ -5,7 +5,7 @@ * * 2007 (c) MontaVista Software, Inc. * 2010 (c) Advanced Micro Devices Inc. - * Borislav Petkov <borislav.petkov@amd.com> + * Borislav Petkov <bp@alien8.de> * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c index 66b5151c1080..2ae78f20cc28 100644 --- a/drivers/edac/mce_amd_inj.c +++ b/drivers/edac/mce_amd_inj.c @@ -6,7 +6,7 @@ * This file may be distributed under the terms of the GNU General Public * License version 2. * - * Copyright (c) 2010: Borislav Petkov <borislav.petkov@amd.com> + * Copyright (c) 2010: Borislav Petkov <bp@alien8.de> * Advanced Micro Devices Inc. */ @@ -168,6 +168,6 @@ module_init(edac_init_mce_inject); module_exit(edac_exit_mce_inject); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>"); +MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>"); MODULE_AUTHOR("AMD Inc."); MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding"); diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 1162d6b3bf85..bb1b392f5cda 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) struct sbp2_logical_unit *lu = sdev->hostdata; sdev->use_10_for_rw = 1; + sdev->no_report_opcodes = 1; + sdev->no_write_same = 1; if (sbp2_param_exclusive_login) sdev->manage_start_stop = 1; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index d055cee36942..47150f5ded04 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -47,7 +47,7 @@ if GPIOLIB config OF_GPIO def_bool y - depends on OF && !SPARC + depends on OF config DEBUG_GPIO bool "Debug GPIO calls" @@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ config GPIO_ADNP tristate "Avionic Design N-bit GPIO expander" - depends on I2C && OF + depends on I2C && OF_GPIO help This option enables support for N GPIOs found on Avionic Design I2C GPIO expanders. The register space will be extended by powers diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index 0f425189de11..ce1c84760076 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c @@ -77,7 +77,7 @@ struct mcp23s08_driver_data { /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg) { @@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, break; #endif /* CONFIG_SPI_MASTER */ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) case MCP_TYPE_008: mcp->ops = &mcp23008_ops; mcp->chip.ngpio = 8; @@ -473,7 +473,7 @@ fail: /*----------------------------------------------------------------------*/ -#ifdef CONFIG_I2C +#if IS_ENABLED(CONFIG_I2C) static int __devinit mcp230xx_probe(struct i2c_client *client, const struct i2c_device_id *id) diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index cf7afb9eb61a..be65c0451ad5 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) return mvchip->membase + GPIO_OUT_OFF; } +static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip) +{ + return mvchip->membase + GPIO_BLINK_EN_OFF; +} + static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) { return mvchip->membase + GPIO_IO_CONF_OFF; @@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) return (u >> pin) & 1; } +static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value) +{ + struct mvebu_gpio_chip *mvchip = + container_of(chip, struct mvebu_gpio_chip, chip); + unsigned long flags; + u32 u; + + spin_lock_irqsave(&mvchip->lock, flags); + u = readl_relaxed(mvebu_gpioreg_blink(mvchip)); + if (value) + u |= 1 << pin; + else + u &= ~(1 << pin); + writel_relaxed(u, mvebu_gpioreg_blink(mvchip)); + spin_unlock_irqrestore(&mvchip->lock, flags); +} + static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) { struct mvebu_gpio_chip *mvchip = @@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, if (ret) return ret; + mvebu_gpio_blink(chip, pin, 0); mvebu_gpio_set(chip, pin, value); spin_lock_irqsave(&mvchip->lock, flags); diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 7ef1b673e1be..133b4132983e 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp) int minor_id = iminor(inode); struct drm_minor *minor; int retcode = 0; + int need_setup = 0; + struct address_space *old_mapping; minor = idr_find(&drm_minors_idr, minor_id); if (!minor) @@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp) if (drm_device_is_unplugged(dev)) return -ENODEV; + if (!dev->open_count++) + need_setup = 1; + mutex_lock(&dev->struct_mutex); + old_mapping = dev->dev_mapping; + if (old_mapping == NULL) + dev->dev_mapping = &inode->i_data; + /* ihold ensures nobody can remove inode with our i_data */ + ihold(container_of(dev->dev_mapping, struct inode, i_data)); + inode->i_mapping = dev->dev_mapping; + filp->f_mapping = dev->dev_mapping; + mutex_unlock(&dev->struct_mutex); + retcode = drm_open_helper(inode, filp, dev); - if (!retcode) { - atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) - retcode = drm_setup(dev); - } - if (!retcode) { - mutex_lock(&dev->struct_mutex); - if (dev->dev_mapping == NULL) - dev->dev_mapping = &inode->i_data; - /* ihold ensures nobody can remove inode with our i_data */ - ihold(container_of(dev->dev_mapping, struct inode, i_data)); - inode->i_mapping = dev->dev_mapping; - filp->f_mapping = dev->dev_mapping; - mutex_unlock(&dev->struct_mutex); + if (retcode) + goto err_undo; + atomic_inc(&dev->counts[_DRM_STAT_OPENS]); + if (need_setup) { + retcode = drm_setup(dev); + if (retcode) + goto err_undo; } + return 0; +err_undo: + mutex_lock(&dev->struct_mutex); + filp->f_mapping = old_mapping; + inode->i_mapping = old_mapping; + iput(container_of(dev->dev_mapping, struct inode, i_data)); + dev->dev_mapping = old_mapping; + mutex_unlock(&dev->struct_mutex); + dev->open_count--; return retcode; } EXPORT_SYMBOL(drm_open); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index b726b478a4f5..6345878ae1e7 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) int old_dpms; /* PCH platforms and VLV only support on/off. */ - if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON) + if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 461a637f1ef7..4154bcd7a070 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3841,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (intel_encoder->type == INTEL_OUTPUT_EDP) { + /* Use VBT settings if we have an eDP panel */ + unsigned int edp_bpc = dev_priv->edp.bpp / 3; + + if (edp_bpc < display_bpc) { + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + display_bpc = edp_bpc; + } + continue; + } + /* * HDMI is either 12 or 8, so if the display lets 10bpc sneak * through, clamp it down. (Note: >12bpc will be caught below.) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 79d308da29ff..c600fb06e25e 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -2382,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) return true; } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ + struct drm_device *dev = intel_sdvo->base.base.dev; + struct drm_connector *connector, *tmp; + + list_for_each_entry_safe(connector, tmp, + &dev->mode_config.connector_list, head) { + if (intel_attached_encoder(connector) == &intel_sdvo->base) + intel_sdvo_destroy(connector); + } +} + static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, int type) @@ -2705,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", SDVO_NAME(intel_sdvo)); - goto err; + /* Output_setup can leave behind connectors! */ + goto err_output; } /* Only enable the hotplug irq if we need it, to work around noisy @@ -2718,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) - goto err; + goto err_output; if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, &intel_sdvo->pixel_clock_min, &intel_sdvo->pixel_clock_max)) - goto err; + goto err_output; DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " "clock range %dMHz - %dMHz, " @@ -2743,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); return true; +err_output: + intel_sdvo_output_cleanup(intel_sdvo); + err: drm_encoder_cleanup(&intel_encoder->base); i2c_del_adapter(&intel_sdvo->ddc); diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 16a9afb1060b..15b182c84ce8 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -22,6 +22,8 @@ * Authors: Ben Skeggs */ +#include <subdev/bar.h> + #include <engine/software.h> #include <engine/disp.h> @@ -37,6 +39,7 @@ nv50_disp_sclass[] = { static void nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) { + struct nouveau_bar *bar = nouveau_bar(priv); struct nouveau_disp *disp = &priv->base; struct nouveau_software_chan *chan, *temp; unsigned long flags; @@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) if (chan->vblank.crtc != crtc) continue; - nv_wr32(priv, 0x001704, chan->vblank.channel); - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); - - if (nv_device(priv)->chipset == 0x50) { - nv_wr32(priv, 0x001570, chan->vblank.offset); - nv_wr32(priv, 0x001574, chan->vblank.value); + if (nv_device(priv)->chipset >= 0xc0) { + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, + upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, + lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); } else { - if (nv_device(priv)->chipset >= 0xc0) { - nv_wr32(priv, 0x06000c, - upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + bar->flush(bar); + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); } - nv_wr32(priv, 0x060010, chan->vblank.offset); - nv_wr32(priv, 0x060014, chan->vblank.value); } list_del(&chan->vblank.head); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c index e45035efb8ca..7bbb1e1b7a8d 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c @@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem) }); } -void +int nv40_grctx_init(struct nouveau_device *device, u32 *size) { - u32 ctxprog[256], i; + u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i; struct nouveau_grctx ctx = { .device = device, .mode = NOUVEAU_GRCTX_PROG, .data = ctxprog, - .ctxprog_max = ARRAY_SIZE(ctxprog) + .ctxprog_max = 256, }; + if (!ctxprog) + return -ENOMEM; + nv40_grctx_generate(&ctx); nv_wr32(device, 0x400324, 0); for (i = 0; i < ctx.ctxprog_len; i++) nv_wr32(device, 0x400328, ctxprog[i]); *size = ctx.ctxvals_pos * 4; + + kfree(ctxprog); + return 0; } diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 8d0021049ec0..cc6574eeb80e 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent, static int nv40_graph_context_fini(struct nouveau_object *object, bool suspend) { - struct nv04_graph_priv *priv = (void *)object->engine; - struct nv04_graph_chan *chan = (void *)object; + struct nv40_graph_priv *priv = (void *)object->engine; + struct nv40_graph_chan *chan = (void *)object; u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4; int ret = 0; @@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object) return ret; /* generate and upload context program */ - nv40_grctx_init(nv_device(priv), &priv->size); + ret = nv40_grctx_init(nv_device(priv), &priv->size); + if (ret) + return ret; /* No context present currently */ nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index d2ac975afc2e..7da35a4e7970 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h @@ -15,7 +15,7 @@ nv44_graph_class(void *priv) return !(0x0baf & (1 << (device->chipset & 0x0f))); } -void nv40_grctx_init(struct nouveau_device *, u32 *size); +int nv40_grctx_init(struct nouveau_device *, u32 *size); void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *); #endif diff --git a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c index 12418574efea..f7c581ad1991 100644 --- a/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c +++ b/drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c @@ -38,7 +38,7 @@ struct nv40_mpeg_priv { }; struct nv40_mpeg_chan { - struct nouveau_mpeg base; + struct nouveau_mpeg_chan base; }; /******************************************************************************* diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h index 818feabbf4a0..486f1a9217fd 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data) return temp; } -static inline bool -nv_strncmp(void *obj, u32 addr, u32 len, const char *str) +static inline int +nv_memcmp(void *obj, u32 addr, const char *str, u32 len) { + unsigned char c1, c2; + while (len--) { - if (nv_ro08(obj, addr++) != *(str++)) - return false; + c1 = nv_ro08(obj, addr++); + c2 = *(str++); + if (c1 != c2) + return c1 - c2; } - return true; + return 0; } #endif diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h index 39e73b91d360..41b7a6a76f19 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/clock.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/clock.h @@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, int clk, struct nouveau_pll_vals *); int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1, struct nouveau_pll_vals *); - +int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *, + int clk, struct nouveau_pll_vals *); #endif diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 7d750382a833..c51197157749 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) } } else if (*ver >= 0x15) { - if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) { + if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) { u16 i2c = nv_ro16(bios, dcb + 2); *hdr = 4; *cnt = (i2c - dcb) / 10; diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c index cc8d7d162d7c..9068c98b96f6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c @@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) return ret; } +int +nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info, + int clk, struct nouveau_pll_vals *pv) +{ + int ret, N, M, P; + + ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P); + + if (ret > 0) { + pv->refclk = info->refclk; + pv->N1 = N; + pv->M1 = M; + pv->log2P = P; + } + return ret; +} + + static int nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nva3_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index 5ccce0b17bf3..f6962c9b6c36 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c @@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine, return ret; priv->base.pll_set = nvc0_clock_pll_set; + priv->base.pll_calc = nva3_clock_pll_calc; return 0; } diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c index 49050d991e75..9474cfca6e4c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c @@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt) static void nv41_vm_flush(struct nouveau_vm *vm) { - struct nv04_vm_priv *priv = (void *)vm->vmm; + struct nv04_vmmgr_priv *priv = (void *)vm->vmm; mutex_lock(&nv_subdev(priv)->mutex); nv_wr32(priv, 0x100810, 0x00000022); diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index cc79c796afee..cbf1fc60a386 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (unlikely(!abi16)) return -ENOMEM; + + if (!drm->channel) + return nouveau_abi16_put(abi16, -ENODEV); + client = nv_client(abi16->client); if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 9a6e2cb282dc..d3595b23434a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * valid - it's not (rh#613284) */ if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) { + if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { status = connector_status_connected; goto out; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 0910125cbbc3..8503b2ea570a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -129,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm) /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); - else if (device->chipset < 0x84) ret = nv10_fence_create(drm); + else if (device->card_type < NV_50) ret = nv10_fence_create(drm); + else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); if (ret) { diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 2e566e123e9e..3bce0299f64a 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1696,35 +1696,43 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) return ATOM_PPLL2; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; - } else { - if (ASIC_IS_AVIVO(rdev)) { - /* in DP mode, the DP ref clock can come from either PPLL - * depending on the asic: - * DCE3: PPLL1 or PPLL2 - */ - if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { - /* use the same PPLL for all DP monitors */ - pll = radeon_get_shared_dp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; - } else { - /* use the same PPLL for all monitors with the same clock */ - pll = radeon_get_shared_nondp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; - } - /* all other cases */ - pll_in_use = radeon_get_pll_use_mask(crtc); + } else if (ASIC_IS_AVIVO(rdev)) { + /* in DP mode, the DP ref clock can come from either PPLL + * depending on the asic: + * DCE3: PPLL1 or PPLL2 + */ + if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { + /* use the same PPLL for all DP monitors */ + pll = radeon_get_shared_dp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } else { + /* use the same PPLL for all monitors with the same clock */ + pll = radeon_get_shared_nondp_ppll(crtc); + if (pll != ATOM_PPLL_INVALID) + return pll; + } + /* all other cases */ + pll_in_use = radeon_get_pll_use_mask(crtc); + /* the order shouldn't matter here, but we probably + * need this until we have atomic modeset + */ + if (rdev->flags & RADEON_IS_IGP) { if (!(pll_in_use & (1 << ATOM_PPLL1))) return ATOM_PPLL1; if (!(pll_in_use & (1 << ATOM_PPLL2))) return ATOM_PPLL2; - DRM_ERROR("unable to allocate a PPLL\n"); - return ATOM_PPLL_INVALID; } else { - /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ - return radeon_crtc->crtc_id; + if (!(pll_in_use & (1 << ATOM_PPLL2))) + return ATOM_PPLL2; + if (!(pll_in_use & (1 << ATOM_PPLL1))) + return ATOM_PPLL1; } + DRM_ERROR("unable to allocate a PPLL\n"); + return ATOM_PPLL_INVALID; + } else { + /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ + return radeon_crtc->crtc_id; } } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index ba498f8e47a2..010bae19554a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1625,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 14313ad43b76..219942c660d7 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + } else { + save->crtc_enabled[i] = false; } } @@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); for (i = 0; i < rdev->num_crtc; i++) { - if (save->crtc_enabled) { + if (save->crtc_enabled[i]) { if (ASIC_IS_DCE6(rdev)) { tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 95e6318b6268..c042e497e450 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index df542f1a5dfb..2bc0f6a1b428 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -91,6 +91,10 @@ #define FB_READ_EN (1 << 0) #define FB_WRITE_EN (1 << 1) +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 #define CP_COHER_BASE 0x85F8 #define CP_STALLED_STAT1 0x8674 #define CP_STALLED_STAT2 0x8678 diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 10ea17a6b2a6..42433344cb1b 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index b0db712060fb..4422d630b33b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2474,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_ESGS_RING_SIZE: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 7d2a20e56577..a8871afc5b4e 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -424,6 +424,7 @@ # define RDERR_INT_ENABLE (1 << 0) # define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_STRMOUT_CNTL 0x84FC #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 860dc4813e99..bd2a3b40cd12 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, /* clear the pages coming from the pool if requested */ if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { list_for_each_entry(p, &plist, lru) { - clear_page(page_address(p)); + if (PageHighMem(p)) + clear_highpage(p); + else + clear_page(page_address(p)); } } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index bf8260133ea9..7d759a430294 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm) if (unlikely(to_page == NULL)) goto out_err; - preempt_disable(); copy_highpage(to_page, from_page); - preempt_enable(); page_cache_release(from_page); } @@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) ret = PTR_ERR(to_page); goto out_err; } - preempt_disable(); copy_highpage(to_page, from_page); - preempt_enable(); set_page_dirty(to_page); mark_page_accessed(to_page); page_cache_release(to_page); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3ce68a2e312d..d1498bfd7873 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); + old_mem_type != VMW_PL_GMR); pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; if (pin) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ed3c1e7ddde9..2dd185e42f21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev) struct drm_device *dev = pci_get_drvdata(pdev); struct vmw_private *dev_priv = vmw_priv(dev); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); + (void) vmw_read(dev_priv, SVGA_REG_ID); + mutex_unlock(&dev_priv->hw_mutex); + /** * Reclaim 3d reference held by fbdev and potentially * start fifo. diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index b07ca2e4d04b..7290811f89be 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); ret = copy_to_user(buffer, bounce, size); + if (ret) + ret = -EFAULT; vfree(bounce); if (unlikely(ret != 0)) diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index f676c01bb471..6fcd466d0825 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -46,9 +46,9 @@ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[559] = 0x45; } /* the same as above (s/usage/physical/) */ - if ((quirks & MS_RDESC_3K) && *rsize == 106 && - !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, - &rdesc[94], 4)) { + if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 && + rdesc[95] == 0x00 && rdesc[96] == 0x29 && + rdesc[97] == 0xff) { rdesc[94] = 0x35; rdesc[96] = 0x45; } diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 17d15bb610d1..7c47fc3f7b2b 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -42,7 +42,6 @@ static struct cdev hidraw_cdev; static struct class *hidraw_class; static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DEFINE_MUTEX(minors_lock); -static void drop_ref(struct hidraw *hid, int exists_bit); static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, __u8 *buf; int ret = 0; - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { ret = -ENODEV; goto out; } @@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file) } mutex_lock(&minors_lock); - if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { + if (!hidraw_table[minor]) { err = -ENODEV; goto out_unlock; } @@ -299,12 +298,36 @@ out: static int hidraw_release(struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); + struct hidraw *dev; struct hidraw_list *list = file->private_data; + int ret; + int i; + + mutex_lock(&minors_lock); + if (!hidraw_table[minor]) { + ret = -ENODEV; + goto unlock; + } - drop_ref(hidraw_table[minor], 0); list_del(&list->node); + dev = hidraw_table[minor]; + if (!--dev->open) { + if (list->hidraw->exist) { + hid_hw_power(dev->hid, PM_HINT_NORMAL); + hid_hw_close(dev->hid); + } else { + kfree(list->hidraw); + } + } + + for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i) + kfree(list->buffer[i].value); kfree(list); - return 0; + ret = 0; +unlock: + mutex_unlock(&minors_lock); + + return ret; } static long hidraw_ioctl(struct file *file, unsigned int cmd, @@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect); void hidraw_disconnect(struct hid_device *hid) { struct hidraw *hidraw = hid->hidraw; - drop_ref(hidraw, 1); + + mutex_lock(&minors_lock); + hidraw->exist = 0; + + device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); + + hidraw_table[hidraw->minor] = NULL; + + if (hidraw->open) { + hid_hw_close(hid); + wake_up_interruptible(&hidraw->wait); + } else { + kfree(hidraw); + } + mutex_unlock(&minors_lock); } EXPORT_SYMBOL_GPL(hidraw_disconnect); @@ -555,23 +592,3 @@ void hidraw_exit(void) unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES); } - -static void drop_ref(struct hidraw *hidraw, int exists_bit) -{ - mutex_lock(&minors_lock); - if (exists_bit) { - hid_hw_close(hidraw->hid); - hidraw->exist = 0; - if (hidraw->open) - wake_up_interruptible(&hidraw->wait); - } else { - --hidraw->open; - } - - if (!hidraw->open && !hidraw->exist) { - device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor)); - hidraw_table[hidraw->minor] = NULL; - kfree(hidraw); - } - mutex_unlock(&minors_lock); -} diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index a227be47149f..520e5bf4f76d 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -32,7 +32,7 @@ * ASB100-A supports pwm1, while plain ASB100 does not. There is no known * way for the driver to tell which one is there. * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * asb100 7 3 1 4 0x31 0x0694 yes no */ diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 1821b7423d5b..de3c7e04c3b5 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index 5b1a6a666441..af1589908709 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -25,7 +25,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) * w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) * w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 5a5046d94c3e..20f11d31da40 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -24,7 +24,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * as99127f 7 3 0 3 0x31 0x12c3 yes no * as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no * w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 39ab7bcc616e..ed397c645198 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -22,7 +22,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83791d 10 5 5 3 0x71 0x5ca3 yes no * * The w83791d chip appears to be part way between the 83781d and the diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 053645279f38..301942d08453 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -31,7 +31,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83792d 9 7 7 3 0x7a 0x5ca3 yes no */ diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index f0e8286c3c70..79710bcac2f7 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -20,7 +20,7 @@ /* * Supports following chips: * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA + * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no */ diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index aa59a254be2c..c02bf208084f 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -39,6 +39,7 @@ #define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ #define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ #define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */ #define AT91_TWI_SWRST 0x0080 /* Software Reset */ #define AT91_TWI_MMR 0x0004 /* Master Mode Register */ @@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev) INIT_COMPLETION(dev->cmd_complete); dev->transfer_status = 0; - if (dev->msg->flags & I2C_M_RD) { + + if (!dev->buf_len) { + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else if (dev->msg->flags & I2C_M_RD) { unsigned start_flags = AT91_TWI_START; if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 286ca1917820..0670da79ee5e 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -287,12 +287,14 @@ read_init_dma_fail: select_init_dma_fail: dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE); select_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; /* Write failpath. */ write_init_dma_fail: dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE); write_init_pio_fail: + dmaengine_terminate_all(i2c->dmach); return -EINVAL; } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index db31eaed6ea5..3525c9e62cb0 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,7 +43,6 @@ #include <linux/slab.h> #include <linux/i2c-omap.h> #include <linux/pm_runtime.h> -#include <linux/pm_qos.h> /* I2C controller revisions */ #define OMAP_I2C_OMAP1_REV_2 0x20 @@ -187,8 +186,9 @@ struct omap_i2c_dev { int reg_shift; /* bit shift for I2C register addresses */ struct completion cmd_complete; struct resource *ioarea; - u32 latency; /* maximum MPU wkup latency */ - struct pm_qos_request pm_qos_request; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + long latency); u32 speed; /* Speed of bus in kHz */ u32 dtrev; /* extra revision from DT */ u32 flags; @@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->threshold) / + (1000 * dev->speed / 8); } /* @@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, dev->buf = msg->buf; dev->buf_len = msg->len; + /* make sure writes to dev->buf_len are ordered */ + barrier(); + omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); /* Clear the FIFO Buffers */ @@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, */ timeout = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); - dev->buf_len = 0; if (timeout == 0) { dev_err(dev->dev, "controller timed out\n"); omap_i2c_init(dev); @@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) if (r < 0) goto out; - /* - * When waiting for completion of a i2c transfer, we need to - * set a wake up latency constraint for the MPU. This is to - * ensure quick enough wakeup from idle, when transfer - * completes. - */ - if (dev->latency) - pm_qos_add_request(&dev->pm_qos_request, - PM_QOS_CPU_DMA_LATENCY, - dev->latency); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, dev->latency); for (i = 0; i < num; i++) { r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); @@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) break; } - if (dev->latency) - pm_qos_remove_request(&dev->pm_qos_request); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, -1); if (r == 0) r = num; @@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev) } else if (pdata != NULL) { dev->speed = pdata->clkrate; dev->flags = pdata->flags; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; dev->dtrev = pdata->rev; } @@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev) dev->b_hw = 1; /* Enable hardware fixes */ /* calculate wakeup latency constraint for MPU */ - dev->latency = (1000000 * dev->fifo_size) / - (1000 * dev->speed / 8); + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * dev->speed / 8); } /* reset ASAP, clearing any IRQs */ diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3e0335f1fc60..9d902725bac9 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); goto free_gpio; } + i2c->gpios[idx] = gpio; ret = gpio_request(gpio, "i2c-bus"); if (ret) { diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 5f097f309b9f..7fa5b24b16db 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c @@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev) mux->busses = devm_kzalloc(&pdev->dev, sizeof(mux->busses) * mux->pdata->bus_count, GFP_KERNEL); - if (!mux->states) { + if (!mux->busses) { dev_err(&pdev->dev, "Cannot allocate busses\n"); ret = -ENOMEM; goto err; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index c0ec7d42c3be..1abbc170d8b7 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src) * input_mt_init_slots() - initialize MT input slots * @dev: input device supporting MT events and finger tracking * @num_slots: number of slots used by the device + * @flags: mt tasks to handle in core * * This function allocates all necessary memory for MT slot handling * in the input device, prepares the ABS_MT_SLOT and * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers. + * Depending on the flags set, it also performs pointer emulation and + * frame synchronization. + * * May be called repeatedly. Returns -EINVAL if attempting to * reinitialize with a different number of slots. */ diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 8f02e3d0e712..4c842c320c2e 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -12,8 +12,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define MOUSEDEV_MINOR_BASE 32 -#define MOUSEDEV_MINORS 32 -#define MOUSEDEV_MIX 31 +#define MOUSEDEV_MINORS 31 +#define MOUSEDEV_MIX 63 #include <linux/sched.h> #include <linux/slab.h> diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index f02028ec3db6..78e5d9ab0ba7 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume); -static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts) +static int __devinit ads7846_setup_pendown(struct spi_device *spi, + struct ads7846 *ts) { struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; @@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 ts->gpio_pendown = pdata->gpio_pendown; + if (pdata->gpio_pendown_debounce) + gpio_set_debounce(pdata->gpio_pendown, + pdata->gpio_pendown_debounce); } else { dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); return -EINVAL; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index d4a4cd445cab..0badfa48b32b 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to) static int intel_iommu_add_device(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - struct pci_dev *bridge, *dma_pdev; + struct pci_dev *bridge, *dma_pdev = NULL; struct iommu_group *group; int ret; @@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev) dma_pdev = pci_get_domain_bus_and_slot( pci_domain_nr(pdev->bus), bridge->subordinate->number, 0); - else + if (!dma_pdev) dma_pdev = pci_dev_get(bridge); } else dma_pdev = pci_dev_get(pdev); diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index a649f146d17b..c0f7a4266263 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v) stats[i], val, offs); } seq_printf(s, "\n"); + dput(dent); return 0; } diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c index dc670ccc6978..16c78f1c5ef2 100644 --- a/drivers/irqchip/irq-bcm2835.c +++ b/drivers/irqchip/irq-bcm2835.c @@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node, } static struct of_device_id irq_of_match[] __initconst = { - { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init } + { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }, + { } }; void __init bcm2835_init_irq(void) diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig index a233ed53913a..86cd75a0e84d 100644 --- a/drivers/isdn/Kconfig +++ b/drivers/isdn/Kconfig @@ -4,7 +4,7 @@ menuconfig ISDN bool "ISDN support" - depends on NET + depends on NET && NETDEVICES depends on !S390 && !UML ---help--- ISDN ("Integrated Services Digital Network", called RNIS in France) diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig index 2302fbe70ac6..9c6650ea848e 100644 --- a/drivers/isdn/i4l/Kconfig +++ b/drivers/isdn/i4l/Kconfig @@ -6,7 +6,7 @@ if ISDN_I4L config ISDN_PPP bool "Support synchronous PPP" - depends on INET && NETDEVICES + depends on INET select SLHC help Over digital connections such as ISDN, there is no need to diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8c610fa6782b..e2a945ee9f05 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) } else return -EINVAL; break; -#ifdef CONFIG_NETDEVICES case IIOCNETGPN: /* Get peer phone number of a connected * isdn network interface */ @@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) return isdn_net_getpeer(&phone, argp); } else return -EINVAL; -#endif default: return -EINVAL; } @@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) case IIOCNETLCR: printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); return -ENODEV; -#ifdef CONFIG_NETDEVICES case IIOCNETAIF: /* Add a network-interface */ if (arg) { @@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) return -EFAULT; return isdn_net_force_hangup(name); break; -#endif /* CONFIG_NETDEVICES */ case IIOCSETVER: dev->net_verbose = arg; printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); diff --git a/drivers/leds/ledtrig-cpu.c b/drivers/leds/ledtrig-cpu.c index b312056da14d..4239b3955ff0 100644 --- a/drivers/leds/ledtrig-cpu.c +++ b/drivers/leds/ledtrig-cpu.c @@ -33,8 +33,6 @@ struct led_trigger_cpu { char name[MAX_NAME_LEN]; struct led_trigger *_trig; - struct mutex lock; - int lock_is_inited; }; static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig); @@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt) { struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig); - /* mutex lock should be initialized before calling mutex_call() */ - if (!trig->lock_is_inited) - return; - - mutex_lock(&trig->lock); - /* Locate the correct CPU LED */ switch (ledevt) { case CPU_LED_IDLE_END: @@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt) /* Will leave the LED as it is */ break; } - - mutex_unlock(&trig->lock); } EXPORT_SYMBOL(ledtrig_cpu); @@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void) for_each_possible_cpu(cpu) { struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); - mutex_init(&trig->lock); - snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu); - mutex_lock(&trig->lock); led_trigger_register_simple(trig->name, &trig->_trig); - trig->lock_is_inited = 1; - mutex_unlock(&trig->lock); } register_syscore_ops(&ledtrig_cpu_syscore_ops); @@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void) for_each_possible_cpu(cpu) { struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu); - mutex_lock(&trig->lock); - led_trigger_unregister_simple(trig->_trig); trig->_trig = NULL; memset(trig->name, 0, MAX_NAME_LEN); - trig->lock_is_inited = 0; - - mutex_unlock(&trig->lock); - mutex_destroy(&trig->lock); } unregister_syscore_ops(&ledtrig_cpu_syscore_ops); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 02db9183ca01..77e6eff41cae 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue) if (!md_in_flight(md)) wake_up(&md->wait); + /* + * Run this off this callpath, as drivers could invoke end_io while + * inside their request_fn (and holding the queue lock). Calling + * back into ->request_fn() could deadlock attempting to grab the + * queue lock again. + */ if (run_queue) - blk_run_queue(md->queue); + blk_run_queue_async(md->queue); /* * dm_put() must be at the end of this function. See the comment above diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ab768acfb62..61200717687b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1817,10 +1817,10 @@ retry: memset(bbp, 0xff, PAGE_SIZE); for (i = 0 ; i < bb->count ; i++) { - u64 internal_bb = *p++; + u64 internal_bb = p[i]; u64 store_bb = ((BB_OFFSET(internal_bb) << 10) | BB_LEN(internal_bb)); - *bbp++ = cpu_to_le64(store_bb); + bbp[i] = cpu_to_le64(store_bb); } bb->changed = 0; if (read_seqretry(&bb->lock, seq)) @@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev) } EXPORT_SYMBOL_GPL(md_stop_writes); -void md_stop(struct mddev *mddev) +static void __md_stop(struct mddev *mddev) { mddev->ready = 0; mddev->pers->stop(mddev); @@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev) mddev->pers = NULL; clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery); } + +void md_stop(struct mddev *mddev) +{ + /* stop the array and free an attached data structures. + * This is called from dm-raid + */ + __md_stop(mddev); + bitmap_destroy(mddev); + if (mddev->bio_set) + bioset_free(mddev->bio_set); +} + EXPORT_SYMBOL_GPL(md_stop); static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) @@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode, set_disk_ro(disk, 0); __md_stop_writes(mddev); - md_stop(mddev); + __md_stop(mddev); mddev->queue->merge_bvec_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; @@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors) { int hi; - int lo = 0; + int lo; u64 *p = bb->page; - int rv = 0; + int rv; sector_t target = s + sectors; unsigned seq; @@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, retry: seq = read_seqbegin(&bb->lock); - + lo = 0; + rv = 0; hi = bb->count; /* Binary search between lo and hi for 'target' diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index d1295aff4173..0d5d0ff2c0f7 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error) */ one_write_done(r10_bio); if (dec_rdev) - rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev); + rdev_dec_pending(rdev, conf->mddev); } /* @@ -1334,18 +1334,21 @@ retry_write: blocked_rdev = rrdev; break; } + if (rdev && (test_bit(Faulty, &rdev->flags) + || test_bit(Unmerged, &rdev->flags))) + rdev = NULL; if (rrdev && (test_bit(Faulty, &rrdev->flags) || test_bit(Unmerged, &rrdev->flags))) rrdev = NULL; r10_bio->devs[i].bio = NULL; r10_bio->devs[i].repl_bio = NULL; - if (!rdev || test_bit(Faulty, &rdev->flags) || - test_bit(Unmerged, &rdev->flags)) { + + if (!rdev && !rrdev) { set_bit(R10BIO_Degraded, &r10_bio->state); continue; } - if (test_bit(WriteErrorSeen, &rdev->flags)) { + if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; sector_t dev_sector = r10_bio->devs[i].addr; int bad_sectors; @@ -1387,8 +1390,10 @@ retry_write: max_sectors = good_sectors; } } - r10_bio->devs[i].bio = bio; - atomic_inc(&rdev->nr_pending); + if (rdev) { + r10_bio->devs[i].bio = bio; + atomic_inc(&rdev->nr_pending); + } if (rrdev) { r10_bio->devs[i].repl_bio = bio; atomic_inc(&rrdev->nr_pending); @@ -1444,69 +1449,71 @@ retry_write: for (i = 0; i < conf->copies; i++) { struct bio *mbio; int d = r10_bio->devs[i].devnum; - if (!r10_bio->devs[i].bio) - continue; + if (r10_bio->devs[i].bio) { + struct md_rdev *rdev = conf->mirrors[d].rdev; + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr+ + choose_data_offset(r10_bio, + rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].bio = mbio; + atomic_inc(&r10_bio->remaining); - mbio->bi_sector = (r10_bio->devs[i].addr+ - choose_data_offset(r10_bio, - conf->mirrors[d].rdev)); - mbio->bi_bdev = conf->mirrors[d].rdev->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; + cb = blk_check_plugged(raid10_unplug, mddev, + sizeof(*plug)); + if (cb) + plug = container_of(cb, struct raid10_plug_cb, + cb); + else + plug = NULL; + spin_lock_irqsave(&conf->device_lock, flags); + if (plug) { + bio_list_add(&plug->pending, mbio); + plug->pending_cnt++; + } else { + bio_list_add(&conf->pending_bio_list, mbio); + conf->pending_count++; + } + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!plug) + md_wakeup_thread(mddev->thread); + } - atomic_inc(&r10_bio->remaining); + if (r10_bio->devs[i].repl_bio) { + struct md_rdev *rdev = conf->mirrors[d].replacement; + if (rdev == NULL) { + /* Replacement just got moved to main 'rdev' */ + smp_mb(); + rdev = conf->mirrors[d].rdev; + } + mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); + md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, + max_sectors); + r10_bio->devs[i].repl_bio = mbio; + + mbio->bi_sector = (r10_bio->devs[i].addr + + choose_data_offset( + r10_bio, rdev)); + mbio->bi_bdev = rdev->bdev; + mbio->bi_end_io = raid10_end_write_request; + mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; + mbio->bi_private = r10_bio; - cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug)); - if (cb) - plug = container_of(cb, struct raid10_plug_cb, cb); - else - plug = NULL; - spin_lock_irqsave(&conf->device_lock, flags); - if (plug) { - bio_list_add(&plug->pending, mbio); - plug->pending_cnt++; - } else { + atomic_inc(&r10_bio->remaining); + spin_lock_irqsave(&conf->device_lock, flags); bio_list_add(&conf->pending_bio_list, mbio); conf->pending_count++; + spin_unlock_irqrestore(&conf->device_lock, flags); + if (!mddev_check_plugged(mddev)) + md_wakeup_thread(mddev->thread); } - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!plug) - md_wakeup_thread(mddev->thread); - - if (!r10_bio->devs[i].repl_bio) - continue; - - mbio = bio_clone_mddev(bio, GFP_NOIO, mddev); - md_trim_bio(mbio, r10_bio->sector - bio->bi_sector, - max_sectors); - r10_bio->devs[i].repl_bio = mbio; - - /* We are actively writing to the original device - * so it cannot disappear, so the replacement cannot - * become NULL here - */ - mbio->bi_sector = (r10_bio->devs[i].addr + - choose_data_offset( - r10_bio, - conf->mirrors[d].replacement)); - mbio->bi_bdev = conf->mirrors[d].replacement->bdev; - mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; - mbio->bi_private = r10_bio; - - atomic_inc(&r10_bio->remaining); - spin_lock_irqsave(&conf->device_lock, flags); - bio_list_add(&conf->pending_bio_list, mbio); - conf->pending_count++; - spin_unlock_irqrestore(&conf->device_lock, flags); - if (!mddev_check_plugged(mddev)) - md_wakeup_thread(mddev->thread); } /* Don't remove the bias on 'remaining' (one_write_done) until diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c5439dce0295..a4502686e7a8 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf, dev = &sh->dev[i]; if (!test_bit(R5_LOCKED, &dev->flags) && (test_bit(R5_UPTODATE, &dev->flags) || - test_and_clear_bit(R5_Discard, &dev->flags))) { + test_bit(R5_Discard, &dev->flags))) { /* We can return any write requests */ struct bio *wbi, *wbi2; pr_debug("Return write for disc %d\n", i); + if (test_and_clear_bit(R5_Discard, &dev->flags)) + clear_bit(R5_UPTODATE, &dev->flags); wbi = dev->written; dev->written = NULL; while (wbi && wbi->bi_sector < @@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf, !test_bit(STRIPE_DEGRADED, &sh->state), 0); } - } + } else if (test_bit(R5_Discard, &sh->dev[i].flags)) + clear_bit(R5_Discard, &sh->dev[i].flags); if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) if (atomic_dec_and_test(&conf->pending_full_writes)) @@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh) handle_failed_sync(conf, sh, &s); } - /* - * might be able to return some write requests if the parity blocks - * are safe, or on a failed drive - */ - pdev = &sh->dev[sh->pd_idx]; - s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); - qdev = &sh->dev[sh->qd_idx]; - s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) - || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) - || conf->level < 6; - - if (s.written && - (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) - && !test_bit(R5_LOCKED, &pdev->flags) - && (test_bit(R5_UPTODATE, &pdev->flags) || - test_bit(R5_Discard, &pdev->flags))))) && - (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) - && !test_bit(R5_LOCKED, &qdev->flags) - && (test_bit(R5_UPTODATE, &qdev->flags) || - test_bit(R5_Discard, &qdev->flags)))))) - handle_stripe_clean_event(conf, sh, disks, &s.return_bi); - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (s.to_read || s.non_overwrite - || (conf->level == 6 && s.to_write && s.failed) - || (s.syncing && (s.uptodate + s.compute < disks)) - || s.replacing - || s.expanding) - handle_stripe_fill(sh, &s, disks); - /* Now we check to see if any write operations have recently * completed */ @@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh) s.dec_preread_active = 1; } + /* + * might be able to return some write requests if the parity blocks + * are safe, or on a failed drive + */ + pdev = &sh->dev[sh->pd_idx]; + s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); + qdev = &sh->dev[sh->qd_idx]; + s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) + || conf->level < 6; + + if (s.written && + (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) + && !test_bit(R5_LOCKED, &pdev->flags) + && (test_bit(R5_UPTODATE, &pdev->flags) || + test_bit(R5_Discard, &pdev->flags))))) && + (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) + && !test_bit(R5_LOCKED, &qdev->flags) + && (test_bit(R5_UPTODATE, &qdev->flags) || + test_bit(R5_Discard, &qdev->flags)))))) + handle_stripe_clean_event(conf, sh, disks, &s.return_bi); + + /* Now we might consider reading some blocks, either to check/generate + * parity, or to satisfy requests + * or to load a block that is being partially written. + */ + if (s.to_read || s.non_overwrite + || (conf->level == 6 && s.to_write && s.failed) + || (s.syncing && (s.uptodate + s.compute < disks)) + || s.replacing + || s.expanding) + handle_stripe_fill(sh, &s, disks); + /* Now to consider new write requests and what else, if anything * should be read. We do not handle new writes when: * 1/ A 'write' operation (copy+xor) is already in flight. @@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev) * discard data disk but write parity disk */ stripe = stripe * PAGE_SIZE; + /* Round up to power of 2, as discard handling + * currently assumes that */ + while ((stripe-1) & stripe) + stripe = (stripe | (stripe-1)) + 1; mddev->queue->limits.discard_alignment = stripe; mddev->queue->limits.discard_granularity = stripe; /* diff --git a/drivers/media/dvb-frontends/stv0900_core.c b/drivers/media/dvb-frontends/stv0900_core.c index 262dfa503c2a..b551ca350e00 100644 --- a/drivers/media/dvb-frontends/stv0900_core.c +++ b/drivers/media/dvb-frontends/stv0900_core.c @@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32 { u32 m_div, clk_sel; - dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, - intp->quartz); - if (intp == NULL) return STV0900_INVALID_HANDLE; if (intp->errs) return STV0900_I2C_ERROR; + dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk, + intp->quartz); + clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6); m_div = ((clk_sel * mclk) / intp->quartz) - 1; stv0900_write_bits(intp, F0900_M_DIV, m_div); diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index 109bc9b12e74..05f8950f6f91 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c @@ -53,8 +53,7 @@ MODULE_LICENSE("GPL"); /* ADV7604 system clock frequency */ #define ADV7604_fsc (28636360) -#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \ - (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR)) +#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI) /* ********************************************************************** @@ -68,7 +67,7 @@ struct adv7604_state { struct v4l2_subdev sd; struct media_pad pad; struct v4l2_ctrl_handler hdl; - enum adv7604_prim_mode prim_mode; + enum adv7604_mode mode; struct v4l2_dv_timings timings; u8 edid[256]; unsigned edid_blocks; @@ -77,6 +76,7 @@ struct adv7604_state { struct workqueue_struct *work_queues; struct delayed_work delayed_work_enable_hotplug; bool connector_hdmi; + bool restart_stdi_once; /* i2c clients */ struct i2c_client *i2c_avlink; @@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = { V4L2_DV_BT_CEA_720X576P50, V4L2_DV_BT_CEA_1280X720P24, V4L2_DV_BT_CEA_1280X720P25, - V4L2_DV_BT_CEA_1280X720P30, V4L2_DV_BT_CEA_1280X720P50, V4L2_DV_BT_CEA_1280X720P60, V4L2_DV_BT_CEA_1920X1080P24, @@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = { V4L2_DV_BT_CEA_1920X1080P50, V4L2_DV_BT_CEA_1920X1080P60, + /* sorted by DMT ID */ V4L2_DV_BT_DMT_640X350P85, V4L2_DV_BT_DMT_640X400P85, V4L2_DV_BT_DMT_720X400P85, @@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = { { }, }; +struct adv7604_video_standards { + struct v4l2_dv_timings timings; + u8 vid_std; + u8 v_freq; +}; + +/* sorted by number of lines */ +static const struct adv7604_video_standards adv7604_prim_mode_comp[] = { + /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */ + { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, + { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 }, + { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 }, + { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, + { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, + { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, + { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, + { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, + /* TODO add 1920x1080P60_RB (CVT timing) */ + { }, +}; + +/* sorted by number of lines */ +static const struct adv7604_video_standards adv7604_prim_mode_gr[] = { + { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, + { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, + { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, + { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, + { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, + { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, + { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, + { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, + { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, + { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, + { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, + { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 }, + { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 }, + { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 }, + { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 }, + { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */ + /* TODO add 1600X1200P60_RB (not a DMT timing) */ + { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 }, + { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */ + { }, +}; + +/* sorted by number of lines */ +static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = { + { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, + { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 }, + { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 }, + { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 }, + { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 }, + { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 }, + { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 }, + { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 }, + { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 }, + { }, +}; + +/* sorted by number of lines */ +static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = { + { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 }, + { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 }, + { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 }, + { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 }, + { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 }, + { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 }, + { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 }, + { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 }, + { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 }, + { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 }, + { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 }, + { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 }, + { }, +}; + /* ----------------------------------------------------------------------- */ static inline struct adv7604_state *to_state(struct v4l2_subdev *sd) @@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) ((io_read(sd, 0x6f) & 0x10) >> 4)); } -static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings) +static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, + u8 prim_mode, + const struct adv7604_video_standards *predef_vid_timings, + const struct v4l2_dv_timings *timings) +{ + struct adv7604_state *state = to_state(sd); + int i; + + for (i = 0; predef_vid_timings[i].timings.bt.width; i++) { + if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings, + DIGITAL_INPUT ? 250000 : 1000000)) + continue; + io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */ + io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) + + prim_mode); /* v_freq and prim mode */ + return 0; + } + + return -1; +} + +static int configure_predefined_video_timings(struct v4l2_subdev *sd, + struct v4l2_dv_timings *timings) { + struct adv7604_state *state = to_state(sd); + int err; + + v4l2_dbg(1, debug, sd, "%s", __func__); + + /* reset to default values */ + io_write(sd, 0x16, 0x43); + io_write(sd, 0x17, 0x5a); + /* disable embedded syncs for auto graphics mode */ + cp_write_and_or(sd, 0x81, 0xef, 0x00); + cp_write(sd, 0x8f, 0x00); + cp_write(sd, 0x90, 0x00); + cp_write(sd, 0xa2, 0x00); + cp_write(sd, 0xa3, 0x00); + cp_write(sd, 0xa4, 0x00); + cp_write(sd, 0xa5, 0x00); + cp_write(sd, 0xa6, 0x00); + cp_write(sd, 0xa7, 0x00); + cp_write(sd, 0xab, 0x00); + cp_write(sd, 0xac, 0x00); + + switch (state->mode) { + case ADV7604_MODE_COMP: + case ADV7604_MODE_GR: + err = find_and_set_predefined_video_timings(sd, + 0x01, adv7604_prim_mode_comp, timings); + if (err) + err = find_and_set_predefined_video_timings(sd, + 0x02, adv7604_prim_mode_gr, timings); + break; + case ADV7604_MODE_HDMI: + err = find_and_set_predefined_video_timings(sd, + 0x05, adv7604_prim_mode_hdmi_comp, timings); + if (err) + err = find_and_set_predefined_video_timings(sd, + 0x06, adv7604_prim_mode_hdmi_gr, timings); + break; + default: + v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", + __func__, state->mode); + err = -1; + break; + } + + + return err; +} + +static void configure_custom_video_timings(struct v4l2_subdev *sd, + const struct v4l2_bt_timings *bt) +{ + struct adv7604_state *state = to_state(sd); struct i2c_client *client = v4l2_get_subdevdata(sd); - u32 width = htotal(timings); - u32 height = vtotal(timings); - u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ? - ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0; + u32 width = htotal(bt); + u32 height = vtotal(bt); + u16 cp_start_sav = bt->hsync + bt->hbackporch - 4; + u16 cp_start_eav = width - bt->hfrontporch; + u16 cp_start_vbi = height - bt->vfrontporch; + u16 cp_end_vbi = bt->vsync + bt->vbackporch; + u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ? + ((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0; + const u8 pll[2] = { + 0xc0 | ((width >> 8) & 0x1f), + width & 0xff + }; v4l2_dbg(2, debug, sd, "%s\n", __func__); - cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); /* CH1_FR_LL */ - cp_write(sd, 0x90, ch1_fr_ll & 0xff); /* CH1_FR_LL */ - cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */ - cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */ - /* TODO support interlaced */ - cp_write(sd, 0x91, 0x10); /* INTERLACED */ - - /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */ - if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) { - u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi; - const u8 pll[2] = { - (0xc0 | ((width >> 8) & 0x1f)), - (width & 0xff) - }; + switch (state->mode) { + case ADV7604_MODE_COMP: + case ADV7604_MODE_GR: + /* auto graphics */ + io_write(sd, 0x00, 0x07); /* video std */ + io_write(sd, 0x01, 0x02); /* prim mode */ + /* enable embedded syncs for auto graphics mode */ + cp_write_and_or(sd, 0x81, 0xef, 0x10); + /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */ /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */ /* IO-map reg. 0x16 and 0x17 should be written in sequence */ if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) { v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n"); - return; + break; } /* active video - horizontal timing */ - cp_start_sav = timings->hsync + timings->hbackporch - 4; - cp_start_eav = width - timings->hfrontporch; cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff); - cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f)); + cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | + ((cp_start_eav >> 8) & 0x0f)); cp_write(sd, 0xa4, cp_start_eav & 0xff); /* active video - vertical timing */ - cp_start_vbi = height - timings->vfrontporch; - cp_end_vbi = timings->vsync + timings->vbackporch; cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff); - cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf)); + cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | + ((cp_end_vbi >> 8) & 0xf)); cp_write(sd, 0xa7, cp_end_vbi & 0xff); - } else { - /* reset to default values */ - io_write(sd, 0x16, 0x43); - io_write(sd, 0x17, 0x5a); - cp_write(sd, 0xa2, 0x00); - cp_write(sd, 0xa3, 0x00); - cp_write(sd, 0xa4, 0x00); - cp_write(sd, 0xa5, 0x00); - cp_write(sd, 0xa6, 0x00); - cp_write(sd, 0xa7, 0x00); + break; + case ADV7604_MODE_HDMI: + /* set default prim_mode/vid_std for HDMI + accoring to [REF_03, c. 4.2] */ + io_write(sd, 0x00, 0x02); /* video std */ + io_write(sd, 0x01, 0x06); /* prim mode */ + break; + default: + v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", + __func__, state->mode); + break; } -} + cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7); + cp_write(sd, 0x90, ch1_fr_ll & 0xff); + cp_write(sd, 0xab, (height >> 4) & 0xff); + cp_write(sd, 0xac, (height & 0x0f) << 4); +} static void set_rgb_quantization_range(struct v4l2_subdev *sd) { @@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) switch (state->rgb_quantization_range) { case V4L2_DV_RGB_RANGE_AUTO: /* automatic */ - if ((hdmi_read(sd, 0x05) & 0x80) || - (state->prim_mode == ADV7604_PRIM_MODE_COMP) || - (state->prim_mode == ADV7604_PRIM_MODE_RGB)) { - /* receiving HDMI or analog signal */ - io_write_and_or(sd, 0x02, 0x0f, 0xf0); - } else { + if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) { /* receiving DVI-D signal */ /* ADV7604 selects RGB limited range regardless of @@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) /* RGB full range (0-255) */ io_write_and_or(sd, 0x02, 0x0f, 0x10); } + } else { + /* receiving HDMI or analog signal, set automode */ + io_write_and_or(sd, 0x02, 0x0f, 0xf0); } break; case V4L2_DV_RGB_RANGE_LIMITED: @@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd, state->aspect_ratio, timings)) return 0; - v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n", - __func__, stdi->lcf, stdi->bl); + v4l2_dbg(2, debug, sd, + "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n", + __func__, stdi->lcvs, stdi->lcf, stdi->bl, + stdi->hs_pol, stdi->vs_pol); return -1; } @@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, adv7604_fill_optional_dv_timings_fields(sd, timings); } else { /* find format - * Since LCVS values are inaccurate (REF_03, page 275-276), + * Since LCVS values are inaccurate [REF_03, p. 275-276], * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails. */ if (!stdi2dv_timings(sd, &stdi, timings)) @@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, stdi.lcvs -= 2; v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs); if (stdi2dv_timings(sd, &stdi, timings)) { + /* + * The STDI block may measure wrong values, especially + * for lcvs and lcf. If the driver can not find any + * valid timing, the STDI block is restarted to measure + * the video timings again. The function will return an + * error, but the restart of STDI will generate a new + * STDI interrupt and the format detection process will + * restart. + */ + if (state->restart_stdi_once) { + v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__); + /* TODO restart STDI for Sync Channel 2 */ + /* enter one-shot mode */ + cp_write_and_or(sd, 0x86, 0xf9, 0x00); + /* trigger STDI restart */ + cp_write_and_or(sd, 0x86, 0xf9, 0x04); + /* reset to continuous mode */ + cp_write_and_or(sd, 0x86, 0xf9, 0x02); + state->restart_stdi_once = false; + return -ENOLINK; + } v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__); return -ERANGE; } + state->restart_stdi_once = true; } found: @@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, { struct adv7604_state *state = to_state(sd); struct v4l2_bt_timings *bt; + int err; if (!timings) return -EINVAL; @@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, __func__, (u32)bt->pixelclock); return -ERANGE; } + adv7604_fill_optional_dv_timings_fields(sd, timings); state->timings = *timings; - /* freerun */ - configure_free_run(sd, bt); + cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10); + + /* Use prim_mode and vid_std when available */ + err = configure_predefined_video_timings(sd, timings); + if (err) { + /* custom settings when the video format + does not have prim_mode/vid_std */ + configure_custom_video_timings(sd, bt); + } set_rgb_quantization_range(sd); @@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd, return 0; } -static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) +static void enable_input(struct v4l2_subdev *sd) { - switch (prim_mode) { - case ADV7604_PRIM_MODE_COMP: - case ADV7604_PRIM_MODE_RGB: + struct adv7604_state *state = to_state(sd); + + switch (state->mode) { + case ADV7604_MODE_COMP: + case ADV7604_MODE_GR: /* enable */ io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ break; - case ADV7604_PRIM_MODE_HDMI_COMP: - case ADV7604_PRIM_MODE_HDMI_GR: + case ADV7604_MODE_HDMI: /* enable */ hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */ hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ break; default: - v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", - __func__, prim_mode); + v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", + __func__, state->mode); break; } } @@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd) hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ } -static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode) +static void select_input(struct v4l2_subdev *sd) { - switch (prim_mode) { - case ADV7604_PRIM_MODE_COMP: - case ADV7604_PRIM_MODE_RGB: - /* set mode and select free run resolution */ - io_write(sd, 0x00, 0x07); /* video std */ - io_write(sd, 0x01, 0x02); /* prim mode */ - /* enable embedded syncs for auto graphics mode */ - cp_write_and_or(sd, 0x81, 0xef, 0x10); + struct adv7604_state *state = to_state(sd); + switch (state->mode) { + case ADV7604_MODE_COMP: + case ADV7604_MODE_GR: /* reset ADI recommended settings for HDMI: */ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */ @@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ break; - case ADV7604_PRIM_MODE_HDMI_COMP: - case ADV7604_PRIM_MODE_HDMI_GR: - /* set mode and select free run resolution */ - /* video std */ - io_write(sd, 0x00, - (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e); - io_write(sd, 0x01, prim_mode); /* prim mode */ - /* disable embedded syncs for auto graphics mode */ - cp_write_and_or(sd, 0x81, 0xef, 0x00); - + case ADV7604_MODE_HDMI: /* set ADI recommended settings for HDMI: */ /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */ @@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod break; default: - v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode); + v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n", + __func__, state->mode); break; } } @@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd, v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input); - switch (input) { - case 0: - /* TODO select HDMI_COMP or HDMI_GR */ - state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP; - break; - case 1: - state->prim_mode = ADV7604_PRIM_MODE_RGB; - break; - case 2: - state->prim_mode = ADV7604_PRIM_MODE_COMP; - break; - default: - return -EINVAL; - } + state->mode = input; disable_input(sd); - select_input(sd, state->prim_mode); + select_input(sd); - enable_input(sd, state->prim_mode); + enable_input(sd); return 0; } @@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd) v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true"); v4l2_info(sd, "CP free run: %s\n", (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off")); - v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n", - io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f); + v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n", + io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f, + (io_read(sd, 0x01) & 0x70) >> 4); v4l2_info(sd, "-----Video Timings-----\n"); if (read_stdi(sd, &stdi)) @@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd) cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */ cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */ cp_write(sd, 0xf9, 0x23); /* STDI ch. 1 - LCVS change threshold - - ADI recommended setting [REF_01 c. 2.3.3] */ + ADI recommended setting [REF_01, c. 2.3.3] */ cp_write(sd, 0x45, 0x23); /* STDI ch. 2 - LCVS change threshold - - ADI recommended setting [REF_01 c. 2.3.3] */ + ADI recommended setting [REF_01, c. 2.3.3] */ cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution for digital formats */ @@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd) afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); - state->prim_mode = pdata->prim_mode; - select_input(sd, pdata->prim_mode); - - enable_input(sd, pdata->prim_mode); - /* interrupts */ io_write(sd, 0x40, 0xc2); /* Configure INT1 */ io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */ @@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client, v4l2_err(sd, "failed to create all i2c clients\n"); goto err_i2c; } + state->restart_stdi_once = true; /* work queues */ state->work_queues = create_singlethread_workqueue(client->name); diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c index 13057b966ee9..333ef178d6fb 100644 --- a/drivers/media/i2c/soc_camera/mt9v022.c +++ b/drivers/media/i2c/soc_camera/mt9v022.c @@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a) if (ret & 1) /* Autoexposure */ ret = reg_write(client, mt9v022->reg->max_total_shutter_width, rect.height + mt9v022->y_skip_top + 43); - else - ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, - rect.height + mt9v022->y_skip_top + 43); + /* + * If autoexposure is off, there is no need to set + * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off + * only if the user has set exposure manually, using the + * V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL. + * In this case the register MT9V022_TOTAL_SHUTTER_WIDTH + * already contains the correct value. + */ } /* Setup frame format: defaults apart from width and height */ if (!ret) diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index bfec9e65aefb..19cbb12a12a2 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c @@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = { MODULE_DEVICE_TABLE(platform, gsc_driver_ids); static const struct of_device_id exynos_gsc_match[] = { - { .compatible = "samsung,exynos5250-gsc", - .data = &gsc_v_100_drvdata, }, + { + .compatible = "samsung,exynos5-gsc", + .data = &gsc_v_100_drvdata, + }, {}, }; MODULE_DEVICE_TABLE(of, exynos_gsc_match); diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c index 60181ab96063..aa9df9d71a7b 100644 --- a/drivers/media/platform/omap3isp/ispccdc.c +++ b/drivers/media/platform/omap3isp/ispccdc.c @@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) } static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) + struct v4l2_event_subscription *sub) { if (sub->type != V4L2_EVENT_FRAME_SYNC) return -EINVAL; @@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, } static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) + struct v4l2_event_subscription *sub) { return v4l2_event_unsubscribe(fh, sub); } diff --git a/drivers/media/platform/omap3isp/ispstat.c b/drivers/media/platform/omap3isp/ispstat.c index d7ac76b5c2ae..b8640be692f1 100644 --- a/drivers/media/platform/omap3isp/ispstat.c +++ b/drivers/media/platform/omap3isp/ispstat.c @@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat) int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) + struct v4l2_event_subscription *sub) { struct ispstat *stat = v4l2_get_subdevdata(subdev); @@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub) + struct v4l2_event_subscription *sub) { return v4l2_event_unsubscribe(fh, sub); } diff --git a/drivers/media/platform/omap3isp/ispstat.h b/drivers/media/platform/omap3isp/ispstat.h index a6fe653eb237..9b7c8654dc8a 100644 --- a/drivers/media/platform/omap3isp/ispstat.h +++ b/drivers/media/platform/omap3isp/ispstat.h @@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name, void omap3isp_stat_cleanup(struct ispstat *stat); int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub); + struct v4l2_event_subscription *sub); int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev, struct v4l2_fh *fh, - const struct v4l2_event_subscription *sub); + struct v4l2_event_subscription *sub); int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable); int omap3isp_stat_busy(struct ispstat *stat); diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index a0b737fecf13..75cd309035f9 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c @@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop) } static int -isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop) +isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop) { struct isp_video *video = video_drvdata(file); struct v4l2_subdev *subdev; diff --git a/drivers/media/platform/s5p-fimc/Kconfig b/drivers/media/platform/s5p-fimc/Kconfig index 8f090a8f270e..c16b20d86ed2 100644 --- a/drivers/media/platform/s5p-fimc/Kconfig +++ b/drivers/media/platform/s5p-fimc/Kconfig @@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC config VIDEO_S5P_MIPI_CSIS tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver" depends on REGULATOR + select S5P_SETUP_MIPIPHY help This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2 receiver (MIPI-CSIS) devices. diff --git a/drivers/media/platform/s5p-fimc/fimc-capture.c b/drivers/media/platform/s5p-fimc/fimc-capture.c index 367efd164d0f..3d39d97abaa5 100644 --- a/drivers/media/platform/s5p-fimc/fimc-capture.c +++ b/drivers/media/platform/s5p-fimc/fimc-capture.c @@ -1736,7 +1736,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct fimc_vid_buffer); - vb2_queue_init(q); + ret = vb2_queue_init(q); + if (ret) + goto err_ent; vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0); diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c index 70bcf39de879..9db246bed841 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite.c @@ -1253,7 +1253,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd) q->buf_struct_size = sizeof(struct flite_buffer); q->drv_priv = fimc; - vb2_queue_init(q); + ret = vb2_queue_init(q); + if (ret < 0) + return ret; fimc->vd_pad.flags = MEDIA_PAD_FL_SINK; ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0); diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 80ada5882f62..38ea4d143a49 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c @@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) static int fimc_register_callback(struct device *dev, void *p) { struct fimc_dev *fimc = dev_get_drvdata(dev); - struct v4l2_subdev *sd = &fimc->vid_cap.subdev; + struct v4l2_subdev *sd; struct fimc_md *fmd = p; - int ret = 0; - - if (!fimc || !fimc->pdev) - return 0; + int ret; - if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS) + if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS) return 0; - fimc->pipeline_ops = &fimc_pipeline_ops; - fmd->fimc[fimc->pdev->id] = fimc; + sd = &fimc->vid_cap.subdev; sd->grp_id = FIMC_GROUP_ID; ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); if (ret) { v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n", fimc->id, ret); + return ret; } - return ret; + fimc->pipeline_ops = &fimc_pipeline_ops; + fmd->fimc[fimc->id] = fimc; + return 0; } static int fimc_lite_register_callback(struct device *dev, void *p) { struct fimc_lite *fimc = dev_get_drvdata(dev); - struct v4l2_subdev *sd = &fimc->subdev; struct fimc_md *fmd = p; int ret; - if (fimc == NULL) + if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS) return 0; - if (fimc->index >= FIMC_LITE_MAX_DEVS) - return 0; + fimc->subdev.grp_id = FLITE_GROUP_ID; - fimc->pipeline_ops = &fimc_pipeline_ops; - fmd->fimc_lite[fimc->index] = fimc; - sd->grp_id = FLITE_GROUP_ID; - - ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); + ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev); if (ret) { v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC-LITE.%d (%d)\n", fimc->index, ret); + return ret; } - return ret; + + fimc->pipeline_ops = &fimc_pipeline_ops; + fmd->fimc_lite[fimc->index] = fimc; + return 0; } static int csis_register_callback(struct device *dev, void *p) @@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p) v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name); id = pdev->id < 0 ? 0 : pdev->id; - fmd->csis[id].sd = sd; sd->grp_id = CSIS_GROUP_ID; + ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); - if (ret) + if (!ret) + fmd->csis[id].sd = sd; + else v4l2_err(&fmd->v4l2_dev, "Failed to register CSIS subdevice: %d\n", ret); return ret; diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 85fd312f0a82..a1c87f0ceaab 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a) /* Assume a dull encoder, do all the work ourselves. */ static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a) { + struct v4l2_crop a_writable = *a; struct video_device *vdev = video_devdata(file); struct sh_vou_device *vou_dev = video_get_drvdata(vdev); - struct v4l2_rect *rect = &a->c; + struct v4l2_rect *rect = &a_writable.c; struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT}; struct v4l2_pix_format *pix = &vou_dev->pix; struct sh_vou_geometry geo; diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c index bbe70991d30b..032b8c9097f9 100644 --- a/drivers/media/platform/soc_camera/mx1_camera.c +++ b/drivers/media/platform/soc_camera/mx1_camera.c @@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd) pcdev->icd = NULL; } -static int mx1_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) -{ - struct v4l2_subdev *sd = soc_camera_to_subdev(icd); - - return v4l2_subdev_call(sd, video, s_crop, a); -} - static int mx1_camera_set_bus_param(struct soc_camera_device *icd) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); @@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = { .add = mx1_camera_add_device, .remove = mx1_camera_remove_device, .set_bus_param = mx1_camera_set_bus_param, - .set_crop = mx1_camera_set_crop, .set_fmt = mx1_camera_set_fmt, .try_fmt = mx1_camera_try_fmt, .init_videobuf = mx1_camera_init_videobuf, diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c index 9fd9d1c5b218..9a55f4c4c7f4 100644 --- a/drivers/media/platform/soc_camera/mx2_camera.c +++ b/drivers/media/platform/soc_camera/mx2_camera.c @@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) bytesperline = soc_mbus_bytes_per_line(icd->user_width, icd->current_fmt->host_fmt); - if (bytesperline < 0) + if (bytesperline < 0) { + spin_unlock_irqrestore(&pcdev->lock, flags); return bytesperline; + } /* * I didn't manage to properly enable/disable the prp @@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count) pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev, pcdev->discard_size, &pcdev->discard_buffer_dma, GFP_KERNEL); - if (!pcdev->discard_buffer) + if (!pcdev->discard_buffer) { + spin_unlock_irqrestore(&pcdev->lock, flags); return -ENOMEM; + } pcdev->buf_discard[0].discard = true; list_add_tail(&pcdev->buf_discard[0].queue, @@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd) } static int mx2_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) + const struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_crop a_writable = *a; + struct v4l2_rect *rect = &a_writable.c; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_mbus_framefmt mf; int ret; diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c index 3557ac97e430..261f6e9e1b17 100644 --- a/drivers/media/platform/soc_camera/mx3_camera.c +++ b/drivers/media/platform/soc_camera/mx3_camera.c @@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width) * default g_crop and cropcap from soc_camera.c */ static int mx3_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) + const struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_crop a_writable = *a; + struct v4l2_rect *rect = &a_writable.c; struct soc_camera_host *ici = to_soc_camera_host(icd->parent); struct mx3_camera_dev *mx3_cam = ici->priv; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c index fa08c7695ccb..13636a585106 100644 --- a/drivers/media/platform/soc_camera/omap1_camera.c +++ b/drivers/media/platform/soc_camera/omap1_camera.c @@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev, } static int omap1_cam_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *crop) + const struct v4l2_crop *crop) { - struct v4l2_rect *rect = &crop->c; + const struct v4l2_rect *rect = &crop->c; const struct soc_camera_format_xlate *xlate = icd->current_fmt; struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct device *dev = icd->parent; diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c index 1e3776d08dac..3434ffe79c6e 100644 --- a/drivers/media/platform/soc_camera/pxa_camera.c +++ b/drivers/media/platform/soc_camera/pxa_camera.c @@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height) } static int pxa_camera_set_crop(struct soc_camera_device *icd, - struct v4l2_crop *a) + const struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + const struct v4l2_rect *rect = &a->c; struct device *dev = icd->parent; struct soc_camera_host *ici = to_soc_camera_host(dev); struct pxa_camera_dev *pcdev = ici->priv; diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c index 0a24253dcda2..2d8861c0e8f2 100644 --- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c +++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c @@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd) } /* Check if any dimension of r1 is smaller than respective one of r2 */ -static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2) +static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2) { return r1->width < r2->width || r1->height < r2->height; } /* Check if r1 fails to cover r2 */ -static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2) +static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2) { return r1->left > r2->left || r1->top > r2->top || r1->left + r1->width < r2->left + r2->width || @@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam) * 3. if (2) failed, try to request the maximum image */ static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop, - const struct v4l2_crop *cam_crop) + struct v4l2_crop *cam_crop) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c; @@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd, static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, const struct v4l2_crop *a) { - struct v4l2_rect *rect = &a->c; + struct v4l2_crop a_writable = *a; + const struct v4l2_rect *rect = &a_writable.c; struct device *dev = icd->parent; struct soc_camera_host *ici = to_soc_camera_host(dev); struct sh_mobile_ceu_dev *pcdev = ici->priv; @@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd, * 1. - 2. Apply iterative camera S_CROP for new input window, read back * actual camera rectangle. */ - ret = client_s_crop(icd, a, &cam_crop); + ret = client_s_crop(icd, &a_writable, &cam_crop); if (ret < 0) return ret; @@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, } static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, - struct v4l2_crop *a) + const struct v4l2_crop *a) { struct v4l2_subdev *sd = soc_camera_to_subdev(icd); struct soc_camera_host *ici = to_soc_camera_host(icd->parent); diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c index 9859d2a2449b..ba51f65204de 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c @@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, /* activate the pid on the device pid filter */ if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER && - adap->pid_filtering && - adap->props->pid_filter) + adap->pid_filtering && adap->props->pid_filter) { ret = adap->props->pid_filter(adap, dvbdmxfeed->index, dvbdmxfeed->pid, (count == 1) ? 1 : 0); - if (ret < 0) - dev_err(&d->udev->dev, "%s: pid_filter() " \ - "failed=%d\n", KBUILD_MODNAME, - ret); + if (ret < 0) + dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n", + KBUILD_MODNAME, ret); + } /* start feeding if it is first pid */ if (adap->feed_count == 1 && count == 1) { diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c index 0431beed0ef4..5716662b4834 100644 --- a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c +++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c @@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf, return -EINVAL; } - ret = mutex_lock_interruptible(&d->usb_mutex); - if (ret < 0) - return ret; + mutex_lock(&d->usb_mutex); dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf); diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c index adabba8d28bc..093f1acce403 100644 --- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c +++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c @@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = { &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) }, { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3, &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) }, + { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102, + &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) }, + { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7, + &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) }, { } }; MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table); diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 1b48f2094806..f4f9bf84bc7b 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -98,9 +98,9 @@ static irqreturn_t arizona_underclocked(int irq, void *data) if (val & ARIZONA_AIF3_UNDERCLOCKED_STS) dev_err(arizona->dev, "AIF3 underclocked\n"); - if (val & ARIZONA_AIF3_UNDERCLOCKED_STS) - dev_err(arizona->dev, "AIF3 underclocked\n"); if (val & ARIZONA_AIF2_UNDERCLOCKED_STS) + dev_err(arizona->dev, "AIF2 underclocked\n"); + if (val & ARIZONA_AIF1_UNDERCLOCKED_STS) dev_err(arizona->dev, "AIF1 underclocked\n"); if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS) dev_err(arizona->dev, "ISRC2 underclocked\n"); @@ -415,11 +415,19 @@ int __devinit arizona_dev_init(struct arizona *arizona) /* If we have a /RESET GPIO we'll already be reset */ if (!arizona->pdata.reset) { + regcache_mark_dirty(arizona->regmap); + ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0); if (ret != 0) { dev_err(dev, "Failed to reset device: %d\n", ret); goto err_reset; } + + ret = regcache_sync(arizona->regmap); + if (ret != 0) { + dev_err(dev, "Failed to sync device: %d\n", ret); + goto err_reset; + } } ret = arizona_wait_for_boot(arizona); @@ -520,7 +528,7 @@ int __devinit arizona_dev_init(struct arizona *arizona) break; case WM5110: ret = mfd_add_devices(arizona->dev, -1, wm5110_devs, - ARRAY_SIZE(wm5102_devs), NULL, 0, NULL); + ARRAY_SIZE(wm5110_devs), NULL, 0, NULL); break; } diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index ef0f2d001df2..b1b009177405 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c @@ -178,6 +178,7 @@ int arizona_irq_init(struct arizona *arizona) switch (arizona->rev) { case 0: + case 1: ctrlif_error = false; break; default: diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index 4ae642320205..a071a8643a47 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -671,7 +671,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base, } if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) { - child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0, + child = add_child(SUB_CHIP_ID1, "twl6030-pwm", NULL, 0, false, 0, 0); if (IS_ERR(child)) return PTR_ERR(child); diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index ad733d76207a..cdd1173ed4e9 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c @@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base) irq = sih_mod + twl4030_irq_base; irq_set_handler_data(irq, agent); agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name); - status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, + status = request_threaded_irq(irq, NULL, handle_twl4030_sih, + IRQF_EARLY_RESUME, agent->irq_name ?: sih->name, NULL); dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name, diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 01b9255ed631..14490cc785d2 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c @@ -43,6 +43,7 @@ static const struct reg_default wm5102_reva_patch[] = { { 0x479, 0x0A30 }, { 0x47B, 0x0810 }, { 0x47D, 0x0510 }, + { 0x4D1, 0x017F }, { 0x500, 0x000D }, { 0x507, 0x1820 }, { 0x508, 0x1820 }, @@ -52,524 +53,6 @@ static const struct reg_default wm5102_reva_patch[] = { { 0x580, 0x000D }, { 0x587, 0x1820 }, { 0x588, 0x1820 }, - { 0x101, 0x8140 }, - { 0x3000, 0x2225 }, - { 0x3001, 0x3a03 }, - { 0x3002, 0x0225 }, - { 0x3003, 0x0801 }, - { 0x3004, 0x6249 }, - { 0x3005, 0x0c04 }, - { 0x3006, 0x0225 }, - { 0x3007, 0x5901 }, - { 0x3008, 0xe249 }, - { 0x3009, 0x030d }, - { 0x300a, 0x0249 }, - { 0x300b, 0x2c01 }, - { 0x300c, 0xe249 }, - { 0x300d, 0x4342 }, - { 0x300e, 0xe249 }, - { 0x300f, 0x73c0 }, - { 0x3010, 0x4249 }, - { 0x3011, 0x0c00 }, - { 0x3012, 0x0225 }, - { 0x3013, 0x1f01 }, - { 0x3014, 0x0225 }, - { 0x3015, 0x1e01 }, - { 0x3016, 0x0225 }, - { 0x3017, 0xfa00 }, - { 0x3018, 0x0000 }, - { 0x3019, 0xf000 }, - { 0x301a, 0x0000 }, - { 0x301b, 0xf000 }, - { 0x301c, 0x0000 }, - { 0x301d, 0xf000 }, - { 0x301e, 0x0000 }, - { 0x301f, 0xf000 }, - { 0x3020, 0x0000 }, - { 0x3021, 0xf000 }, - { 0x3022, 0x0000 }, - { 0x3023, 0xf000 }, - { 0x3024, 0x0000 }, - { 0x3025, 0xf000 }, - { 0x3026, 0x0000 }, - { 0x3027, 0xf000 }, - { 0x3028, 0x0000 }, - { 0x3029, 0xf000 }, - { 0x302a, 0x0000 }, - { 0x302b, 0xf000 }, - { 0x302c, 0x0000 }, - { 0x302d, 0xf000 }, - { 0x302e, 0x0000 }, - { 0x302f, 0xf000 }, - { 0x3030, 0x0225 }, - { 0x3031, 0x1a01 }, - { 0x3032, 0x0225 }, - { 0x3033, 0x1e00 }, - { 0x3034, 0x0225 }, - { 0x3035, 0x1f00 }, - { 0x3036, 0x6225 }, - { 0x3037, 0xf800 }, - { 0x3038, 0x0000 }, - { 0x3039, 0xf000 }, - { 0x303a, 0x0000 }, - { 0x303b, 0xf000 }, - { 0x303c, 0x0000 }, - { 0x303d, 0xf000 }, - { 0x303e, 0x0000 }, - { 0x303f, 0xf000 }, - { 0x3040, 0x2226 }, - { 0x3041, 0x3a03 }, - { 0x3042, 0x0226 }, - { 0x3043, 0x0801 }, - { 0x3044, 0x6249 }, - { 0x3045, 0x0c06 }, - { 0x3046, 0x0226 }, - { 0x3047, 0x5901 }, - { 0x3048, 0xe249 }, - { 0x3049, 0x030d }, - { 0x304a, 0x0249 }, - { 0x304b, 0x2c01 }, - { 0x304c, 0xe249 }, - { 0x304d, 0x4342 }, - { 0x304e, 0xe249 }, - { 0x304f, 0x73c0 }, - { 0x3050, 0x4249 }, - { 0x3051, 0x0c00 }, - { 0x3052, 0x0226 }, - { 0x3053, 0x1f01 }, - { 0x3054, 0x0226 }, - { 0x3055, 0x1e01 }, - { 0x3056, 0x0226 }, - { 0x3057, 0xfa00 }, - { 0x3058, 0x0000 }, - { 0x3059, 0xf000 }, - { 0x305a, 0x0000 }, - { 0x305b, 0xf000 }, - { 0x305c, 0x0000 }, - { 0x305d, 0xf000 }, - { 0x305e, 0x0000 }, - { 0x305f, 0xf000 }, - { 0x3060, 0x0000 }, - { 0x3061, 0xf000 }, - { 0x3062, 0x0000 }, - { 0x3063, 0xf000 }, - { 0x3064, 0x0000 }, - { 0x3065, 0xf000 }, - { 0x3066, 0x0000 }, - { 0x3067, 0xf000 }, - { 0x3068, 0x0000 }, - { 0x3069, 0xf000 }, - { 0x306a, 0x0000 }, - { 0x306b, 0xf000 }, - { 0x306c, 0x0000 }, - { 0x306d, 0xf000 }, - { 0x306e, 0x0000 }, - { 0x306f, 0xf000 }, - { 0x3070, 0x0226 }, - { 0x3071, 0x1a01 }, - { 0x3072, 0x0226 }, - { 0x3073, 0x1e00 }, - { 0x3074, 0x0226 }, - { 0x3075, 0x1f00 }, - { 0x3076, 0x6226 }, - { 0x3077, 0xf800 }, - { 0x3078, 0x0000 }, - { 0x3079, 0xf000 }, - { 0x307a, 0x0000 }, - { 0x307b, 0xf000 }, - { 0x307c, 0x0000 }, - { 0x307d, 0xf000 }, - { 0x307e, 0x0000 }, - { 0x307f, 0xf000 }, - { 0x3080, 0x2227 }, - { 0x3081, 0x3a03 }, - { 0x3082, 0x0227 }, - { 0x3083, 0x0801 }, - { 0x3084, 0x6255 }, - { 0x3085, 0x0c04 }, - { 0x3086, 0x0227 }, - { 0x3087, 0x5901 }, - { 0x3088, 0xe255 }, - { 0x3089, 0x030d }, - { 0x308a, 0x0255 }, - { 0x308b, 0x2c01 }, - { 0x308c, 0xe255 }, - { 0x308d, 0x4342 }, - { 0x308e, 0xe255 }, - { 0x308f, 0x73c0 }, - { 0x3090, 0x4255 }, - { 0x3091, 0x0c00 }, - { 0x3092, 0x0227 }, - { 0x3093, 0x1f01 }, - { 0x3094, 0x0227 }, - { 0x3095, 0x1e01 }, - { 0x3096, 0x0227 }, - { 0x3097, 0xfa00 }, - { 0x3098, 0x0000 }, - { 0x3099, 0xf000 }, - { 0x309a, 0x0000 }, - { 0x309b, 0xf000 }, - { 0x309c, 0x0000 }, - { 0x309d, 0xf000 }, - { 0x309e, 0x0000 }, - { 0x309f, 0xf000 }, - { 0x30a0, 0x0000 }, - { 0x30a1, 0xf000 }, - { 0x30a2, 0x0000 }, - { 0x30a3, 0xf000 }, - { 0x30a4, 0x0000 }, - { 0x30a5, 0xf000 }, - { 0x30a6, 0x0000 }, - { 0x30a7, 0xf000 }, - { 0x30a8, 0x0000 }, - { 0x30a9, 0xf000 }, - { 0x30aa, 0x0000 }, - { 0x30ab, 0xf000 }, - { 0x30ac, 0x0000 }, - { 0x30ad, 0xf000 }, - { 0x30ae, 0x0000 }, - { 0x30af, 0xf000 }, - { 0x30b0, 0x0227 }, - { 0x30b1, 0x1a01 }, - { 0x30b2, 0x0227 }, - { 0x30b3, 0x1e00 }, - { 0x30b4, 0x0227 }, - { 0x30b5, 0x1f00 }, - { 0x30b6, 0x6227 }, - { 0x30b7, 0xf800 }, - { 0x30b8, 0x0000 }, - { 0x30b9, 0xf000 }, - { 0x30ba, 0x0000 }, - { 0x30bb, 0xf000 }, - { 0x30bc, 0x0000 }, - { 0x30bd, 0xf000 }, - { 0x30be, 0x0000 }, - { 0x30bf, 0xf000 }, - { 0x30c0, 0x2228 }, - { 0x30c1, 0x3a03 }, - { 0x30c2, 0x0228 }, - { 0x30c3, 0x0801 }, - { 0x30c4, 0x6255 }, - { 0x30c5, 0x0c06 }, - { 0x30c6, 0x0228 }, - { 0x30c7, 0x5901 }, - { 0x30c8, 0xe255 }, - { 0x30c9, 0x030d }, - { 0x30ca, 0x0255 }, - { 0x30cb, 0x2c01 }, - { 0x30cc, 0xe255 }, - { 0x30cd, 0x4342 }, - { 0x30ce, 0xe255 }, - { 0x30cf, 0x73c0 }, - { 0x30d0, 0x4255 }, - { 0x30d1, 0x0c00 }, - { 0x30d2, 0x0228 }, - { 0x30d3, 0x1f01 }, - { 0x30d4, 0x0228 }, - { 0x30d5, 0x1e01 }, - { 0x30d6, 0x0228 }, - { 0x30d7, 0xfa00 }, - { 0x30d8, 0x0000 }, - { 0x30d9, 0xf000 }, - { 0x30da, 0x0000 }, - { 0x30db, 0xf000 }, - { 0x30dc, 0x0000 }, - { 0x30dd, 0xf000 }, - { 0x30de, 0x0000 }, - { 0x30df, 0xf000 }, - { 0x30e0, 0x0000 }, - { 0x30e1, 0xf000 }, - { 0x30e2, 0x0000 }, - { 0x30e3, 0xf000 }, - { 0x30e4, 0x0000 }, - { 0x30e5, 0xf000 }, - { 0x30e6, 0x0000 }, - { 0x30e7, 0xf000 }, - { 0x30e8, 0x0000 }, - { 0x30e9, 0xf000 }, - { 0x30ea, 0x0000 }, - { 0x30eb, 0xf000 }, - { 0x30ec, 0x0000 }, - { 0x30ed, 0xf000 }, - { 0x30ee, 0x0000 }, - { 0x30ef, 0xf000 }, - { 0x30f0, 0x0228 }, - { 0x30f1, 0x1a01 }, - { 0x30f2, 0x0228 }, - { 0x30f3, 0x1e00 }, - { 0x30f4, 0x0228 }, - { 0x30f5, 0x1f00 }, - { 0x30f6, 0x6228 }, - { 0x30f7, 0xf800 }, - { 0x30f8, 0x0000 }, - { 0x30f9, 0xf000 }, - { 0x30fa, 0x0000 }, - { 0x30fb, 0xf000 }, - { 0x30fc, 0x0000 }, - { 0x30fd, 0xf000 }, - { 0x30fe, 0x0000 }, - { 0x30ff, 0xf000 }, - { 0x3100, 0x222b }, - { 0x3101, 0x3a03 }, - { 0x3102, 0x222b }, - { 0x3103, 0x5803 }, - { 0x3104, 0xe26f }, - { 0x3105, 0x030d }, - { 0x3106, 0x626f }, - { 0x3107, 0x2c01 }, - { 0x3108, 0xe26f }, - { 0x3109, 0x4342 }, - { 0x310a, 0xe26f }, - { 0x310b, 0x73c0 }, - { 0x310c, 0x026f }, - { 0x310d, 0x0c00 }, - { 0x310e, 0x022b }, - { 0x310f, 0x1f01 }, - { 0x3110, 0x022b }, - { 0x3111, 0x1e01 }, - { 0x3112, 0x022b }, - { 0x3113, 0xfa00 }, - { 0x3114, 0x0000 }, - { 0x3115, 0xf000 }, - { 0x3116, 0x0000 }, - { 0x3117, 0xf000 }, - { 0x3118, 0x0000 }, - { 0x3119, 0xf000 }, - { 0x311a, 0x0000 }, - { 0x311b, 0xf000 }, - { 0x311c, 0x0000 }, - { 0x311d, 0xf000 }, - { 0x311e, 0x0000 }, - { 0x311f, 0xf000 }, - { 0x3120, 0x022b }, - { 0x3121, 0x0a01 }, - { 0x3122, 0x022b }, - { 0x3123, 0x1e00 }, - { 0x3124, 0x022b }, - { 0x3125, 0x1f00 }, - { 0x3126, 0x622b }, - { 0x3127, 0xf800 }, - { 0x3128, 0x0000 }, - { 0x3129, 0xf000 }, - { 0x312a, 0x0000 }, - { 0x312b, 0xf000 }, - { 0x312c, 0x0000 }, - { 0x312d, 0xf000 }, - { 0x312e, 0x0000 }, - { 0x312f, 0xf000 }, - { 0x3130, 0x0000 }, - { 0x3131, 0xf000 }, - { 0x3132, 0x0000 }, - { 0x3133, 0xf000 }, - { 0x3134, 0x0000 }, - { 0x3135, 0xf000 }, - { 0x3136, 0x0000 }, - { 0x3137, 0xf000 }, - { 0x3138, 0x0000 }, - { 0x3139, 0xf000 }, - { 0x313a, 0x0000 }, - { 0x313b, 0xf000 }, - { 0x313c, 0x0000 }, - { 0x313d, 0xf000 }, - { 0x313e, 0x0000 }, - { 0x313f, 0xf000 }, - { 0x3140, 0x0000 }, - { 0x3141, 0xf000 }, - { 0x3142, 0x0000 }, - { 0x3143, 0xf000 }, - { 0x3144, 0x0000 }, - { 0x3145, 0xf000 }, - { 0x3146, 0x0000 }, - { 0x3147, 0xf000 }, - { 0x3148, 0x0000 }, - { 0x3149, 0xf000 }, - { 0x314a, 0x0000 }, - { 0x314b, 0xf000 }, - { 0x314c, 0x0000 }, - { 0x314d, 0xf000 }, - { 0x314e, 0x0000 }, - { 0x314f, 0xf000 }, - { 0x3150, 0x0000 }, - { 0x3151, 0xf000 }, - { 0x3152, 0x0000 }, - { 0x3153, 0xf000 }, - { 0x3154, 0x0000 }, - { 0x3155, 0xf000 }, - { 0x3156, 0x0000 }, - { 0x3157, 0xf000 }, - { 0x3158, 0x0000 }, - { 0x3159, 0xf000 }, - { 0x315a, 0x0000 }, - { 0x315b, 0xf000 }, - { 0x315c, 0x0000 }, - { 0x315d, 0xf000 }, - { 0x315e, 0x0000 }, - { 0x315f, 0xf000 }, - { 0x3160, 0x0000 }, - { 0x3161, 0xf000 }, - { 0x3162, 0x0000 }, - { 0x3163, 0xf000 }, - { 0x3164, 0x0000 }, - { 0x3165, 0xf000 }, - { 0x3166, 0x0000 }, - { 0x3167, 0xf000 }, - { 0x3168, 0x0000 }, - { 0x3169, 0xf000 }, - { 0x316a, 0x0000 }, - { 0x316b, 0xf000 }, - { 0x316c, 0x0000 }, - { 0x316d, 0xf000 }, - { 0x316e, 0x0000 }, - { 0x316f, 0xf000 }, - { 0x3170, 0x0000 }, - { 0x3171, 0xf000 }, - { 0x3172, 0x0000 }, - { 0x3173, 0xf000 }, - { 0x3174, 0x0000 }, - { 0x3175, 0xf000 }, - { 0x3176, 0x0000 }, - { 0x3177, 0xf000 }, - { 0x3178, 0x0000 }, - { 0x3179, 0xf000 }, - { 0x317a, 0x0000 }, - { 0x317b, 0xf000 }, - { 0x317c, 0x0000 }, - { 0x317d, 0xf000 }, - { 0x317e, 0x0000 }, - { 0x317f, 0xf000 }, - { 0x3180, 0x2001 }, - { 0x3181, 0xf101 }, - { 0x3182, 0x0000 }, - { 0x3183, 0xf000 }, - { 0x3184, 0x0000 }, - { 0x3185, 0xf000 }, - { 0x3186, 0x0000 }, - { 0x3187, 0xf000 }, - { 0x3188, 0x0000 }, - { 0x3189, 0xf000 }, - { 0x318a, 0x0000 }, - { 0x318b, 0xf000 }, - { 0x318c, 0x0000 }, - { 0x318d, 0xf000 }, - { 0x318e, 0x0000 }, - { 0x318f, 0xf000 }, - { 0x3190, 0x0000 }, - { 0x3191, 0xf000 }, - { 0x3192, 0x0000 }, - { 0x3193, 0xf000 }, - { 0x3194, 0x0000 }, - { 0x3195, 0xf000 }, - { 0x3196, 0x0000 }, - { 0x3197, 0xf000 }, - { 0x3198, 0x0000 }, - { 0x3199, 0xf000 }, - { 0x319a, 0x0000 }, - { 0x319b, 0xf000 }, - { 0x319c, 0x0000 }, - { 0x319d, 0xf000 }, - { 0x319e, 0x0000 }, - { 0x319f, 0xf000 }, - { 0x31a0, 0x0000 }, - { 0x31a1, 0xf000 }, - { 0x31a2, 0x0000 }, - { 0x31a3, 0xf000 }, - { 0x31a4, 0x0000 }, - { 0x31a5, 0xf000 }, - { 0x31a6, 0x0000 }, - { 0x31a7, 0xf000 }, - { 0x31a8, 0x0000 }, - { 0x31a9, 0xf000 }, - { 0x31aa, 0x0000 }, - { 0x31ab, 0xf000 }, - { 0x31ac, 0x0000 }, - { 0x31ad, 0xf000 }, - { 0x31ae, 0x0000 }, - { 0x31af, 0xf000 }, - { 0x31b0, 0x0000 }, - { 0x31b1, 0xf000 }, - { 0x31b2, 0x0000 }, - { 0x31b3, 0xf000 }, - { 0x31b4, 0x0000 }, - { 0x31b5, 0xf000 }, - { 0x31b6, 0x0000 }, - { 0x31b7, 0xf000 }, - { 0x31b8, 0x0000 }, - { 0x31b9, 0xf000 }, - { 0x31ba, 0x0000 }, - { 0x31bb, 0xf000 }, - { 0x31bc, 0x0000 }, - { 0x31bd, 0xf000 }, - { 0x31be, 0x0000 }, - { 0x31bf, 0xf000 }, - { 0x31c0, 0x0000 }, - { 0x31c1, 0xf000 }, - { 0x31c2, 0x0000 }, - { 0x31c3, 0xf000 }, - { 0x31c4, 0x0000 }, - { 0x31c5, 0xf000 }, - { 0x31c6, 0x0000 }, - { 0x31c7, 0xf000 }, - { 0x31c8, 0x0000 }, - { 0x31c9, 0xf000 }, - { 0x31ca, 0x0000 }, - { 0x31cb, 0xf000 }, - { 0x31cc, 0x0000 }, - { 0x31cd, 0xf000 }, - { 0x31ce, 0x0000 }, - { 0x31cf, 0xf000 }, - { 0x31d0, 0x0000 }, - { 0x31d1, 0xf000 }, - { 0x31d2, 0x0000 }, - { 0x31d3, 0xf000 }, - { 0x31d4, 0x0000 }, - { 0x31d5, 0xf000 }, - { 0x31d6, 0x0000 }, - { 0x31d7, 0xf000 }, - { 0x31d8, 0x0000 }, - { 0x31d9, 0xf000 }, - { 0x31da, 0x0000 }, - { 0x31db, 0xf000 }, - { 0x31dc, 0x0000 }, - { 0x31dd, 0xf000 }, - { 0x31de, 0x0000 }, - { 0x31df, 0xf000 }, - { 0x31e0, 0x0000 }, - { 0x31e1, 0xf000 }, - { 0x31e2, 0x0000 }, - { 0x31e3, 0xf000 }, - { 0x31e4, 0x0000 }, - { 0x31e5, 0xf000 }, - { 0x31e6, 0x0000 }, - { 0x31e7, 0xf000 }, - { 0x31e8, 0x0000 }, - { 0x31e9, 0xf000 }, - { 0x31ea, 0x0000 }, - { 0x31eb, 0xf000 }, - { 0x31ec, 0x0000 }, - { 0x31ed, 0xf000 }, - { 0x31ee, 0x0000 }, - { 0x31ef, 0xf000 }, - { 0x31f0, 0x0000 }, - { 0x31f1, 0xf000 }, - { 0x31f2, 0x0000 }, - { 0x31f3, 0xf000 }, - { 0x31f4, 0x0000 }, - { 0x31f5, 0xf000 }, - { 0x31f6, 0x0000 }, - { 0x31f7, 0xf000 }, - { 0x31f8, 0x0000 }, - { 0x31f9, 0xf000 }, - { 0x31fa, 0x0000 }, - { 0x31fb, 0xf000 }, - { 0x31fc, 0x0000 }, - { 0x31fd, 0xf000 }, - { 0x31fe, 0x0000 }, - { 0x31ff, 0xf000 }, - { 0x024d, 0xff50 }, - { 0x0252, 0xff50 }, - { 0x0259, 0x0112 }, - { 0x025e, 0x0112 }, - { 0x101, 0x0304 }, { 0x80, 0x0000 }, }; diff --git a/drivers/mmc/host/dw_mmc-exynos.c b/drivers/mmc/host/dw_mmc-exynos.c index 660bbc528862..4d50da618166 100644 --- a/drivers/mmc/host/dw_mmc-exynos.c +++ b/drivers/mmc/host/dw_mmc-exynos.c @@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = { MMC_CAP_CMD23, }; -static struct dw_mci_drv_data exynos5250_drv_data = { +static const struct dw_mci_drv_data exynos5250_drv_data = { .caps = exynos5250_dwmmc_caps, .init = dw_mci_exynos_priv_init, .setup_clock = dw_mci_exynos_setup_clock, @@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = { static const struct of_device_id dw_mci_exynos_match[] = { { .compatible = "samsung,exynos5250-dw-mshc", - .data = (void *)&exynos5250_drv_data, }, + .data = &exynos5250_drv_data, }, {}, }; -MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match); +MODULE_DEVICE_TABLE(of, dw_mci_exynos_match); int dw_mci_exynos_probe(struct platform_device *pdev) { - struct dw_mci_drv_data *drv_data; + const struct dw_mci_drv_data *drv_data; const struct of_device_id *match; match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node); diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index c960ca7ffbe6..917936bee5d5 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -24,7 +24,7 @@ #include "dw_mmc.h" int dw_mci_pltfm_register(struct platform_device *pdev, - struct dw_mci_drv_data *drv_data) + const struct dw_mci_drv_data *drv_data) { struct dw_mci *host; struct resource *regs; @@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev, if (!host->regs) return -ENOMEM; - if (host->drv_data->init) { - ret = host->drv_data->init(host); + if (drv_data && drv_data->init) { + ret = drv_data->init(host); if (ret) return ret; } diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index 301f24541fc2..2ac37b81de4d 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -13,7 +13,7 @@ #define _DW_MMC_PLTFM_H_ extern int dw_mci_pltfm_register(struct platform_device *pdev, - struct dw_mci_drv_data *drv_data); + const struct dw_mci_drv_data *drv_data); extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); extern const struct dev_pm_ops dw_mci_pltfm_pmops; diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c2828f35c3b8..c0667c8af2bd 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) { struct mmc_data *data; struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_drv_data *drv_data = slot->host->drv_data; u32 cmdr; cmd->error = -EINPROGRESS; @@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr |= SDMMC_CMD_DAT_WR; } - if (slot->host->drv_data->prepare_command) - slot->host->drv_data->prepare_command(slot->host, &cmdr); + if (drv_data && drv_data->prepare_command) + drv_data->prepare_command(slot->host, &cmdr); return cmdr; } @@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host) return 0; } -static struct dw_mci_dma_ops dw_mci_idmac_ops = { +static const struct dw_mci_dma_ops dw_mci_idmac_ops = { .init = dw_mci_idmac_init, .start = dw_mci_idmac_start_dma, .stop = dw_mci_idmac_stop_dma, @@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct dw_mci_slot *slot = mmc_priv(mmc); + struct dw_mci_drv_data *drv_data = slot->host->drv_data; u32 regs; /* set default 1 bit mode */ @@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) slot->clock = ios->clock; } - if (slot->host->drv_data->set_ios) - slot->host->drv_data->set_ios(slot->host, ios); + if (drv_data && drv_data->set_ios) + drv_data->set_ios(slot->host, ios); switch (ios->power_mode) { case MMC_POWER_UP: @@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) { struct mmc_host *mmc; struct dw_mci_slot *slot; + struct dw_mci_drv_data *drv_data = host->drv_data; int ctrl_id, ret; u8 bus_width; @@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) } else { ctrl_id = to_platform_device(host->dev)->id; } - if (host->drv_data && host->drv_data->caps) - mmc->caps |= host->drv_data->caps[ctrl_id]; + if (drv_data && drv_data->caps) + mmc->caps |= drv_data->caps[ctrl_id]; if (host->pdata->caps2) mmc->caps2 = host->pdata->caps2; @@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) else bus_width = 1; - if (host->drv_data->setup_bus) { + if (drv_data && drv_data->setup_bus) { struct device_node *slot_np; slot_np = dw_mci_of_find_slot_node(host->dev, slot->id); - ret = host->drv_data->setup_bus(host, slot_np, bus_width); + ret = drv_data->setup_bus(host, slot_np, bus_width); if (ret) goto err_setup_bus; } @@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host) /* Determine which DMA interface to use */ #ifdef CONFIG_MMC_DW_IDMAC host->dma_ops = &dw_mci_idmac_ops; - dev_info(&host->dev, "Using internal DMA controller.\n"); + dev_info(host->dev, "Using internal DMA controller.\n"); #endif if (!host->dma_ops) @@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) struct dw_mci_board *pdata; struct device *dev = host->dev; struct device_node *np = dev->of_node; + struct dw_mci_drv_data *drv_data = host->drv_data; int idx, ret; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); @@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); - if (host->drv_data->parse_dt) { - ret = host->drv_data->parse_dt(host); + if (drv_data && drv_data->parse_dt) { + ret = drv_data->parse_dt(host); if (ret) return ERR_PTR(ret); } @@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) int dw_mci_probe(struct dw_mci *host) { + struct dw_mci_drv_data *drv_data = host->drv_data; int width, i, ret = 0; u32 fifo_size; int init_slots = 0; @@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host) else host->bus_hz = clk_get_rate(host->ciu_clk); - if (host->drv_data->setup_clock) { - ret = host->drv_data->setup_clock(host); + if (drv_data && drv_data->setup_clock) { + ret = drv_data->setup_clock(host); if (ret) { dev_err(host->dev, "implementation specific clock setup failed\n"); @@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host) else host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; + /* + * Enable interrupts for command done, data over, data empty, card det, + * receive ready and error such as transmit, receive timeout, crc error + */ + mci_writel(host, RINTSTS, 0xFFFFFFFF); + mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | + SDMMC_INT_TXDR | SDMMC_INT_RXDR | + DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); + mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ + + dev_info(host->dev, "DW MMC controller at irq %d, " + "%d bit host data width, " + "%u deep fifo\n", + host->irq, width, fifo_size); + /* We need at least one slot to succeed */ for (i = 0; i < host->num_slots; i++) { ret = dw_mci_init_slot(host, i); @@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host) else host->data_offset = DATA_240A_OFFSET; - /* - * Enable interrupts for command done, data over, data empty, card det, - * receive ready and error such as transmit, receive timeout, crc error - */ - mci_writel(host, RINTSTS, 0xFFFFFFFF); - mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | - SDMMC_INT_TXDR | SDMMC_INT_RXDR | - DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); - mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ - - dev_info(host->dev, "DW MMC controller at irq %d, " - "%d bit host data width, " - "%u deep fifo\n", - host->irq, width, fifo_size); if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n"); diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index edc3e9baf0e7..5e39b312c7cc 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -33,6 +33,7 @@ #include <linux/amba/mmci.h> #include <linux/pm_runtime.h> #include <linux/types.h> +#include <linux/pinctrl/consumer.h> #include <asm/div64.h> #include <asm/io.h> @@ -654,9 +655,31 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) /* The ST Micro variants has a special bit to enable SDIO */ if (variant->sdio && host->mmc->card) - if (mmc_card_sdio(host->mmc->card)) + if (mmc_card_sdio(host->mmc->card)) { + /* + * The ST Micro variants has a special bit + * to enable SDIO. + */ + u32 clk; + datactrl |= MCI_ST_DPSM_SDIOEN; + /* + * The ST Micro variant for SDIO small write transfers + * needs to have clock H/W flow control disabled, + * otherwise the transfer will not start. The threshold + * depends on the rate of MCLK. + */ + if (data->flags & MMC_DATA_WRITE && + (host->size < 8 || + (host->size <= 8 && host->mclk > 50000000))) + clk = host->clk_reg & ~variant->clkreg_enable; + else + clk = host->clk_reg | variant->clkreg_enable; + + mmci_write_clkreg(host, clk); + } + /* * Attempt to use DMA operation mode, if this * should fail, fall back to PIO mode @@ -840,14 +863,14 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema if (unlikely(count & 0x3)) { if (count < 4) { unsigned char buf[4]; - readsl(base + MMCIFIFO, buf, 1); + ioread32_rep(base + MMCIFIFO, buf, 1); memcpy(ptr, buf, count); } else { - readsl(base + MMCIFIFO, ptr, count >> 2); + ioread32_rep(base + MMCIFIFO, ptr, count >> 2); count &= ~0x3; } } else { - readsl(base + MMCIFIFO, ptr, count >> 2); + ioread32_rep(base + MMCIFIFO, ptr, count >> 2); } ptr += count; @@ -877,22 +900,6 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem count = min(remain, maxcnt); /* - * The ST Micro variant for SDIO transfer sizes - * less then 8 bytes should have clock H/W flow - * control disabled. - */ - if (variant->sdio && - mmc_card_sdio(host->mmc->card)) { - u32 clk; - if (count < 8) - clk = host->clk_reg & ~variant->clkreg_enable; - else - clk = host->clk_reg | variant->clkreg_enable; - - mmci_write_clkreg(host, clk); - } - - /* * SDIO especially may want to send something that is * not divisible by 4 (as opposed to card sectors * etc), and the FIFO only accept full 32-bit writes. @@ -900,7 +907,7 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem * byte become a 32bit write, 7 bytes will be two * 32bit writes etc. */ - writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); + iowrite32_rep(base + MMCIFIFO, ptr, (count + 3) >> 2); ptr += count; remain -= count; @@ -1360,6 +1367,23 @@ static int __devinit mmci_probe(struct amba_device *dev, mmc->f_max = min(host->mclk, fmax); dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); + host->pinctrl = devm_pinctrl_get(&dev->dev); + if (IS_ERR(host->pinctrl)) { + ret = PTR_ERR(host->pinctrl); + goto clk_disable; + } + + host->pins_default = pinctrl_lookup_state(host->pinctrl, + PINCTRL_STATE_DEFAULT); + + /* enable pins to be muxed in and configured */ + if (!IS_ERR(host->pins_default)) { + ret = pinctrl_select_state(host->pinctrl, host->pins_default); + if (ret) + dev_warn(&dev->dev, "could not set default pins\n"); + } else + dev_warn(&dev->dev, "could not get default pinstate\n"); + #ifdef CONFIG_REGULATOR /* If we're using the regulator framework, try to fetch a regulator */ host->vcc = regulator_get(&dev->dev, "vmmc"); diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index d437ccf62d6b..d34d8c0add8e 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -195,6 +195,10 @@ struct mmci_host { unsigned int size; struct regulator *vcc; + /* pinctrl handles */ + struct pinctrl *pinctrl; + struct pinctrl_state *pins_default; + #ifdef CONFIG_DMA_ENGINE /* DMA stuff */ struct dma_chan *dma_current; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index 565c2e4fac75..6290b7f1ccfe 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver); MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver"); MODULE_AUTHOR("Sascha Hauer, Pengutronix"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:imx-mmc"); +MODULE_ALIAS("platform:mxc-mmc"); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 54bfd0cc106b..fedd258cc4ea 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -178,7 +178,8 @@ struct omap_hsmmc_host { static int omap_hsmmc_card_detect(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) static int omap_hsmmc_get_wp(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes write protect signal is active-high */ return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); @@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; /* NOTE: assumes card detect signal is active-low */ return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); @@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; disable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = dev_get_drvdata(dev); + struct omap_mmc_platform_data *mmc = host->pdata; enable_irq(mmc->slots[0].card_detect_irq); return 0; @@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev) clk_put(host->dbclk); } - mmc_free_host(host->mmc); + omap_hsmmc_gpio_free(host->pdata); iounmap(host->base); - omap_hsmmc_gpio_free(pdev->dev.platform_data); + mmc_free_host(host->mmc); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c index 90140eb03e36..8fd50a211037 100644 --- a/drivers/mmc/host/sdhci-dove.c +++ b/drivers/mmc/host/sdhci-dove.c @@ -19,6 +19,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/err.h> #include <linux/io.h> #include <linux/clk.h> #include <linux/err.h> @@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev) struct sdhci_dove_priv *priv; int ret; - ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); - if (ret) - goto sdhci_dove_register_fail; - priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "unable to allocate private data"); - ret = -ENOMEM; - goto sdhci_dove_allocate_fail; + return -ENOMEM; } + priv->clk = clk_get(&pdev->dev, NULL); + if (!IS_ERR(priv->clk)) + clk_prepare_enable(priv->clk); + + ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata); + if (ret) + goto sdhci_dove_register_fail; + host = platform_get_drvdata(pdev); pltfm_host = sdhci_priv(host); pltfm_host->priv = priv; - priv->clk = clk_get(&pdev->dev, NULL); - if (!IS_ERR(priv->clk)) - clk_prepare_enable(priv->clk); return 0; -sdhci_dove_allocate_fail: - sdhci_pltfm_unregister(pdev); sdhci_dove_register_fail: + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); + } return ret; } @@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_dove_priv *priv = pltfm_host->priv; - if (priv->clk) { - if (!IS_ERR(priv->clk)) { - clk_disable_unprepare(priv->clk); - clk_put(priv->clk); - } - devm_kfree(&pdev->dev, priv->clk); + sdhci_pltfm_unregister(pdev); + + if (!IS_ERR(priv->clk)) { + clk_disable_unprepare(priv->clk); + clk_put(priv->clk); } - return sdhci_pltfm_unregister(pdev); + return 0; } static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = { diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ae5fcbfa1eef..63d219f57cae 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host) } #endif +static void esdhc_of_platform_init(struct sdhci_host *host) +{ + u32 vvn; + + vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS); + vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT; + if (vvn == VENDOR_V_22) + host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23; +} + static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl, .read_w = esdhc_readw, @@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .enable_dma = esdhc_of_enable_dma, .get_max_clock = esdhc_of_get_max_clock, .get_min_clock = esdhc_of_get_min_clock, + .platform_init = esdhc_of_platform_init, #ifdef CONFIG_PM .platform_suspend = esdhc_of_suspend, .platform_resume = esdhc_of_resume, diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 4bb74b042a06..04936f353ced 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( return ERR_PTR(-ENODEV); } - if (pci_resource_len(pdev, bar) != 0x100) { + if (pci_resource_len(pdev, bar) < 0x100) { dev_err(&pdev->dev, "Invalid iomem size. You may " "experience problems.\n"); } diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 65551a9709cc..27164457f861 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, goto err_remap; } + /* + * Some platforms need to probe the controller to be able to + * determine which caps should be used. + */ + if (host->ops && host->ops->platform_init) + host->ops->platform_init(host); + platform_set_drvdata(pdev, host); return host; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2903949594c6..a54dd5d7a5f9 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) if (ourhost->cur_clk != best_src) { struct clk *clk = ourhost->clk_bus[best_src]; - clk_enable(clk); - clk_disable(ourhost->clk_bus[ourhost->cur_clk]); + clk_prepare_enable(clk); + clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); /* turn clock off to card before changing clock source */ writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); @@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } /* enable the local io clock and keep it running for the moment. */ - clk_enable(sc->clk_io); + clk_prepare_enable(sc->clk_io); for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) { struct clk *clk; @@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } #ifndef CONFIG_PM_RUNTIME - clk_enable(sc->clk_bus[sc->cur_clk]); + clk_prepare_enable(sc->clk_bus[sc->cur_clk]); #endif res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) sdhci_s3c_setup_card_detect_gpio(sc); #ifdef CONFIG_PM_RUNTIME - clk_disable(sc->clk_io); + if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) + clk_disable_unprepare(sc->clk_io); #endif return 0; err_req_regs: #ifndef CONFIG_PM_RUNTIME - clk_disable(sc->clk_bus[sc->cur_clk]); + clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); #endif for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { @@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) } err_no_busclks: - clk_disable(sc->clk_io); + clk_disable_unprepare(sc->clk_io); clk_put(sc->clk_io); err_io_clk: @@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) gpio_free(sc->ext_cd_gpio); #ifdef CONFIG_PM_RUNTIME - clk_enable(sc->clk_io); + if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL) + clk_prepare_enable(sc->clk_io); #endif sdhci_remove_host(host, 1); @@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); #ifndef CONFIG_PM_RUNTIME - clk_disable(sc->clk_bus[sc->cur_clk]); + clk_disable_unprepare(sc->clk_bus[sc->cur_clk]); #endif for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_put(sc->clk_bus[ptr]); } } - clk_disable(sc->clk_io); + clk_disable_unprepare(sc->clk_io); clk_put(sc->clk_io); if (pdev->dev.of_node) { @@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev) ret = sdhci_runtime_suspend_host(host); - clk_disable(ourhost->clk_bus[ourhost->cur_clk]); - clk_disable(busclk); + clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]); + clk_disable_unprepare(busclk); return ret; } @@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev) struct clk *busclk = ourhost->clk_io; int ret; - clk_enable(busclk); - clk_enable(ourhost->clk_bus[ourhost->cur_clk]); + clk_prepare_enable(busclk); + clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]); ret = sdhci_runtime_resume_host(host); return ret; } diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 7922adb42386..c7851c0aabce 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { - /* eMMC uses cmd21 while sd and sdio use cmd19 */ - tuning_opcode = mmc->card->type == MMC_TYPE_MMC ? - MMC_SEND_TUNING_BLOCK_HS200 : - MMC_SEND_TUNING_BLOCK; - spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, tuning_opcode); - spin_lock_irqsave(&host->lock, flags); - - /* Restore original mmc_request structure */ - host->mrq = mrq; + if (mmc->card) { + /* eMMC uses cmd21 but sd and sdio use cmd19 */ + tuning_opcode = + mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; + spin_unlock_irqrestore(&host->lock, flags); + sdhci_execute_tuning(mmc, tuning_opcode); + spin_lock_irqsave(&host->lock, flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; + } } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) @@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host) if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA)) mmc->caps |= MMC_CAP_4_BIT_DATA; + if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23) + mmc->caps &= ~MMC_CAP_CMD23; + if (caps[0] & SDHCI_CAN_DO_HISPD) mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; @@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host) /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); - if (IS_ERR(host->vqmmc)) { - pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc)); - host->vqmmc = NULL; + if (IS_ERR_OR_NULL(host->vqmmc)) { + if (PTR_ERR(host->vqmmc) < 0) { + pr_info("%s: no vqmmc regulator found\n", + mmc_hostname(mmc)); + host->vqmmc = NULL; + } } else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000)) regulator_enable(host->vqmmc); @@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host) ocr_avail = 0; host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); - if (IS_ERR(host->vmmc)) { - pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); - host->vmmc = NULL; + if (IS_ERR_OR_NULL(host->vmmc)) { + if (PTR_ERR(host->vmmc) < 0) { + pr_info("%s: no vmmc regulator found\n", + mmc_hostname(mmc)); + host->vmmc = NULL; + } } else regulator_enable(host->vmmc); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 97653ea8942b..71a4a7ed46c5 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -278,6 +278,7 @@ struct sdhci_ops { void (*hw_reset)(struct sdhci_host *host); void (*platform_suspend)(struct sdhci_host *host); void (*platform_resume)(struct sdhci_host *host); + void (*platform_init)(struct sdhci_host *host); }; #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 11d2bc3b51d5..d25bc97dc5c6 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); + clk_disable(host->hclk); mmc_free_host(host->mmc); pm_runtime_put_sync(&pdev->dev); - clk_disable(host->hclk); pm_runtime_disable(&pdev->dev); return 0; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e48..5a5cd2ace4a6 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 374c46dff7dd..ec794a72975d 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -1077,7 +1077,8 @@ EXPORT_SYMBOL_GPL(mtd_writev); * until the request succeeds or until the allocation size falls below * the system page size. This attempts to make sure it does not adversely * impact system performance, so when allocating more than one page, we - * ask the memory allocator to avoid re-trying. + * ask the memory allocator to avoid re-trying, swapping, writing back + * or performing I/O. * * Note, this function also makes sure that the allocated buffer is aligned to * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value. @@ -1091,7 +1092,8 @@ EXPORT_SYMBOL_GPL(mtd_writev); */ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size) { - gfp_t flags = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY; + gfp_t flags = __GFP_NOWARN | __GFP_WAIT | + __GFP_NORETRY | __GFP_NO_KSWAPD; size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); void *kbuf; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index ec6841d8e956..1a03b7f673ce 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, /* * Field definitions are in the following datasheets: * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) - * New style (6 byte ID): Samsung K9GAG08U0F (p.44) + * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) * Hynix MLC (6 byte ID): Hynix H27UBG8T2B (p.22) * - * Check for ID length, cell type, and Hynix/Samsung ID to decide what - * to do. + * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung + * ID to decide what to do. */ - if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) { + if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && + (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b0..d9127e2ed808 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 7153e0d27101..b3f41f200622 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int * flexonenand_set_boundary - Writes the SLC boundary * @param mtd - mtd info structure */ -int flexonenand_set_boundary(struct mtd_info *mtd, int die, +static int flexonenand_set_boundary(struct mtd_info *mtd, int die, int boundary, int lock) { struct onenand_chip *this = mtd->priv; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b2530b002125..5f5b69f37d2e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; netdev_features_t vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE; @@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond) dst_release_flag &= slave->dev->priv_flags; if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE; bond_dev->priv_flags = flags | dst_release_flag; diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index d04911d33b64..47618e505355 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index c65295dded39..6e5bdd1a31d9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata) SHMEM_EEE_ADV_STATUS_SHIFT); if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) { DP(BNX2X_MSG_ETHTOOL, - "Direct manipulation of EEE advertisment is not supported\n"); + "Direct manipulation of EEE advertisement is not supported\n"); return -EINVAL; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 6dd0dd076cc5..f6cfdc6cf20f 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -9941,7 +9941,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy, else rc = bnx2x_8483x_disable_eee(phy, params, vars); if (rc) { - DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n"); + DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n"); return rc; } } else { @@ -12987,7 +12987,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params, DP(NETIF_MSG_LINK, "Analyze TX Fault\n"); break; default: - DP(NETIF_MSG_LINK, "Analyze UNKOWN\n"); + DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n"); } DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up, old_status, status); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index bd1fd3d87c24..01611b33a93d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9545,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) */ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 32eec15fe4c2..730ae2cfa49e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox) { struct fw_bye_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, BYE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox) { struct fw_initialize_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, INITIALIZE, WRITE); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); } @@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset) { struct fw_reset_cmd c; + memset(&c, 0, sizeof(c)); INIT_CMD(c, RESET, WRITE); c.val = htonl(reset); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); @@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size, HOSTPAGESIZEPF7(sge_hps)); t4_set_reg_field(adap, SGE_CONTROL, - INGPADBOUNDARY(INGPADBOUNDARY_MASK) | + INGPADBOUNDARY_MASK | EGRSTATUSPAGESIZE_MASK, INGPADBOUNDARY(fl_align_log - 5) | EGRSTATUSPAGESIZE(stat_len != 64)); @@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, { struct fw_vi_enable_cmd c; + memset(&c, 0, sizeof(c)); c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST | FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid)); c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c)); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1d03dcdd5e56..19ac096cb07b 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1353,8 +1353,11 @@ static int gfar_restore(struct device *dev) struct gfar_private *priv = dev_get_drvdata(dev); struct net_device *ndev = priv->ndev; - if (!netif_running(ndev)) + if (!netif_running(ndev)) { + netif_device_attach(ndev); + return 0; + } gfar_init_bds(ndev); init_registers(ndev); diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c index f8064df10cc4..60ac46f4ac08 100644 --- a/drivers/net/ethernet/jme.c +++ b/drivers/net/ethernet/jme.c @@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev) jme_clear_pm(jme); JME_NAPI_ENABLE(jme); - tasklet_enable(&jme->linkch_task); - tasklet_enable(&jme->txclean_task); - tasklet_hi_enable(&jme->rxclean_task); - tasklet_hi_enable(&jme->rxempty_task); + tasklet_init(&jme->linkch_task, jme_link_change_tasklet, + (unsigned long) jme); + tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet, + (unsigned long) jme); + tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet, + (unsigned long) jme); rc = jme_request_irq(jme); if (rc) @@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev) JME_NAPI_DISABLE(jme); - tasklet_disable(&jme->linkch_task); - tasklet_disable(&jme->txclean_task); - tasklet_disable(&jme->rxclean_task); - tasklet_disable(&jme->rxempty_task); + tasklet_kill(&jme->linkch_task); + tasklet_kill(&jme->txclean_task); + tasklet_kill(&jme->rxclean_task); + tasklet_kill(&jme->rxempty_task); jme_disable_rx_engine(jme); jme_disable_tx_engine(jme); @@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev, tasklet_init(&jme->pcc_task, jme_pcc_tasklet, (unsigned long) jme); - tasklet_init(&jme->linkch_task, - jme_link_change_tasklet, - (unsigned long) jme); - tasklet_init(&jme->txclean_task, - jme_tx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxclean_task, - jme_rx_clean_tasklet, - (unsigned long) jme); - tasklet_init(&jme->rxempty_task, - jme_rx_empty_tasklet, - (unsigned long) jme); - tasklet_disable_nosync(&jme->linkch_task); - tasklet_disable_nosync(&jme->txclean_task); - tasklet_disable_nosync(&jme->rxclean_task); - tasklet_disable_nosync(&jme->rxempty_task); jme->dpi.cur = PCC_P1; jme->reg_ghc = 0; diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 9b9c2ac5c4c2..d19a143aa5a8 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4026,7 +4026,7 @@ static void __devexit skge_remove(struct pci_dev *pdev) dev0 = hw->dev[0]; unregister_netdev(dev0); - tasklet_disable(&hw->phy_task); + tasklet_kill(&hw->phy_task); spin_lock_irq(&hw->hw_lock); hw->intr_mask = 0; diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index 318fee91c79d..69e01977a1dd 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev) /* Delay for receive task to stop scheduling itself. */ msleep(2000 / HZ); - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); + tasklet_kill(&hw_priv->rx_tasklet); + tasklet_kill(&hw_priv->tx_tasklet); free_irq(dev->irq, hw_priv->dev); transmit_cleanup(hw_priv, 0); @@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev) rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev); if (rc) return rc; - tasklet_enable(&hw_priv->rx_tasklet); - tasklet_enable(&hw_priv->tx_tasklet); + tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, + (unsigned long) hw_priv); + tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, + (unsigned long) hw_priv); hw->promiscuous = 0; hw->all_multi = 0; @@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev, spin_lock_init(&hw_priv->hwlock); mutex_init(&hw_priv->lock); - /* tasklet is enabled. */ - tasklet_init(&hw_priv->rx_tasklet, rx_proc_task, - (unsigned long) hw_priv); - tasklet_init(&hw_priv->tx_tasklet, tx_proc_task, - (unsigned long) hw_priv); - - /* tasklet_enable will decrement the atomic counter. */ - tasklet_disable(&hw_priv->rx_tasklet); - tasklet_disable(&hw_priv->tx_tasklet); - for (i = 0; i < TOTAL_PORT_NUM; i++) init_waitqueue_head(&hw_priv->counter[i].counter); diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 1c818254b7be..b01f83a044c4 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp) cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0))); cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4))); - cpw32_f(HiTxRingAddr, 0); - cpw32_f(HiTxRingAddr + 4, 0); - - ring_dma = cp->ring_dma; - cpw32_f(RxRingAddr, ring_dma & 0xffffffff); - cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); - - ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; - cpw32_f(TxRingAddr, ring_dma & 0xffffffff); - cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); - cp_start_hw(cp); cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */ @@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp) cpw8(Config5, cpr8(Config5) & PMEStatus); + cpw32_f(HiTxRingAddr, 0); + cpw32_f(HiTxRingAddr + 4, 0); + + ring_dma = cp->ring_dma; + cpw32_f(RxRingAddr, ring_dma & 0xffffffff); + cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16); + + ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE; + cpw32_f(TxRingAddr, ring_dma & 0xffffffff); + cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16); + cpw16(MultiIntr, 0); cpw8_f(Cfg9346, Cfg9346_Lock); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e7ff886e8047..927aa33d4349 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -3827,6 +3827,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: @@ -4519,6 +4521,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index fb9f6b38511f..edf5edb13140 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev) netif_start_queue(net_dev); /* Workaround for EDB */ - sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); + sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 62d1baf111ea..c53c0f4e2ce3 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev) static int __devinit smsc911x_init(struct net_device *dev) { struct smsc911x_data *pdata = netdev_priv(dev); - unsigned int byte_test; + unsigned int byte_test, mask; unsigned int to = 100; SMSC_TRACE(pdata, probe, "Driver Parameters:"); @@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev) /* * poll the READY bit in PMT_CTRL. Any other access to the device is * forbidden while this bit isn't set. Try for 100ms + * + * Note that this test is done before the WORD_SWAP register is + * programmed. So in some configurations the READY bit is at 16 before + * WORD_SWAP is written to. This issue is worked around by waiting + * until either bit 0 or bit 16 gets set in PMT_CTRL. + * + * SMSC has confirmed that checking bit 16 (marked as reserved in + * the datasheet) is fine since these bits "will either never be set + * or can only go high after READY does (so also indicate the device + * is ready)". */ - while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) + + mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_); + while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to) udelay(1000); + if (to == 0) { pr_err("Device not READY in 100ms aborting\n"); return -ENODEV; diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 4e9810013850..66e025ad5df1 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c @@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev) ingress_irq = rc; tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU); rc = request_irq(ingress_irq, tile_net_handle_ingress_irq, - 0, NULL, NULL); + 0, "tile_net", NULL); if (rc != 0) { netdev_err(dev, "request_irq failed: %d\n", rc); destroy_irq(ingress_irq); diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 0793299bd39e..a788501e978e 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -894,6 +894,8 @@ out: return IRQ_HANDLED; } +static void axienet_dma_err_handler(unsigned long data); + /** * axienet_open - Driver open routine. * @ndev: Pointer to net_device structure @@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev) phy_start(lp->phy_dev); } + /* Enable tasklets for Axi DMA error handling */ + tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, + (unsigned long) lp); + /* Enable interrupts for Axi DMA Tx */ ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev); if (ret) @@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev) ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev); if (ret) goto err_rx_irq; - /* Enable tasklets for Axi DMA error handling */ - tasklet_enable(&lp->dma_err_tasklet); + return 0; err_rx_irq: @@ -960,6 +965,7 @@ err_tx_irq: if (lp->phy_dev) phy_disconnect(lp->phy_dev); lp->phy_dev = NULL; + tasklet_kill(&lp->dma_err_tasklet); dev_err(lp->dev, "request_irq() failed\n"); return ret; } @@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev) axienet_setoptions(ndev, lp->options & ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN)); - tasklet_disable(&lp->dma_err_tasklet); + tasklet_kill(&lp->dma_err_tasklet); free_irq(lp->tx_irq, ndev); free_irq(lp->rx_irq, ndev); @@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op) goto err_iounmap_2; } - tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler, - (unsigned long) lp); - tasklet_disable(&lp->dma_err_tasklet); - return 0; err_iounmap_2: diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 98934bdf6acf..477d6729b17f 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -1102,10 +1102,12 @@ static int init_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 5039f08f5a5b..43e9ab4f4d7e 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index 6428fcbbdd4b..daec9b05d168 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -234,7 +234,6 @@ void free_mdio_bitbang(struct mii_bus *bus) struct mdiobb_ctrl *ctrl = bus->priv; module_put(ctrl->ops->owner); - mdiobus_unregister(bus); mdiobus_free(bus); } EXPORT_SYMBOL(free_mdio_bitbang); diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 899274f2f9b1..2ed1140df3e9 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev) { struct mdio_gpio_platform_data *pdata; struct mii_bus *new_bus; - int ret; + int ret, bus_id; - if (pdev->dev.of_node) + if (pdev->dev.of_node) { pdata = mdio_gpio_of_get_data(pdev); - else + bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio"); + } else { pdata = pdev->dev.platform_data; + bus_id = pdev->id; + } if (!pdata) return -ENODEV; - new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id); + new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id); if (!new_bus) return -ENODEV; diff --git a/drivers/net/team/team_mode_broadcast.c b/drivers/net/team/team_mode_broadcast.c index 9db0171e9366..c5db428e73fa 100644 --- a/drivers/net/team/team_mode_broadcast.c +++ b/drivers/net/team/team_mode_broadcast.c @@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) if (last) { skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { - ret = team_dev_queue_xmit(team, last, - skb2); + ret = !team_dev_queue_xmit(team, last, + skb2); if (!sum_ret) sum_ret = ret; } @@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb) } } if (last) { - ret = team_dev_queue_xmit(team, last, skb); + ret = !team_dev_queue_xmit(team, last, skb); if (!sum_ret) sum_ret = ret; } diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index c81e278629ff..08d55b6bf272 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -31,6 +31,7 @@ #include <linux/usb/cdc.h> #include <linux/usb/usbnet.h> #include <linux/gfp.h> +#include <linux/if_vlan.h> /* @@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf) /* no jumbogram (16K) support for now */ - dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN; + dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4cd582a4f625..74fab1a40156 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -540,10 +540,12 @@ advance: (ctx->ether_desc == NULL) || (ctx->control != intf)) goto error; - /* claim interfaces, if any */ - temp = usb_driver_claim_interface(driver, ctx->data, dev); - if (temp) - goto error; + /* claim data interface, if different from control */ + if (ctx->data != ctx->control) { + temp = usb_driver_claim_interface(driver, ctx->data, dev); + if (temp) + goto error; + } iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber; @@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) tasklet_kill(&ctx->bh); + /* handle devices with combined control and data interface */ + if (ctx->control == ctx->data) + ctx->data = NULL; + /* disconnect master --> disconnect slave */ if (intf == ctx->control && ctx->data) { usb_set_intfdata(ctx->data, NULL); @@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, + /* Huawei NCM devices disguised as vendor specific */ + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), + .driver_info = (unsigned long)&wwan_info, + }, + { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), + .driver_info = (unsigned long)&wwan_info, + }, + /* Generic CDC-NCM devices */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 7479a5761d0d..362cb8cfeb92 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) /* set the address, index & direction (read from PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; - addr = (phy_id << 11) | (idx << 6) | MII_READ_; + addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_; ret = smsc95xx_write_reg(dev, MII_ADDR, addr); check_warn_goto_done(ret, "Error writing MII_ADDR"); @@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, /* set the address, index & direction (write to PHY) */ phy_id &= dev->mii.phy_id_mask; idx &= dev->mii.reg_num_mask; - addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; + addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_; ret = smsc95xx_write_reg(dev, MII_ADDR, addr); check_warn_goto_done(ret, "Error writing MII_ADDR"); @@ -1344,6 +1344,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, } else { u32 csum_preamble = smsc95xx_calc_csum_preamble(skb); skb_push(skb, 4); + cpu_to_le32s(&csum_preamble); memcpy(skb->data, &csum_preamble, 4); } } diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index cb04f900cc46..edb81ed06950 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb, void usbnet_defer_kevent (struct usbnet *dev, int work) { set_bit (work, &dev->flags); - if (!schedule_work (&dev->kevent)) - netdev_err(dev->net, "kevent %d may have been dropped\n", work); - else + if (!schedule_work (&dev->kevent)) { + if (net_ratelimit()) + netdev_err(dev->net, "kevent %d may have been dropped\n", work); + } else { netdev_dbg(dev->net, "kevent %d scheduled\n", work); + } } EXPORT_SYMBOL_GPL(usbnet_defer_kevent); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 7b4adde93c01..8b5c61917076 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -1,5 +1,5 @@ /* - * VXLAN: Virtual eXtensiable Local Area Network + * VXLAN: Virtual eXtensible Local Area Network * * Copyright (c) 2012 Vyatta Inc. * @@ -50,8 +50,8 @@ #define VXLAN_N_VID (1u << 24) #define VXLAN_VID_MASK (VXLAN_N_VID - 1) -/* VLAN + IP header + UDP + VXLAN */ -#define VXLAN_HEADROOM (4 + 20 + 8 + 8) +/* IP header + UDP + VXLAN + Ethernet header */ +#define VXLAN_HEADROOM (20 + 8 + 8 + 14) #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ @@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, if (!tb[IFLA_MTU]) dev->mtu = lowerdev->mtu - VXLAN_HEADROOM; + + /* update header length based on lower device */ + dev->hard_header_len = lowerdev->hard_header_len + + VXLAN_HEADROOM; } if (data[IFLA_VXLAN_TOS]) diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 3f575afd8cfc..e9a3da588e95 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port) { int i; - if (!ports_open) - if (!(dma_pool = dma_pool_create(DRV_NAME, NULL, - POOL_ALLOC_SIZE, 32, 0))) + if (!ports_open) { + dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev, + POOL_ALLOC_SIZE, 32, 0); + if (!dma_pool) return -ENOMEM; + } if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL, &port->desc_tab_phys))) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8e1559aba495..1829b445d0b0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) switch (type) { case ATH9K_RESET_POWER_ON: ret = ath9k_hw_set_reset_power_on(ah); - if (!ret) + if (ret) ah->reset_power_on = true; break; case ATH9K_RESET_WARM: diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c index 192251adf986..282eedec675e 100644 --- a/drivers/net/wireless/b43legacy/pio.c +++ b/drivers/net/wireless/b43legacy/pio.c @@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue) { struct b43legacy_pio_txpacket *packet, *tmp_packet; - tasklet_disable(&queue->txtask); + tasklet_kill(&queue->txtask); list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) free_txpacket(packet, 0); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index a6f1e8166008..481345c23ded 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode) static void brcmf_wiphy_pno_params(struct wiphy *wiphy) { -#ifndef CONFIG_BRCMFISCAN +#ifndef CONFIG_BRCMISCAN /* scheduled scan settings */ wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT; wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT; diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index ff8162d4c454..2d9eee93c743 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); if (iwlagn_tx_skb(priv, control->sta, skb)) - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw, @@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw, vif_priv->ctx = ctx; ctx->vif = vif; + /* + * In SNIFFER device type, the firmware reports the FCS to + * the host, rather than snipping it off. Unfortunately, + * mac80211 doesn't (yet) provide a per-packet flag for + * this, so that we have to set the hardware flag based + * on the interfaces added. As the monitor interface can + * only be present by itself, and will be removed before + * other interfaces are added, this is safe. + */ + if (vif->type == NL80211_IFTYPE_MONITOR) + priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS; + else + priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; + err = iwl_setup_interface(priv, ctx); if (!err || reset) goto out; diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 7ff3f1430678..408132cf83c1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c @@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(priv->hw, skb); } static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 17c8e5d82681..bb69f8f90b3b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c @@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) dma_map_page(trans->dev, page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + rxb->page = NULL; + spin_lock_irqsave(&rxq->lock, flags); + list_add(&rxb->list, &rxq->rx_used); + spin_unlock_irqrestore(&rxq->lock, flags); + __free_pages(page, trans_pcie->rx_page_order); + return; + } /* dma address must be no more than 36 bits */ BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); /* and also 256 byte aligned! */ @@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, dma_map_page(trans->dev, rxb->page, 0, PAGE_SIZE << trans_pcie->rx_page_order, DMA_FROM_DEVICE); - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; + if (dma_mapping_error(trans->dev, rxb->page_dma)) { + /* + * free the page(s) as well to not break + * the invariant that the items on the used + * list have no page(s) + */ + __free_pages(rxb->page, trans_pcie->rx_page_order); + rxb->page = NULL; + list_add_tail(&rxb->list, &rxq->rx_used); + } else { + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } } else list_add_tail(&rxb->list, &rxq->rx_used); spin_unlock_irqrestore(&rxq->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 105e3af3c621..79a4ddc002d3 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u16 rd_ptr, wr_ptr; - int n_bd = trans_pcie->txq[txq_id].q.n_bd; if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { WARN_ONCE(1, "queue %d not used", txq_id); return; } - rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); - wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); - - WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", - txq_id, rd_ptr, wr_ptr); - iwl_txq_set_inactive(trans, txq_id); IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); } diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 8d465107f52b..ae9010ed58de 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index fc8a9bfa1248..82cf0fa2d9f6 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 9970c2b1b199..b7e6607e6b6d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index caa011008cd0..fc24eb9b3948 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev, /* Grant backend access to each skb fragment page. */ for (i = 0; i < frags; i++) { skb_frag_t *frag = skb_shinfo(skb)->frags + i; + struct page *page = skb_frag_page(frag); - tx->flags |= XEN_NETTXF_more_data; + len = skb_frag_size(frag); + offset = frag->page_offset; - id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs); - np->tx_skbs[id].skb = skb_get(skb); - tx = RING_GET_REQUEST(&np->tx, prod++); - tx->id = id; - ref = gnttab_claim_grant_reference(&np->gref_tx_head); - BUG_ON((signed short)ref < 0); + /* Data must not cross a page boundary. */ + BUG_ON(len + offset > PAGE_SIZE<<compound_order(page)); - mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag))); - gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id, - mfn, GNTMAP_readonly); + /* Skip unused frames from start of page */ + page += offset >> PAGE_SHIFT; + offset &= ~PAGE_MASK; - tx->gref = np->grant_tx_ref[id] = ref; - tx->offset = frag->page_offset; - tx->size = skb_frag_size(frag); - tx->flags = 0; + while (len > 0) { + unsigned long bytes; + + BUG_ON(offset >= PAGE_SIZE); + + bytes = PAGE_SIZE - offset; + if (bytes > len) + bytes = len; + + tx->flags |= XEN_NETTXF_more_data; + + id = get_id_from_freelist(&np->tx_skb_freelist, + np->tx_skbs); + np->tx_skbs[id].skb = skb_get(skb); + tx = RING_GET_REQUEST(&np->tx, prod++); + tx->id = id; + ref = gnttab_claim_grant_reference(&np->gref_tx_head); + BUG_ON((signed short)ref < 0); + + mfn = pfn_to_mfn(page_to_pfn(page)); + gnttab_grant_foreign_access_ref(ref, + np->xbdev->otherend_id, + mfn, GNTMAP_readonly); + + tx->gref = np->grant_tx_ref[id] = ref; + tx->offset = offset; + tx->size = bytes; + tx->flags = 0; + + offset += bytes; + len -= bytes; + + /* Next frame */ + if (offset == PAGE_SIZE && len) { + BUG_ON(!PageCompound(page)); + page++; + offset = 0; + } + } } np->tx.req_prod_pvt = prod; } +/* + * Count how many ring slots are required to send the frags of this + * skb. Each frag might be a compound page. + */ +static int xennet_count_skb_frag_slots(struct sk_buff *skb) +{ + int i, frags = skb_shinfo(skb)->nr_frags; + int pages = 0; + + for (i = 0; i < frags; i++) { + skb_frag_t *frag = skb_shinfo(skb)->frags + i; + unsigned long size = skb_frag_size(frag); + unsigned long offset = frag->page_offset; + + /* Skip unused frames from start of page */ + offset &= ~PAGE_MASK; + + pages += PFN_UP(offset + size); + } + + return pages; +} + static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned short id; @@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) grant_ref_t ref; unsigned long mfn; int notify; - int frags = skb_shinfo(skb)->nr_frags; + int slots; unsigned int offset = offset_in_page(data); unsigned int len = skb_headlen(skb); unsigned long flags; - frags += DIV_ROUND_UP(offset + len, PAGE_SIZE); - if (unlikely(frags > MAX_SKB_FRAGS + 1)) { - printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n", - frags); - dump_stack(); + slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) + + xennet_count_skb_frag_slots(skb); + if (unlikely(slots > MAX_SKB_FRAGS + 1)) { + net_alert_ratelimited( + "xennet: skb rides the rocket: %d slots\n", slots); goto drop; } spin_lock_irqsave(&np->tx_lock, flags); if (unlikely(!netif_carrier_ok(dev) || - (frags > 1 && !xennet_can_sg(dev)) || + (slots > 1 && !xennet_can_sg(dev)) || netif_needs_gso(skb, netif_skb_features(skb)))) { spin_unlock_irqrestore(&np->tx_lock, flags); goto drop; diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 97c440a8cd61..30ae18a03a9c 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work) cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue); + list_del(&cmd->queue); + mutex_unlock(&dev->cmd_lock); __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame, cmd->in_frame_len, cmd->cmd_complete, cmd->arg, cmd->flags); - list_del(&cmd->queue); kfree(cmd); } @@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } @@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } @@ -2078,8 +2077,12 @@ error: static int pn533_tm_send_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { + struct sk_buff *skb_out = arg; + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); + dev_kfree_skb(skb_out); + if (params_len < 0) { nfc_dev_err(&dev->interface->dev, "Error %d when sending data", @@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame, dev->in_maxlen, pn533_tm_send_complete, - NULL, GFP_KERNEL); + skb, GFP_KERNEL); if (rc) { nfc_dev_err(&dev->interface->dev, "Error %d when trying to send data", rc); diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 6241fd05bd41..a543746fb354 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), } else next = dev->bus_list.next; - /* Run device routines with the device locked */ - device_lock(&dev->dev); retval = cb(dev, userdata); - device_unlock(&dev->dev); if (retval) break; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 94c6e2aa03d6..6c94fc9489e7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev) struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_driver *drv = pci_dev->driver; + pm_runtime_resume(dev); + if (drv && drv->shutdown) drv->shutdown(pci_dev); pci_msi_shutdown(pci_dev); @@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev) * continue to do DMA */ pci_disable_device(pci_dev); - - /* - * Devices may be enabled to wake up by runtime PM, but they need not - * be supposed to wake up the system from its "power off" state (e.g. - * ACPI S5). Therefore disable wakeup for all devices that aren't - * supposed to wake up the system at this point. The state argument - * will be ignored by pci_enable_wake(). - */ - if (!device_may_wakeup(dev)) - pci_enable_wake(pci_dev, PCI_UNKNOWN, false); } #ifdef CONFIG_PM diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 02d107b15281..f39378d9da15 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) } struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static void -pci_config_pm_runtime_get(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - if (parent) - pm_runtime_get_sync(parent); - pm_runtime_get_noresume(dev); - /* - * pdev->current_state is set to PCI_D3cold during suspending, - * so wait until suspending completes - */ - pm_runtime_barrier(dev); - /* - * Only need to resume devices in D3cold, because config - * registers are still accessible for devices suspended but - * not in D3cold. - */ - if (pdev->current_state == PCI_D3cold) - pm_runtime_resume(dev); -} - -static void -pci_config_pm_runtime_put(struct pci_dev *pdev) -{ - struct device *dev = &pdev->dev; - struct device *parent = dev->parent; - - pm_runtime_put(dev); - if (parent) - pm_runtime_put_sync(parent); -} - static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 54858838f098..aabf64798bda 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(pci_dev_run_wake); +void pci_config_pm_runtime_get(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + if (parent) + pm_runtime_get_sync(parent); + pm_runtime_get_noresume(dev); + /* + * pdev->current_state is set to PCI_D3cold during suspending, + * so wait until suspending completes + */ + pm_runtime_barrier(dev); + /* + * Only need to resume devices in D3cold, because config + * registers are still accessible for devices suspended but + * not in D3cold. + */ + if (pdev->current_state == PCI_D3cold) + pm_runtime_resume(dev); +} + +void pci_config_pm_runtime_put(struct pci_dev *pdev) +{ + struct device *dev = &pdev->dev; + struct device *parent = dev->parent; + + pm_runtime_put(dev); + if (parent) + pm_runtime_put_sync(parent); +} + /** * pci_pm_init - Initialize PM functions of given PCI device * @dev: PCI device to handle. diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index bacbcba69cf3..fd92aab9904b 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev); extern int pci_finish_runtime_suspend(struct pci_dev *dev); extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); extern void pci_wakeup_bus(struct pci_bus *bus); +extern void pci_config_pm_runtime_get(struct pci_dev *dev); +extern void pci_config_pm_runtime_put(struct pci_dev *dev); extern void pci_pm_init(struct pci_dev *dev); extern void platform_pci_wakeup_init(struct pci_dev *dev); extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 06bad96af415..af4e31cd3a3b 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); dev->error_state = result_data->state; if (!dev->driver || @@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data) dev->driver ? "no AER-aware driver" : "no driver"); } - return 0; + goto out; } err_handler = dev->driver->err_handler; vote = err_handler->error_detected(dev, result_data->state); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->mmio_enabled) - return 0; + goto out; err_handler = dev->driver->err_handler; vote = err_handler->mmio_enabled(dev); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data) struct aer_broadcast_data *result_data; result_data = (struct aer_broadcast_data *) data; + device_lock(&dev->dev); if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->slot_reset) - return 0; + goto out; err_handler = dev->driver->err_handler; vote = err_handler->slot_reset(dev); result_data->result = merge_result(result_data->result, vote); +out: + device_unlock(&dev->dev); return 0; } @@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data) { const struct pci_error_handlers *err_handler; + device_lock(&dev->dev); dev->error_state = pci_channel_io_normal; if (!dev->driver || !dev->driver->err_handler || !dev->driver->err_handler->resume) - return 0; + goto out; err_handler = dev->driver->err_handler; err_handler->resume(dev); +out: + device_unlock(&dev->dev); return 0; } diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index d03a7a39b2d8..ed129b414624 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev) } /* Hot-Plug Capable */ - if (cap_mask & PCIE_PORT_SERVICE_HP) { + if ((cap_mask & PCIE_PORT_SERVICE_HP) && + dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) { pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, ®32); if (reg32 & PCI_EXP_SLTCAP_HPC) { services |= PCIE_PORT_SERVICE_HP; diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index eb907a8faf2a..9b8505ccc56d 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp if (!access_ok(VERIFY_WRITE, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; pci_user_read_config_byte(dev, pos, &val); @@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; return nbytes; } @@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof if (!access_ok(VERIFY_READ, buf, cnt)) return -EINVAL; + pci_config_pm_runtime_get(dev); + if ((pos & 1) && cnt) { unsigned char val; __get_user(val, buf); @@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof cnt--; } + pci_config_pm_runtime_put(dev); + *ppos = pos; i_size_write(ino, dp->size); return nbytes; diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7bf914df6e91..aeecf0f72cad 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -178,12 +178,14 @@ config PINCTRL_COH901 ports of 8 GPIO pins each. config PINCTRL_SAMSUNG - bool "Samsung pinctrl driver" + bool + depends on OF && GPIOLIB select PINMUX select PINCONF config PINCTRL_EXYNOS4 bool "Pinctrl driver data for Exynos4 SoC" + depends on OF && GPIOLIB select PINCTRL_SAMSUNG config PINCTRL_MVEBU diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c index 5d4f44f462f0..b1fd6ee33c6c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear.c +++ b/drivers/pinctrl/spear/pinctrl-spear.c @@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, else temp = ~muxreg->val; - val |= temp; + val |= muxreg->mask & temp; pmx_writel(pmx, val, muxreg->reg); } } diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c index d6cca8c81b92..0436fc7895d6 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1310.c +++ b/drivers/pinctrl/spear/pinctrl-spear1310.c @@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = { }; /* registers */ -#define PERIP_CFG 0x32C - #define MCIF_SEL_SHIFT 3 +#define PERIP_CFG 0x3B0 + #define MCIF_SEL_SHIFT 5 #define MCIF_SEL_SD (0x1 << MCIF_SEL_SHIFT) #define MCIF_SEL_CF (0x2 << MCIF_SEL_SHIFT) #define MCIF_SEL_XD (0x3 << MCIF_SEL_SHIFT) @@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = { #define PMX_SSP0_CS0_MASK (1 << 29) #define PMX_SSP0_CS1_2_MASK (1 << 30) +#define PAD_DIRECTION_SEL_0 0x65C +#define PAD_DIRECTION_SEL_1 0x660 +#define PAD_DIRECTION_SEL_2 0x664 + /* combined macros */ #define PMX_GMII_MASK (PMX_GMIICLK_MASK | \ PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK | \ @@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2C0_MASK, .val = PMX_I2C0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2C0_MASK, + .val = PMX_I2C0_MASK, }, }; @@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SSP0_MASK, .val = PMX_SSP0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SSP0_MASK, + .val = PMX_SSP0_MASK, }, }; @@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_SSP0_CS0_MASK, .val = PMX_SSP0_CS0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_SSP0_CS0_MASK, + .val = PMX_SSP0_CS0_MASK, }, }; @@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_SSP0_CS1_2_MASK, .val = PMX_SSP0_CS1_2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_SSP0_CS1_2_MASK, + .val = PMX_SSP0_CS1_2_MASK, }, }; @@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK, .val = PMX_I2S0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK, + .val = PMX_I2S0_MASK, }, }; @@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_I2S1_MASK, .val = PMX_I2S1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_I2S1_MASK, + .val = PMX_I2S1_MASK, }, }; @@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = PMX_CLCD1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_CLCD2_MASK, .val = PMX_CLCD2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_CLCD2_MASK, + .val = PMX_CLCD2_MASK, }, }; @@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = { .nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux), }; -static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" }; +static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" }; static struct spear_function clcd_function = { .name = "clcd", .groups = clcd_grps, @@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_EGPIO_1_GRP_MASK, .val = PMX_EGPIO_1_GRP_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_EGPIO_0_GRP_MASK, + .val = PMX_EGPIO_0_GRP_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_EGPIO_1_GRP_MASK, + .val = PMX_EGPIO_1_GRP_MASK, }, }; @@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SMI_MASK, .val = PMX_SMI_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, }, }; @@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, + .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK, }, }; @@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_GMII_MASK, .val = PMX_GMII_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_GMII_MASK, + .val = PMX_GMII_MASK, }, }; @@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_RGMII_REG2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_RGMII_REG0_MASK, + .val = PMX_RGMII_REG0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_RGMII_REG1_MASK, + .val = PMX_RGMII_REG1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_RGMII_REG2_MASK, + .val = PMX_RGMII_REG2_MASK, }, }; @@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_SMII_0_1_2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_SMII_0_1_2_MASK, + .val = PMX_SMII_0_1_2_MASK, }, }; @@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NFCE2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NFCE2_MASK, + .val = PMX_NFCE2_MASK, }, }; @@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND8BIT_1_MASK, .val = PMX_NAND8BIT_1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_NAND8BIT_0_MASK, + .val = PMX_NAND8BIT_0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND8BIT_1_MASK, + .val = PMX_NAND8BIT_1_MASK, }, }; @@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND16BIT_1_MASK, .val = PMX_NAND16BIT_1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND16BIT_1_MASK, + .val = PMX_NAND16BIT_1_MASK, }, }; @@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NAND_4CHIPS_MASK, .val = PMX_NAND_4CHIPS_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NAND_4CHIPS_MASK, + .val = PMX_NAND_4CHIPS_MASK, }, }; @@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL68_MASK, .val = PMX_KBD_ROWCOL68_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL68_MASK, + .val = PMX_KBD_ROWCOL68_MASK, }, }; @@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_UART0_MASK, .val = PMX_UART0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_UART0_MASK, + .val = PMX_UART0_MASK, }, }; @@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_UART0_MODEM_MASK, .val = PMX_UART0_MODEM_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_UART0_MODEM_MASK, + .val = PMX_UART0_MODEM_MASK, }, }; @@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT0_TMR0_MASK, .val = PMX_GPT0_TMR0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT0_TMR0_MASK, + .val = PMX_GPT0_TMR0_MASK, }, }; @@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT0_TMR1_MASK, .val = PMX_GPT0_TMR1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT0_TMR1_MASK, + .val = PMX_GPT0_TMR1_MASK, }, }; @@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT1_TMR0_MASK, .val = PMX_GPT1_TMR0_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT1_TMR0_MASK, + .val = PMX_GPT1_TMR0_MASK, }, }; @@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_GPT1_TMR1_MASK, .val = PMX_GPT1_TMR1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_GPT1_TMR1_MASK, + .val = PMX_GPT1_TMR1_MASK, }, }; @@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214, .reg = PAD_FUNCTION_EN_2, \ .mask = PMX_MCIFALL_2_MASK, \ .val = PMX_MCIFALL_2_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_0, \ + .mask = PMX_MCI_DATA8_15_MASK, \ + .val = PMX_MCI_DATA8_15_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_1, \ + .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \ + PMX_NFWPRT2_MASK, \ + .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \ + PMX_NFWPRT2_MASK, \ + }, { \ + .reg = PAD_DIRECTION_SEL_2, \ + .mask = PMX_MCIFALL_2_MASK, \ + .val = PMX_MCIFALL_2_MASK, \ } /* sdhci device */ @@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_TOUCH_XY_MASK, .val = PMX_TOUCH_XY_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_TOUCH_XY_MASK, + .val = PMX_TOUCH_XY_MASK, }, }; @@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2C0_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2C0_MASK, + .val = PMX_I2C0_MASK, }, }; @@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = { .mask = PMX_MCIDATA1_MASK | PMX_MCIDATA2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_MCIDATA1_MASK | + PMX_MCIDATA2_MASK, + .val = PMX_MCIDATA1_MASK | + PMX_MCIDATA2_MASK, }, }; @@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK, + .val = PMX_I2S0_MASK, }, }; @@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK, + .val = PMX_I2S0_MASK | PMX_CLCD1_MASK, }, }; @@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK, + .val = PMX_CLCD1_MASK, }, }; @@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_CLCD1_MASK | PMX_SMI_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_CLCD1_MASK | PMX_SMI_MASK, + .val = PMX_CLCD1_MASK | PMX_SMI_MASK, }, }; @@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, + .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK, }, }; @@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = { .reg = PAD_FUNCTION_EN_0, .mask = PMX_SMI_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_SMI_MASK, + .val = PMX_SMI_MASK, }, }; @@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCIDATA5_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_MCIDATA4_MASK, + .val = PMX_MCIDATA4_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIDATA5_MASK, + .val = PMX_MCIDATA5_MASK, }, }; @@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = { .mask = PMX_MCIDATA6_MASK | PMX_MCIDATA7_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIDATA6_MASK | + PMX_MCIDATA7_MASK, + .val = PMX_MCIDATA6_MASK | + PMX_MCIDATA7_MASK, }, }; @@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL25_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK, + .val = PMX_KBD_ROWCOL25_MASK, }, }; @@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = { .mask = PMX_MCIIORDRE_MASK | PMX_MCIIOWRWE_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIIORDRE_MASK | + PMX_MCIIOWRWE_MASK, + .val = PMX_MCIIORDRE_MASK | + PMX_MCIIOWRWE_MASK, }, }; @@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = { .mask = PMX_MCIRESETCF_MASK | PMX_MCICS0CE_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIRESETCF_MASK | + PMX_MCICS0CE_MASK, + .val = PMX_MCIRESETCF_MASK | + PMX_MCICS0CE_MASK, }, }; @@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_NFRSTPWDWN3_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_NFRSTPWDWN2_MASK, + .val = PMX_NFRSTPWDWN2_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_NFRSTPWDWN3_MASK, + .val = PMX_NFRSTPWDWN3_MASK, }, }; @@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, + .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK, }, }; @@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = { .reg = PAD_FUNCTION_EN_2, .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, + .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK, }, }; @@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = { .reg = PAD_FUNCTION_EN_1, .mask = PMX_KBD_ROWCOL25_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK, + .val = PMX_KBD_ROWCOL25_MASK, }, }; @@ -1763,29 +1997,64 @@ static struct spear_function can1_function = { .ngroups = ARRAY_SIZE(can1_grps), }; -/* Pad multiplexing for pci device */ -static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, +/* Pad multiplexing for (ras-ip) pci device */ +static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 }; -#define PCI_SATA_MUXREG \ - { \ - .reg = PAD_FUNCTION_EN_0, \ - .mask = PMX_MCI_DATA8_15_MASK, \ - .val = 0, \ - }, { \ - .reg = PAD_FUNCTION_EN_1, \ - .mask = PMX_PCI_REG1_MASK, \ - .val = 0, \ - }, { \ - .reg = PAD_FUNCTION_EN_2, \ - .mask = PMX_PCI_REG2_MASK, \ - .val = 0, \ - } -/* pad multiplexing for pcie0 device */ +static struct spear_muxreg pci_muxreg[] = { + { + .reg = PAD_FUNCTION_EN_0, + .mask = PMX_MCI_DATA8_15_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_1, + .mask = PMX_PCI_REG1_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_2, + .mask = PMX_PCI_REG2_MASK, + .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_0, + .mask = PMX_MCI_DATA8_15_MASK, + .val = PMX_MCI_DATA8_15_MASK, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_PCI_REG1_MASK, + .val = PMX_PCI_REG1_MASK, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_PCI_REG2_MASK, + .val = PMX_PCI_REG2_MASK, + }, +}; + +static struct spear_modemux pci_modemux[] = { + { + .muxregs = pci_muxreg, + .nmuxregs = ARRAY_SIZE(pci_muxreg), + }, +}; + +static struct spear_pingroup pci_pingroup = { + .name = "pci_grp", + .pins = pci_pins, + .npins = ARRAY_SIZE(pci_pins), + .modemuxs = pci_modemux, + .nmodemuxs = ARRAY_SIZE(pci_modemux), +}; + +static const char *const pci_grps[] = { "pci_grp" }; +static struct spear_function pci_function = { + .name = "pci", + .groups = pci_grps, + .ngroups = ARRAY_SIZE(pci_grps), +}; + +/* pad multiplexing for (fix-part) pcie0 device */ static struct spear_muxreg pcie0_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(0), @@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = { static struct spear_pingroup pcie0_pingroup = { .name = "pcie0_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie0_modemux, .nmodemuxs = ARRAY_SIZE(pcie0_modemux), }; -/* pad multiplexing for pcie1 device */ +/* pad multiplexing for (fix-part) pcie1 device */ static struct spear_muxreg pcie1_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(1), @@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = { static struct spear_pingroup pcie1_pingroup = { .name = "pcie1_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie1_modemux, .nmodemuxs = ARRAY_SIZE(pcie1_modemux), }; -/* pad multiplexing for pcie2 device */ +/* pad multiplexing for (fix-part) pcie2 device */ static struct spear_muxreg pcie2_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = PCIE_CFG_VAL(2), @@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = { static struct spear_pingroup pcie2_pingroup = { .name = "pcie2_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = pcie2_modemux, .nmodemuxs = ARRAY_SIZE(pcie2_modemux), }; -static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" }; -static struct spear_function pci_function = { - .name = "pci", - .groups = pci_grps, - .ngroups = ARRAY_SIZE(pci_grps), +static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" +}; +static struct spear_function pcie_function = { + .name = "pci_express", + .groups = pcie_grps, + .ngroups = ARRAY_SIZE(pcie_grps), }; /* pad multiplexing for sata0 device */ static struct spear_muxreg sata0_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(0), @@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = { static struct spear_pingroup sata0_pingroup = { .name = "sata0_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata0_modemux, .nmodemuxs = ARRAY_SIZE(sata0_modemux), }; /* pad multiplexing for sata1 device */ static struct spear_muxreg sata1_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(1), @@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = { static struct spear_pingroup sata1_pingroup = { .name = "sata1_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata1_modemux, .nmodemuxs = ARRAY_SIZE(sata1_modemux), }; /* pad multiplexing for sata2 device */ static struct spear_muxreg sata2_muxreg[] = { - PCI_SATA_MUXREG, { .reg = PCIE_SATA_CFG, .mask = SATA_CFG_VAL(2), @@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = { static struct spear_pingroup sata2_pingroup = { .name = "sata2_grp", - .pins = pci_sata_pins, - .npins = ARRAY_SIZE(pci_sata_pins), .modemuxs = sata2_modemux, .nmodemuxs = ARRAY_SIZE(sata2_modemux), }; @@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = { PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | PMX_NFCE2_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_1, + .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | + PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | + PMX_NFCE2_MASK, + .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK | + PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK | + PMX_NFCE2_MASK, }, }; @@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = { .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | PMX_MCICECF_MASK | PMX_MCICEXD_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | + PMX_MCICECF_MASK | PMX_MCICEXD_MASK, + .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK | + PMX_MCICECF_MASK | PMX_MCICEXD_MASK, }, }; @@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = { .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK | PMX_MCILEDS_MASK, .val = 0, + }, { + .reg = PAD_DIRECTION_SEL_2, + .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK + | PMX_MCILEDS_MASK, + .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK + | PMX_MCILEDS_MASK, }, }; @@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = { &can0_dis_sd_pingroup, &can1_dis_sd_pingroup, &can1_dis_kbd_pingroup, + &pci_pingroup, &pcie0_pingroup, &pcie1_pingroup, &pcie2_pingroup, @@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = { &can0_function, &can1_function, &pci_function, + &pcie_function, &sata_function, &ssp1_function, &gpt64_function, diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c index a0eb057e55bd..0606b8cf3f2c 100644 --- a/drivers/pinctrl/spear/pinctrl-spear1340.c +++ b/drivers/pinctrl/spear/pinctrl-spear1340.c @@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = { * Pad multiplexing for making all pads as gpio's. This is done to override the * values passed from bootloader and start from scratch. */ -static const unsigned pads_as_gpio_pins[] = { 251 }; +static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 }; static struct spear_muxreg pads_as_gpio_muxreg[] = { { .reg = PAD_FUNCTION_EN_1, @@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = { .nmodemuxs = ARRAY_SIZE(clcd_modemux), }; -static const char *const clcd_grps[] = { "clcd_grp" }; +/* Disable cld runtime to save panel damage */ +static struct spear_muxreg clcd_sleep_muxreg[] = { + { + .reg = PAD_SHARED_IP_EN_1, + .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK, + .val = 0, + }, { + .reg = PAD_FUNCTION_EN_5, + .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK, + .val = 0x0, + }, { + .reg = PAD_FUNCTION_EN_6, + .mask = CLCD_AND_ARM_TRACE_REG5_MASK, + .val = 0x0, + }, { + .reg = PAD_FUNCTION_EN_7, + .mask = CLCD_AND_ARM_TRACE_REG6_MASK, + .val = 0x0, + }, +}; + +static struct spear_modemux clcd_sleep_modemux[] = { + { + .muxregs = clcd_sleep_muxreg, + .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg), + }, +}; + +static struct spear_pingroup clcd_sleep_pingroup = { + .name = "clcd_sleep_grp", + .pins = clcd_pins, + .npins = ARRAY_SIZE(clcd_pins), + .modemuxs = clcd_sleep_modemux, + .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux), +}; + +static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" }; static struct spear_function clcd_function = { .name = "clcd", .groups = clcd_grps, @@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = { &sdhci_pingroup, &cf_pingroup, &xd_pingroup, + &clcd_sleep_pingroup, &clcd_pingroup, &arm_trace_pingroup, &miphy_dbg_pingroup, diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c index 020b1e0bdb3e..ca47b0e50780 100644 --- a/drivers/pinctrl/spear/pinctrl-spear320.c +++ b/drivers/pinctrl/spear/pinctrl-spear320.c @@ -2240,6 +2240,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = { .mask = PMX_SSP_CS_MASK, .val = 0, }, { + .reg = MODE_CONFIG_REG, + .mask = PMX_PWM_MASK, + .val = PMX_PWM_MASK, + }, { .reg = IP_SEL_PAD_30_39_REG, .mask = PMX_PL_34_MASK, .val = PMX_PWM2_PL_34_VAL, @@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = { }; /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */ -static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, +static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }; -static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 }; +static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 }; static struct spear_muxreg mii0_1_muxreg[] = { { .reg = PMX_CONFIG_REG, diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.h b/drivers/pinctrl/spear/pinctrl-spear3xx.h index 31f44347f17c..7860b36053c4 100644 --- a/drivers/pinctrl/spear/pinctrl-spear3xx.h +++ b/drivers/pinctrl/spear/pinctrl-spear3xx.h @@ -15,6 +15,7 @@ #include "pinctrl-spear.h" /* pad mux declarations */ +#define PMX_PWM_MASK (1 << 16) #define PMX_FIRDA_MASK (1 << 14) #define PMX_I2C_MASK (1 << 13) #define PMX_SSP_CS_MASK (1 << 12) diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index c17ae22567e0..0c6fcb461faf 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); /** * rio_map_inb_region -- Map inbound memory region. * @mport: Master port. - * @lstart: physical address of memory region to be mapped + * @local: physical address of memory region to be mapped * @rbase: RIO base address assigned to this window * @size: Size of the memory region * @rflags: Flags for mapping. diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 5c4829cba6a6..e872c8be080e 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); -/** - * regulator_put - "free" the regulator source - * @regulator: regulator source - * - * Note: drivers must ensure that all regulator_enable calls made on this - * regulator source are balanced by regulator_disable calls prior to calling - * this function. - */ -void regulator_put(struct regulator *regulator) +/* Locks held by regulator_put() */ +static void _regulator_put(struct regulator *regulator) { struct regulator_dev *rdev; if (regulator == NULL || IS_ERR(regulator)) return; - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; debugfs_remove_recursive(regulator->debugfs); @@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator) rdev->exclusive = 0; module_put(rdev->owner); +} + +/** + * regulator_put - "free" the regulator source + * @regulator: regulator source + * + * Note: drivers must ensure that all regulator_enable calls made on this + * regulator source are balanced by regulator_disable calls prior to calling + * this function. + */ +void regulator_put(struct regulator *regulator) +{ + mutex_lock(®ulator_list_mutex); + _regulator_put(regulator); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_put); @@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator, if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { ret = regulator_get_voltage(regulator); if (ret >= 0) - return (min_uV >= ret && ret <= max_uV); + return (min_uV <= ret && ret <= max_uV); else return ret; } @@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc, if (ret != 0) { rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", config->ena_gpio, ret); - goto clean; + goto wash; } rdev->ena_gpio = config->ena_gpio; @@ -3445,10 +3451,11 @@ unset_supplies: scrub: if (rdev->supply) - regulator_put(rdev->supply); + _regulator_put(rdev->supply); if (rdev->ena_gpio) gpio_free(rdev->ena_gpio); kfree(rdev->constraints); +wash: device_unregister(&rdev->dev); /* device core frees rdev */ rdev = ERR_PTR(ret); diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 9ffb6d5f17aa..4ed343e4eb41 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -44,7 +44,6 @@ #define RAW3215_NR_CCWS 3 #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ -#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ #define RAW3215_WORKING 4 /* set if a request is being worked on */ #define RAW3215_THROTTLED 8 /* set if reading is disabled */ #define RAW3215_STOPPED 16 /* set if writing is disabled */ @@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data) struct tty_struct *tty; tty = tty_port_tty_get(&raw->port); - tty_wakeup(tty); - tty_kref_put(tty); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); + } } /* @@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) DECLARE_WAITQUEUE(wait, current); unsigned long flags; - if (!(raw->port.flags & ASYNC_INITIALIZED) || - (raw->flags & RAW3215_FIXED)) + if (!(raw->port.flags & ASYNC_INITIALIZED)) return; /* Wait for outstanding requests, then free irq */ spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); @@ -926,8 +926,6 @@ static int __init con3215_init(void) dev_set_drvdata(&cdev->dev, raw); cdev->handler = raw3215_irq; - raw->flags |= RAW3215_FIXED; - /* Request the console irq */ if (raw3215_startup(raw) != 0) { raw3215_free_info(raw); diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 33bb4d891e16..4af3dfe70ef5 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *); extern void css_reiterate_subchannels(void); void css_update_ssd_info(struct subchannel *sch); -#define __MAX_SUBCHANNEL 65535 -#define __MAX_SSID 3 - struct channel_subsystem { u8 cssid; int valid; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fc916f5d7314..fd3143c291c6 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) } if (device_is_disconnected(cdev)) return IO_SCH_REPROBE; - if (cdev->online) + if (cdev->online && !cdev->private->flags.resuming) return IO_SCH_VERIFY; if (cdev->private->state == DEV_STATE_NOT_OPER) return IO_SCH_UNREG_ATTACH; @@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) rc = 0; goto out_unlock; case IO_SCH_VERIFY: - if (cdev->private->flags.resuming == 1) { - if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) { - ccw_device_set_notoper(cdev); - break; - } - } /* Trigger path verification. */ io_subchannel_verify(sch); rc = 0; diff --git a/drivers/s390/cio/idset.c b/drivers/s390/cio/idset.c index 199bc6791177..65d13e38803f 100644 --- a/drivers/s390/cio/idset.c +++ b/drivers/s390/cio/idset.c @@ -125,8 +125,7 @@ int idset_is_empty(struct idset *set) void idset_add_set(struct idset *to, struct idset *from) { - int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), - __BITOPS_WORDS(from->num_ssid * from->num_id)); + int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id); bitmap_or(to->bitmap, to->bitmap, from->bitmap, len); } diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3e25d3150456..4d6ba00d0047 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card, QETH_DBF_TEXT(SETUP, 2, "qipasscb"); cmd = (struct qeth_ipa_cmd *) data; + + switch (cmd->hdr.return_code) { + case IPA_RC_NOTSUPP: + case IPA_RC_L2_UNSUPPORTED_CMD: + QETH_DBF_TEXT(SETUP, 2, "ipaunsup"); + card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS; + card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS; + return -0; + default: + if (cmd->hdr.return_code) { + QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " + "rc=%d\n", + dev_name(&card->gdev->dev), + cmd->hdr.return_code); + return 0; + } + } + if (cmd->hdr.prot_version == QETH_PROT_IPV4) { card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled; - } else { + } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) { card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported; card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled; - } + } else + QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" + "\n", dev_name(&card->gdev->dev)); QETH_DBF_TEXT(SETUP, 2, "suppenbl"); QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported); QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index e67e0258aec5..fddb62654b6a 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card) QETH_DBF_TEXT(SETUP, 2, "doL2init"); QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card)); - rc = qeth_query_setadapterparms(card); - if (rc) { - QETH_DBF_MESSAGE(2, "could not query adapter parameters on " - "device %s: x%x\n", CARD_BUS_ID(card), rc); + if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) { + rc = qeth_query_setadapterparms(card); + if (rc) { + QETH_DBF_MESSAGE(2, "could not query adapter " + "parameters on device %s: x%x\n", + CARD_BUS_ID(card), rc); + } } if (card->info.type == QETH_CARD_TYPE_IQD || @@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) return -ERESTARTSYS; } rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]); - if (!rc) + if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND)) rc = qeth_l2_send_setmac(card, addr->sa_data); return rc ? -EINVAL : 0; } diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index c1bafc3f3fb1..9594ab62702b 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index b191dd549207..71fddbc60f18 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = { static const struct of_device_id qpti_match[]; static int __devinit qpti_sbus_probe(struct platform_device *op) { - const struct of_device_id *match; - struct scsi_host_template *tpnt; struct device_node *dp = op->dev.of_node; struct Scsi_Host *host; struct qlogicpti *qpti; static int nqptis; const char *fcode; - match = of_match_device(qpti_match, &op->dev); - if (!match) - return -EINVAL; - tpnt = match->data; - /* Sometimes Antares cards come up not completely * setup, and we get a report of a zero IRQ. */ if (op->archdata.irqs[0] == 0) return -ENODEV; - host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); + host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti)); if (!host) return -ENOMEM; @@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op) static const struct of_device_id qpti_match[] = { { .name = "ptisp", - .data = &qpti_template, }, { .name = "PTI,ptisp", - .data = &qpti_template, }, { .name = "QLGC,isp", - .data = &qpti_template, }, { .name = "SUNW,isp", - .data = &qpti_template, }, {}, }; diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 2936b447cae9..2c0d0ec8150b 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -55,6 +55,7 @@ #include <linux/cpu.h> #include <linux/mutex.h> #include <linux/async.h> +#include <asm/unaligned.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -1062,6 +1063,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, EXPORT_SYMBOL_GPL(scsi_get_vpd_page); /** + * scsi_report_opcode - Find out if a given command opcode is supported + * @sdev: scsi device to query + * @buffer: scratch buffer (must be at least 20 bytes long) + * @len: length of buffer + * @opcode: opcode for command to look up + * + * Uses the REPORT SUPPORTED OPERATION CODES to look up the given + * opcode. Returns 0 if RSOC fails or if the command opcode is + * unsupported. Returns 1 if the device claims to support the command. + */ +int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer, + unsigned int len, unsigned char opcode) +{ + unsigned char cmd[16]; + struct scsi_sense_hdr sshdr; + int result; + + if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3) + return 0; + + memset(cmd, 0, 16); + cmd[0] = MAINTENANCE_IN; + cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES; + cmd[2] = 1; /* One command format */ + cmd[3] = opcode; + put_unaligned_be32(len, &cmd[6]); + memset(buffer, 0, len); + + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, + &sshdr, 30 * HZ, 3, NULL); + + if (result && scsi_sense_valid(&sshdr) && + sshdr.sense_key == ILLEGAL_REQUEST && + (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00) + return 0; + + if ((buffer[1] & 3) == 3) /* Command supported */ + return 1; + + return 0; +} +EXPORT_SYMBOL(scsi_report_opcode); + +/** * scsi_device_get - get an additional reference to a scsi_device * @sdev: device to get a reference to * diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index da36a3a81a9e..9032e910bca3 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_FAIL; error = -EILSEQ; /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (cmd->cmnd[0] == UNMAP || - cmd->cmnd[0] == WRITE_SAME_16 || - cmd->cmnd[0] == WRITE_SAME)) { - description = "Discard failure"; + } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (cmd->cmnd[0]) { + case UNMAP: + description = "Discard failure"; + break; + case WRITE_SAME: + case WRITE_SAME_16: + if (cmd->cmnd[1] & 0x8) + description = "Discard failure"; + else + description = + "Write same failure"; + break; + default: + description = "Invalid command failure"; + break; + } action = ACTION_FAIL; error = -EREMOTEIO; } else diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 12f6fdfc1147..352bc77b7c88 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #endif static void sd_config_discard(struct scsi_disk *, unsigned int); +static void sd_config_write_same(struct scsi_disk *); static int sd_revalidate_disk(struct gendisk *); static void sd_unlock_native_capacity(struct gendisk *disk); static int sd_probe(struct device *); @@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev, return err ? err : count; } +static ssize_t +sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + + return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks); +} + +static ssize_t +sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct scsi_disk *sdkp = to_scsi_disk(dev); + struct scsi_device *sdp = sdkp->device; + unsigned long max; + int err; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (sdp->type != TYPE_DISK) + return -EINVAL; + + err = kstrtoul(buf, 10, &max); + + if (err) + return err; + + if (max == 0) + sdp->no_write_same = 1; + else if (max <= SD_MAX_WS16_BLOCKS) + sdkp->max_ws_blocks = max; + + sd_config_write_same(sdkp); + + return count; +} + static struct device_attribute sd_disk_attrs[] = { __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type, sd_store_cache_type), @@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = { __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL), __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode, sd_store_provisioning_mode), + __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR, + sd_show_write_same_blocks, sd_store_write_same_blocks), __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR, sd_show_max_medium_access_timeouts, sd_store_max_medium_access_timeouts), @@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) return; case SD_LBP_UNMAP: - max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_unmap_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS16: - max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS10: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); break; case SD_LBP_ZERO: - max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff); + max_blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); q->limits.discard_zeroes_data = 1; break; } @@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) } /** - * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device + * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device * @sdp: scsi device to operate one * @rq: Request to prepare * * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) { struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); - struct bio *bio = rq->bio; - sector_t sector = bio->bi_sector; - unsigned int nr_sectors = bio_sectors(bio); + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); unsigned int len; int ret; char *buf; struct page *page; - if (sdkp->device->sector_size == 4096) { - sector >>= 3; - nr_sectors >>= 3; - } - + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; rq->timeout = SD_TIMEOUT; memset(rq->cmd, 0, rq->cmd_len); @@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) blk_add_request_payload(rq, page, len); ret = scsi_setup_blk_pc_cmnd(sdp, rq); rq->buffer = page_address(page); + rq->__data_len = nr_bytes; out: if (ret != BLKPREP_OK) { @@ -669,6 +713,83 @@ out: return ret; } +static void sd_config_write_same(struct scsi_disk *sdkp) +{ + struct request_queue *q = sdkp->disk->queue; + unsigned int logical_block_size = sdkp->device->sector_size; + unsigned int blocks = 0; + + if (sdkp->device->no_write_same) { + sdkp->max_ws_blocks = 0; + goto out; + } + + /* Some devices can not handle block counts above 0xffff despite + * supporting WRITE SAME(16). Consequently we default to 64k + * blocks per I/O unless the device explicitly advertises a + * bigger limit. + */ + if (sdkp->max_ws_blocks == 0) + sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS; + + if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS) + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS16_BLOCKS); + else + blocks = min_not_zero(sdkp->max_ws_blocks, + (u32)SD_MAX_WS10_BLOCKS); + +out: + blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9)); +} + +/** + * sd_setup_write_same_cmnd - write the same data to multiple blocks + * @sdp: scsi device to operate one + * @rq: Request to prepare + * + * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on + * preference indicated by target device. + **/ +static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) +{ + struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); + struct bio *bio = rq->bio; + sector_t sector = blk_rq_pos(rq); + unsigned int nr_sectors = blk_rq_sectors(rq); + unsigned int nr_bytes = blk_rq_bytes(rq); + int ret; + + if (sdkp->device->no_write_same) + return BLKPREP_KILL; + + BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size); + + sector >>= ilog2(sdp->sector_size) - 9; + nr_sectors >>= ilog2(sdp->sector_size) - 9; + + rq->__data_len = sdp->sector_size; + rq->timeout = SD_WRITE_SAME_TIMEOUT; + memset(rq->cmd, 0, rq->cmd_len); + + if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) { + rq->cmd_len = 16; + rq->cmd[0] = WRITE_SAME_16; + put_unaligned_be64(sector, &rq->cmd[2]); + put_unaligned_be32(nr_sectors, &rq->cmd[10]); + } else { + rq->cmd_len = 10; + rq->cmd[0] = WRITE_SAME; + put_unaligned_be32(sector, &rq->cmd[2]); + put_unaligned_be16(nr_sectors, &rq->cmd[7]); + } + + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + rq->__data_len = nr_bytes; + + return ret; +} + static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) { rq->timeout = SD_FLUSH_TIMEOUT; @@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * block PC requests to make life easier. */ if (rq->cmd_flags & REQ_DISCARD) { - ret = scsi_setup_discard_cmnd(sdp, rq); + ret = sd_setup_discard_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_flags & REQ_WRITE_SAME) { + ret = sd_setup_write_same_cmnd(sdp, rq); goto out; } else if (rq->cmd_flags & REQ_FLUSH) { ret = scsi_setup_flush_cmnd(sdp, rq); @@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt) unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); struct scsi_sense_hdr sshdr; struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); + struct request *req = SCpnt->request; int sense_valid = 0; int sense_deferred = 0; unsigned char op = SCpnt->cmnd[0]; + unsigned char unmap = SCpnt->cmnd[1] & 8; - if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result) - scsi_set_resid(SCpnt, 0); + if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) { + if (!result) { + good_bytes = blk_rq_bytes(req); + scsi_set_resid(SCpnt, 0); + } else { + good_bytes = 0; + scsi_set_resid(SCpnt, blk_rq_bytes(req)); + } + } if (result) { sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr); @@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt) if (sshdr.asc == 0x10) /* DIX: Host detected corruption */ good_bytes = sd_completed_bytes(SCpnt); /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ - if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) && - (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME)) - sd_config_discard(sdkp, SD_LBP_DISABLE); + if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { + switch (op) { + case UNMAP: + sd_config_discard(sdkp, SD_LBP_DISABLE); + break; + case WRITE_SAME_16: + case WRITE_SAME: + if (unmap) + sd_config_discard(sdkp, SD_LBP_DISABLE); + else { + sdkp->device->no_write_same = 1; + sd_config_write_same(sdkp); + + good_bytes = 0; + req->__data_len = blk_rq_bytes(req); + req->cmd_flags |= REQ_QUIET; + } + } + } break; default: break; @@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) if (buffer[3] == 0x3c) { unsigned int lba_count, desc_count; - sdkp->max_ws_blocks = - (u32) min_not_zero(get_unaligned_be64(&buffer[36]), - (u64)0xffffffff); + sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]); if (!sdkp->lbpme) goto out; @@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp) kfree(buffer); } +static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) +{ + if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE, + WRITE_SAME_16)) + sdkp->ws16 = 1; +} + static int sd_try_extended_inquiry(struct scsi_device *sdp) { /* @@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); + sd_read_write_same(sdkp, buffer); } sdkp->first_scan = 0; @@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk) blk_queue_flush(sdkp->disk->queue, flush); set_capacity(disk, sdkp->capacity); + sd_config_write_same(sdkp); kfree(buffer); out: diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 47c52a6d733c..74a1e4ca5401 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -14,6 +14,7 @@ #define SD_TIMEOUT (30 * HZ) #define SD_MOD_TIMEOUT (75 * HZ) #define SD_FLUSH_TIMEOUT (60 * HZ) +#define SD_WRITE_SAME_TIMEOUT (120 * HZ) /* * Number of allowed retries @@ -39,6 +40,11 @@ enum { }; enum { + SD_MAX_WS10_BLOCKS = 0xffff, + SD_MAX_WS16_BLOCKS = 0x7fffff, +}; + +enum { SD_LBP_FULL = 0, /* Full logical block provisioning */ SD_LBP_UNMAP, /* Use UNMAP command */ SD_LBP_WS16, /* Use WRITE SAME(16) with UNMAP bit */ @@ -77,6 +83,7 @@ struct scsi_disk { unsigned lbpws : 1; unsigned lbpws10 : 1; unsigned lbpvpd : 1; + unsigned ws16 : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) diff --git a/drivers/staging/android/android_alarm.h b/drivers/staging/android/android_alarm.h index f2ffd963f1c3..d0cafd637199 100644 --- a/drivers/staging/android/android_alarm.h +++ b/drivers/staging/android/android_alarm.h @@ -51,12 +51,10 @@ enum android_alarm_return_flags { #define ANDROID_ALARM_WAIT _IO('a', 1) #define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size) -#define ALARM_IOR(c, type, size) _IOR('a', (c) | ((type) << 4), size) - /* Set alarm */ #define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec) #define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec) -#define ANDROID_ALARM_GET_TIME(type) ALARM_IOR(4, type, struct timespec) +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec) #define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec) #define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0))) #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4) diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c index a5dec1ca1b82..13ee53bd0bf6 100644 --- a/drivers/tty/hvc/hvc_console.c +++ b/drivers/tty/hvc/hvc_console.c @@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; unsigned long flags; - int temp_open_count; if (!hp) return; @@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty) return; } - temp_open_count = hp->port.count; hp->port.count = 0; spin_unlock_irqrestore(&hp->port.lock, flags); tty_port_tty_set(&hp->port, NULL); @@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty) if (hp->ops->notifier_hangup) hp->ops->notifier_hangup(hp, hp->data); - - while(temp_open_count) { - --temp_open_count; - tty_port_put(&hp->port); - } } /* diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3d7e1ee2fa57..a6134c94a9fc 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -43,7 +43,6 @@ #include <asm/io.h> #include <asm/ioctls.h> -#include <asm/mach/serial_at91.h> #include <mach/board.h> #ifdef CONFIG_ARM @@ -1513,23 +1512,6 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, } } -/* - * Register board-specific modem-control line handlers. - */ -void __init atmel_register_uart_fns(struct atmel_port_fns *fns) -{ - if (fns->enable_ms) - atmel_pops.enable_ms = fns->enable_ms; - if (fns->get_mctrl) - atmel_pops.get_mctrl = fns->get_mctrl; - if (fns->set_mctrl) - atmel_pops.set_mctrl = fns->set_mctrl; - atmel_open_hook = fns->open; - atmel_close_hook = fns->close; - atmel_pops.pm = fns->pm; - atmel_pops.set_wake = fns->set_wake; -} - struct platform_device *atmel_default_console_device; /* the serial console device */ #ifdef CONFIG_SERIAL_ATMEL_CONSOLE diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 2bc28a59d385..1ab1d2c66de4 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi) static const struct spi_device_id max310x_id_table[] = { { "max3107", MAX310X_TYPE_MAX3107 }, { "max3108", MAX310X_TYPE_MAX3108 }, + { } }; MODULE_DEVICE_TABLE(spi, max310x_id_table); diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c index 2ca5959ec3fa..ecc1e16be623 100644 --- a/drivers/tty/serial/sa1100.c +++ b/drivers/tty/serial/sa1100.c @@ -29,6 +29,7 @@ #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> +#include <linux/platform_data/sa11x0-serial.h> #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> @@ -39,7 +40,6 @@ #include <asm/irq.h> #include <mach/hardware.h> #include <mach/irqs.h> -#include <asm/mach/serial_sa1100.h> /* We've been assigned a range on the "Low-density serial ports" major */ #define SERIAL_SA1100_MAJOR 204 diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index f87d7e8964bf..4e0d0c3734b3 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -539,25 +539,25 @@ static void insert_char(struct vc_data *vc, unsigned int nr) { unsigned short *p = (unsigned short *) vc->vc_pos; - scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x); + scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2); scr_memsetw(p, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (DO_UPDATE(vc)) do_update_region(vc, (unsigned long) p, - (vc->vc_cols - vc->vc_x) / 2 + 1); + vc->vc_cols - vc->vc_x); } static void delete_char(struct vc_data *vc, unsigned int nr) { unsigned short *p = (unsigned short *) vc->vc_pos; - scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr); + scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2); scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, nr * 2); vc->vc_need_wrap = 0; if (DO_UPDATE(vc)) do_update_region(vc, (unsigned long) p, - (vc->vc_cols - vc->vc_x) / 2); + vc->vc_cols - vc->vc_x); } static int softcursor_original; diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1e741bca0265..f034716190ff 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum); irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; + unsigned long flags; irqreturn_t rc; + /* IRQF_DISABLED doesn't work correctly with shared IRQs + * when the first handler doesn't use it. So let's just + * assume it's never used. + */ + local_irq_save(flags); + if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) rc = IRQ_NONE; else if (hcd->driver->irq(hcd) == IRQ_NONE) @@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) else rc = IRQ_HANDLED; + local_irq_restore(flags); return rc; } EXPORT_SYMBOL_GPL(usb_hcd_irq); @@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd, int retval; if (hcd->driver->irq) { + + /* IRQF_DISABLED doesn't work as advertised when used together + * with IRQF_SHARED. As usb_hcd_irq() will always disable + * interrupts we can remove it here. + */ + if (irqflags & IRQF_SHARED) + irqflags &= ~IRQF_DISABLED; + snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); retval = request_irq(irqnum, &usb_hcd_irq, irqflags, diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index e426ad626d74..4bfa78af379c 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -20,6 +20,7 @@ #include <linux/usb/ehci_def.h> #include <linux/delay.h> #include <linux/serial_core.h> +#include <linux/kconfig.h> #include <linux/kgdb.h> #include <linux/kthread.h> #include <asm/io.h> @@ -614,12 +615,6 @@ err: return -ENODEV; } -int dbgp_external_startup(struct usb_hcd *hcd) -{ - return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); -} -EXPORT_SYMBOL_GPL(dbgp_external_startup); - static int ehci_reset_port(int port) { u32 portsc; @@ -979,6 +974,7 @@ struct console early_dbgp_console = { .index = -1, }; +#if IS_ENABLED(CONFIG_USB_EHCI_HCD) int dbgp_reset_prep(struct usb_hcd *hcd) { int ret = xen_dbgp_reset_prep(hcd); @@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd) } EXPORT_SYMBOL_GPL(dbgp_reset_prep); +int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); +} +EXPORT_SYMBOL_GPL(dbgp_external_startup); +#endif /* USB_EHCI_HCD */ + #ifdef CONFIG_KGDB static char kgdbdbgp_buf[DBGP_MAX_PACKET]; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 8efbf08c3561..d4ca9f1f7f24 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -29,6 +29,7 @@ #include <linux/list.h> #include <linux/interrupt.h> #include <linux/mm.h> +#include <linux/platform_data/pxa2xx_udc.h> #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <linux/irq.h> @@ -59,9 +60,6 @@ #include <mach/lubbock.h> #endif -#include <asm/mach/udc_pxa2xx.h> - - /* * This driver handles the USB Device Controller (UDC) in Intel's PXA 25x * series processors. The UDC for the IXP 4xx series is very similar. diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 6458764994ef..4ec3c0d7a18b 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -20,6 +20,7 @@ #include <linux/ctype.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> +#include <linux/if_vlan.h> #include "u_ether.h" @@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) while (skb2) { if (status < 0 || ETH_HLEN > skb2->len - || skb2->len > ETH_FRAME_LEN) { + || skb2->len > VLAN_ETH_FRAME_LEN) { dev->net->stats.rx_errors++; dev->net->stats.rx_length_errors++; DBG(dev, "rx length %d\n", skb2->len); diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c index ca759652626b..aa0f328922df 100644 --- a/drivers/usb/host/ehci-ls1x.c +++ b/drivers/usb/host/ehci-ls1x.c @@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev) goto err_put_hcd; } - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (ret) goto err_put_hcd; diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c index 84201cd1a472..41e378f17c66 100644 --- a/drivers/usb/host/ohci-xls.c +++ b/drivers/usb/host/ohci-xls.c @@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver, goto err3; } - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (retval != 0) goto err4; return retval; diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index d0b87e7b4abf..b6b84dacc791 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = musb_readw(epio, MUSB_RXCOUNT); /* - * use mode 1 only if we expect data of at least ep packet_sz - * and have not yet received a short packet + * Enable Mode 1 on RX transfers only when short_not_ok flag + * is set. Currently short_not_ok flag is set only from + * file_storage and f_mass_storage drivers */ - if ((request->length - request->actual >= musb_ep->packet_sz) && - (fifo_count >= musb_ep->packet_sz)) + + if (request->short_not_ok && fifo_count == musb_ep->packet_sz) use_mode_1 = 1; else use_mode_1 = 0; @@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req) c = musb->dma_controller; channel = musb_ep->dma; + /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in + * mode 0 only. So we do not get endpoint interrupts due to DMA + * completion. We only get interrupts from DMA controller. + * + * We could operate in DMA mode 1 if we knew the size of the tranfer + * in advance. For mass storage class, request->length = what the host + * sends, so that'd work. But for pretty much everything else, + * request->length is routinely more than what the host sends. For + * most these gadgets, end of is signified either by a short packet, + * or filling the last byte of the buffer. (Sending extra data in + * that last pckate should trigger an overflow fault.) But in mode 1, + * we don't get DMA completion interrupt for short packets. + * + * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1), + * to get endpoint interrupt on every DMA req, but that didn't seem + * to work reliably. + * + * REVISIT an updated g_file_storage can set req->short_not_ok, which + * then becomes usable as a runtime "use mode 1" hint... + */ + /* Experimental: Mode1 works with mass storage use cases */ if (use_mode_1) { csr |= MUSB_RXCSR_AUTOCLEAR; diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index d62a91fedc22..0e62f504410e 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev) struct platform_device *musb; struct ux500_glue *glue; struct clk *clk; - + int musbid; int ret = -ENOMEM; glue = kzalloc(sizeof(*glue), GFP_KERNEL); diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index d8c8a42bff3e..6223062d5d1b 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE && REGULATOR_TWL4030 + depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 @@ -68,7 +68,7 @@ config TWL4030_USB config TWL6030_USB tristate "TWL6030 USB Transceiver Driver" - depends on TWL4030_CORE && OMAP_USB2 + depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL6030 diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 7179b0c5f814..cff8dd5b462d 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial) static int keyspan_port_probe(struct usb_serial_port *port) { struct usb_serial *serial = port->serial; - struct keyspan_port_private *s_priv; + struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; const struct keyspan_device_details *d_details; struct callbacks *cback; @@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port) if (!p_priv) return -ENOMEM; - s_priv = usb_get_serial_data(port->serial); p_priv->device_details = d_details; /* Setup values for the various callback routines */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5dee7d61241e..edc64bb6f457 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -158,6 +158,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 @@ -193,6 +194,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -283,6 +287,7 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 +#define ALCATEL_PRODUCT_X220_X500D 0x0017 #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -706,6 +711,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -728,6 +734,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -1157,6 +1165,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 61a73ad1a187..a3e9c095f0d8 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -455,9 +455,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port, struct usb_serial *serial = port->serial; struct urb *urb; - if (endpoint == -1) - return NULL; /* endpoint not needed */ - urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { dev_dbg(&serial->interface->dev, @@ -489,6 +486,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port) init_usb_anchor(&portdata->delayed); for (i = 0; i < N_IN_URB; i++) { + if (!port->bulk_in_size) + break; + buffer = (u8 *)__get_free_page(GFP_KERNEL); if (!buffer) goto bail_out_error; @@ -502,8 +502,8 @@ int usb_wwan_port_probe(struct usb_serial_port *port) } for (i = 0; i < N_OUT_URB; i++) { - if (port->bulk_out_endpointAddress == -1) - continue; + if (!port->bulk_out_size) + break; buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); if (!buffer) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a3d54366afcc..92f35abee92d 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev) /* Some devices don't handle VPD pages correctly */ sdev->skip_vpd_pages = 1; + /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */ + sdev->no_report_opcodes = 1; + + /* Do not attempt to use WRITE SAME */ + sdev->no_write_same = 1; + /* Some disks return the total number of blocks in response * to READ CAPACITY rather than the highest block number. * If this device makes that mistake, tell the sd driver. */ diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index d64ac3842884..bee92846cfab 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c @@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module) struct omap_dss_output *out; enum omap_dss_output_id id; - id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; + switch (module) { + case 0: + id = OMAP_DSS_OUTPUT_DSI1; + break; + case 1: + id = OMAP_DSS_OUTPUT_DSI2; + break; + default: + return NULL; + } out = omap_dss_get_output(id); - return out->pdev; + return out ? out->pdev : NULL; } static inline void dsi_write_reg(struct platform_device *dsidev, diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 2ab1c3e96553..5f6eea801b06 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c @@ -697,11 +697,15 @@ static int dss_get_clocks(void) dss.dss_clk = clk; - clk = clk_get(NULL, dss.feat->clk_name); - if (IS_ERR(clk)) { - DSSERR("Failed to get %s\n", dss.feat->clk_name); - r = PTR_ERR(clk); - goto err; + if (dss.feat->clk_name) { + clk = clk_get(NULL, dss.feat->clk_name); + if (IS_ERR(clk)) { + DSSERR("Failed to get %s\n", dss.feat->clk_name); + r = PTR_ERR(clk); + goto err; + } + } else { + clk = NULL; } dss.dpll4_m4_ck = clk; @@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev) if (cpu_is_omap24xx()) src = &omap24xx_dss_feats; - else if (cpu_is_omap34xx()) - src = &omap34xx_dss_feats; else if (cpu_is_omap3630()) src = &omap3630_dss_feats; + else if (cpu_is_omap34xx()) + src = &omap34xx_dss_feats; else if (cpu_is_omap44xx()) src = &omap44xx_dss_feats; else if (soc_is_omap54xx()) diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index a48a7dd75b33..8c9b8b3b7f77 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c @@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s) { mutex_lock(&hdmi.lock); - if (hdmi_runtime_get()) + if (hdmi_runtime_get()) { + mutex_unlock(&hdmi.lock); return; + } hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s); hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s); diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/omap2/omapfb/omapfb-ioctl.c index 606b89f12351..d630b26a005c 100644 --- a/drivers/video/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/omap2/omapfb/omapfb-ioctl.c @@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); - if (!display && !display->output && !display->output->manager) { + if (!display || !display->output || !display->output->manager) { r = -EINVAL; break; } diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index 1e8659ca27ef..809b0de59c09 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device); void unregister_virtio_device(struct virtio_device *dev) { + int index = dev->index; /* save for after device release */ + device_unregister(&dev->dev); - ida_simple_remove(&virtio_index_ida, dev->index); + ida_simple_remove(&virtio_index_ida, index); } EXPORT_SYMBOL_GPL(unregister_virtio_device); diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0e8637035457..74354708c6c4 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y) obj-y += manage.o balloon.o obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o endif +obj-$(CONFIG_X86) += fallback.o obj-y += grant-table.o features.o events.o obj-y += xenbus/ diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 912ac81b6dbf..0be4df39e953 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1395,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); + irq_enter(); #ifdef CONFIG_X86 exit_idle(); #endif - irq_enter(); __xen_evtchn_do_upcall(); diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c new file mode 100644 index 000000000000..0ef7c4d40f86 --- /dev/null +++ b/drivers/xen/fallback.c @@ -0,0 +1,80 @@ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/bug.h> +#include <linux/export.h> +#include <asm/hypervisor.h> +#include <asm/xen/hypercall.h> + +int xen_event_channel_op_compat(int cmd, void *arg) +{ + struct evtchn_op op; + int rc; + + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, event_channel_op_compat, &op); + + switch (cmd) { + case EVTCHNOP_close: + case EVTCHNOP_send: + case EVTCHNOP_bind_vcpu: + case EVTCHNOP_unmask: + /* no output */ + break; + +#define COPY_BACK(eop) \ + case EVTCHNOP_##eop: \ + memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \ + break + + COPY_BACK(bind_interdomain); + COPY_BACK(bind_virq); + COPY_BACK(bind_pirq); + COPY_BACK(status); + COPY_BACK(alloc_unbound); + COPY_BACK(bind_ipi); +#undef COPY_BACK + + default: + WARN_ON(rc != -ENOSYS); + break; + } + + return rc; +} +EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); + +int HYPERVISOR_physdev_op_compat(int cmd, void *arg) +{ + struct physdev_op op; + int rc; + + op.cmd = cmd; + memcpy(&op.u, arg, sizeof(op.u)); + rc = _hypercall1(int, physdev_op_compat, &op); + + switch (cmd) { + case PHYSDEVOP_IRQ_UNMASK_NOTIFY: + case PHYSDEVOP_set_iopl: + case PHYSDEVOP_set_iobitmap: + case PHYSDEVOP_apic_write: + /* no output */ + break; + +#define COPY_BACK(pop, fld) \ + case PHYSDEVOP_##pop: \ + memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \ + break + + COPY_BACK(irq_status_query, irq_status_query); + COPY_BACK(apic_read, apic_op); + COPY_BACK(ASSIGN_VECTOR, irq_op); +#undef COPY_BACK + + default: + WARN_ON(rc != -ENOSYS); + break; + } + + return rc; +} diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 8adb9cc267f9..71f5c459b088 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) down_write(&mm->mmap_sem); vma = find_vma(mm, m.addr); - ret = -EINVAL; if (!vma || vma->vm_ops != &privcmd_vm_ops || (m.addr != vma->vm_start) || ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) || !privcmd_enforce_singleshot_mapping(vma)) { up_write(&mm->mmap_sem); + ret = -EINVAL; goto out; } @@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) up_write(&mm->mmap_sem); - if (state.global_error && (version == 1)) { - /* Write back errors in second pass. */ - state.user_mfn = (xen_pfn_t *)m.arr; - state.err = err_array; - ret = traverse_pages(m.num, sizeof(xen_pfn_t), - &pagelist, mmap_return_errors_v1, &state); + if (version == 1) { + if (state.global_error) { + /* Write back errors in second pass. */ + state.user_mfn = (xen_pfn_t *)m.arr; + state.err = err_array; + ret = traverse_pages(m.num, sizeof(xen_pfn_t), + &pagelist, mmap_return_errors_v1, &state); + } else + ret = 0; + } else if (version == 2) { ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); if (ret) |