diff options
181 files changed, 1881 insertions, 1654 deletions
diff --git a/Documentation/filesystems/ntfs.txt b/Documentation/filesystems/ntfs.txt index 6ef8cf3bc9a..933bc66ccff 100644 --- a/Documentation/filesystems/ntfs.txt +++ b/Documentation/filesystems/ntfs.txt @@ -460,6 +460,8 @@ Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. 2.1.30: - Fix writev() (it kept writing the first segment over and over again instead of moving onto subsequent segments). + - Fix crash in ntfs_mft_record_alloc() when mapping the new extent mft + record failed. 2.1.29: - Fix a deadlock when mounting read-write. 2.1.28: diff --git a/MAINTAINERS b/MAINTAINERS index 9d12977b6ba..445537d46e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3139,6 +3139,12 @@ S: Maintained F: net/ieee802154/ F: drivers/ieee802154/ +IKANOS/ADI EAGLE ADSL USB DRIVER +M: Matthieu Castet <castet.matthieu@free.fr> +M: Stanislaw Gruszka <stf_xl@wp.pl> +S: Maintained +F: drivers/usb/atm/ueagle-atm.c + INTEGRITY MEASUREMENT ARCHITECTURE (IMA) M: Mimi Zohar <zohar@us.ibm.com> S: Supported @@ -6594,6 +6600,16 @@ S: Maintained F: drivers/char/virtio_console.c F: include/linux/virtio_console.h +VIRTIO CORE, NET AND BLOCK DRIVERS +M: Rusty Russell <rusty@rustcorp.com.au> +M: "Michael S. Tsirkin" <mst@redhat.com> +L: virtualization@lists.linux-foundation.org +S: Maintained +F: drivers/virtio/ +F: drivers/net/virtio_net.c +F: drivers/block/virtio_blk.c +F: include/linux/virtio_*.h + VIRTIO HOST (VHOST) M: "Michael S. Tsirkin" <mst@redhat.com> L: kvm@vger.kernel.org diff --git a/arch/arm/mach-omap1/include/mach/entry-macro.S b/arch/arm/mach-omap1/include/mach/entry-macro.S index c9be6d4d83e..bfb4fb1d738 100644 --- a/arch/arm/mach-omap1/include/mach/entry-macro.S +++ b/arch/arm/mach-omap1/include/mach/entry-macro.S @@ -14,19 +14,6 @@ #include <mach/irqs.h> #include <asm/hardware/gic.h> -/* - * We use __glue to avoid errors with multiple definitions of - * .globl omap_irq_flags as it's included from entry-armv.S but not - * from entry-common.S. - */ -#ifdef __glue - .pushsection .data - .globl omap_irq_flags -omap_irq_flags: - .word 0 - .popsection -#endif - .macro disable_fiq .endm diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index 47701584df3..731dd33bff5 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c @@ -57,6 +57,7 @@ struct omap_irq_bank { unsigned long wake_enable; }; +u32 omap_irq_flags; static unsigned int irq_bank_count; static struct omap_irq_bank *irq_banks; @@ -176,7 +177,6 @@ static struct irq_chip omap_irq_chip = { void __init omap_init_irq(void) { - extern unsigned int omap_irq_flags; int i, j; #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c index d2f15f5cfd3..34922b2d2e3 100644 --- a/arch/arm/mach-omap2/dma.c +++ b/arch/arm/mach-omap2/dma.c @@ -264,7 +264,7 @@ static int __init omap2_system_dma_init_dev(struct omap_hwmod *oh, void *unused) if (IS_ERR(od)) { pr_err("%s: Cant build omap_device for %s:%s.\n", __func__, name, oh->name); - return IS_ERR(od); + return PTR_ERR(od); } mem = platform_get_resource(&od->pdev, IORESOURCE_MEM, 0); diff --git a/arch/arm/mach-omap2/include/mach/entry-macro.S b/arch/arm/mach-omap2/include/mach/entry-macro.S index befa321c4c1..81985a665cb 100644 --- a/arch/arm/mach-omap2/include/mach/entry-macro.S +++ b/arch/arm/mach-omap2/include/mach/entry-macro.S @@ -38,20 +38,6 @@ */ #ifdef MULTI_OMAP2 - -/* - * We use __glue to avoid errors with multiple definitions of - * .globl omap_irq_base as it's included from entry-armv.S but not - * from entry-common.S. - */ -#ifdef __glue - .pushsection .data - .globl omap_irq_base -omap_irq_base: - .word 0 - .popsection -#endif - /* * Configure the interrupt base on the first interrupt. * See also omap_irq_base_init for setting omap_irq_base. diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index e66687b0b9d..c2032041d26 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -314,14 +314,13 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data) return omap_hwmod_set_postsetup_state(oh, *(u8 *)data); } +void __iomem *omap_irq_base; + /* * Initialize asm_irq_base for entry-macro.S */ static inline void omap_irq_base_init(void) { - extern void __iomem *omap_irq_base; - -#ifdef MULTI_OMAP2 if (cpu_is_omap24xx()) omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE); else if (cpu_is_omap34xx()) @@ -330,7 +329,6 @@ static inline void omap_irq_base_init(void) omap_irq_base = OMAP2_L4_IO_ADDRESS(OMAP44XX_GIC_CPU_BASE); else pr_err("Could not initialize omap_irq_base\n"); -#endif } void __init omap2_init_common_infrastructure(void) diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index df8d2f2872c..fae49d12bc7 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c @@ -160,7 +160,7 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, struct omap_mux *mux = NULL; struct omap_mux_entry *e; const char *mode_name; - int found = 0, found_mode, mode0_len = 0; + int found = 0, found_mode = 0, mode0_len = 0; struct list_head *muxmodes = &partition->muxmodes; mode_name = strchr(muxname, '.'); diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index bd066206e11..ad804880151 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c @@ -207,9 +207,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) spin_unlock_irqrestore(&bank->lvl_lock[port], flags); if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) - __set_irq_handler_unlocked(irq, handle_level_irq); + __set_irq_handler_unlocked(d->irq, handle_level_irq); else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - __set_irq_handler_unlocked(irq, handle_edge_irq); + __set_irq_handler_unlocked(d->irq, handle_edge_irq); return 0; } diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index d7723955dac..a217f68ba57 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h @@ -20,6 +20,8 @@ #ifndef __MACH_CLK_H #define __MACH_CLK_H +struct clk; + void tegra_periph_reset_deassert(struct clk *c); void tegra_periph_reset_assert(struct clk *c); diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h index 412f5c63e65..66cd3f4fc89 100644 --- a/arch/arm/mach-tegra/include/mach/clkdev.h +++ b/arch/arm/mach-tegra/include/mach/clkdev.h @@ -20,6 +20,8 @@ #ifndef __MACH_CLKDEV_H #define __MACH_CLKDEV_H +struct clk; + static inline int __clk_get(struct clk *clk) { return 1; diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index de7dfad6f76..17c74d21077 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c @@ -46,24 +46,24 @@ #define ICTLR_COP_IER_CLR 0x38 #define ICTLR_COP_IEP_CLASS 0x3c -static void (*gic_mask_irq)(struct irq_data *d); -static void (*gic_unmask_irq)(struct irq_data *d); +static void (*tegra_gic_mask_irq)(struct irq_data *d); +static void (*tegra_gic_unmask_irq)(struct irq_data *d); -#define irq_to_ictlr(irq) (((irq)-32) >> 5) +#define irq_to_ictlr(irq) (((irq) - 32) >> 5) static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); -#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100) +#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100) static void tegra_mask(struct irq_data *d) { void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); - gic_mask_irq(d); - writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_CLR); + tegra_gic_mask_irq(d); + writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR); } static void tegra_unmask(struct irq_data *d) { void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); - gic_unmask_irq(d); + tegra_gic_unmask_irq(d); writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET); } @@ -98,8 +98,8 @@ void __init tegra_init_irq(void) IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); gic = get_irq_chip(29); - gic_unmask_irq = gic->irq_unmask; - gic_mask_irq = gic->irq_mask; + tegra_gic_unmask_irq = gic->irq_unmask; + tegra_gic_mask_irq = gic->irq_mask; tegra_irq.irq_ack = gic->irq_ack; #ifdef CONFIG_SMP tegra_irq.irq_set_affinity = gic->irq_set_affinity; diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index ddc81a06edb..fd12d7ce7ff 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -241,21 +241,15 @@ void __init xen_build_dynamic_phys_to_machine(void) * As long as the mfn_list has enough entries to completely * fill a p2m page, pointing into the array is ok. But if * not the entries beyond the last pfn will be undefined. - * And guessing that the 'what-ever-there-is' does not take it - * too kindly when changing it to invalid markers, a new page - * is allocated, initialized and filled with the valid part. */ if (unlikely(pfn + P2M_PER_PAGE > max_pfn)) { unsigned long p2midx; - unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE); - p2m_init(p2m); - - for (p2midx = 0; pfn + p2midx < max_pfn; p2midx++) { - p2m[p2midx] = mfn_list[pfn + p2midx]; - } - p2m_top[topidx][mididx] = p2m; - } else - p2m_top[topidx][mididx] = &mfn_list[pfn]; + + p2midx = max_pfn % P2M_PER_PAGE; + for ( ; p2midx < P2M_PER_PAGE; p2midx++) + mfn_list[pfn + p2midx] = INVALID_P2M_ENTRY; + } + p2m_top[topidx][mididx] = &mfn_list[pfn]; } m2p_override_init(); diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index b5a7f928234..a8a66a50d44 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -179,8 +179,13 @@ char * __init xen_memory_setup(void) e820.nr_map = 0; xen_extra_mem_start = mem_end; for (i = 0; i < memmap.nr_entries; i++) { - unsigned long long end = map[i].addr + map[i].size; + unsigned long long end; + /* Guard against non-page aligned E820 entries. */ + if (map[i].type == E820_RAM) + map[i].size -= (map[i].size + map[i].addr) % PAGE_SIZE; + + end = map[i].addr + map[i].size; if (map[i].type == E820_RAM && end > mem_end) { /* RAM off the end - may be partially included */ u64 delta = min(map[i].size, end - mem_end); @@ -350,6 +355,7 @@ void __init xen_arch_setup(void) boot_cpu_data.hlt_works_ok = 1; #endif pm_idle = default_idle; + boot_option_idle_override = IDLE_HALT; fiddle_vdso(); } diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 328826381a2..b8d96ce37fc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -260,6 +260,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */ { PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */ { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */ + { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -379,6 +380,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ { PCI_DEVICE(0x1b4b, 0x9123), + .class = PCI_CLASS_STORAGE_SATA_AHCI, + .class_mask = 0xffffff, .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ /* Promise */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a31fe96f7de..d4e52e21485 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4138,6 +4138,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { * device and controller are SATA. */ { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, + { "PIONEER DVD-RW DVR-212D", "1.28", ATA_HORKAGE_NOSETXFER }, /* End Marker */ { } diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5defc74973d..600f6353ecf 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1099,9 +1099,9 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, struct request_queue *q = sdev->request_queue; void *buf; - /* set the min alignment and padding */ - blk_queue_update_dma_alignment(sdev->request_queue, - ATA_DMA_PAD_SZ - 1); + sdev->sector_size = ATA_SECT_SIZE; + + /* set DMA padding */ blk_queue_update_dma_pad(sdev->request_queue, ATA_DMA_PAD_SZ - 1); @@ -1115,13 +1115,25 @@ static int ata_scsi_dev_config(struct scsi_device *sdev, blk_queue_dma_drain(q, atapi_drain_needed, buf, ATAPI_MAX_DRAIN); } else { - /* ATA devices must be sector aligned */ sdev->sector_size = ata_id_logical_sector_size(dev->id); - blk_queue_update_dma_alignment(sdev->request_queue, - sdev->sector_size - 1); sdev->manage_start_stop = 1; } + /* + * ata_pio_sectors() expects buffer for each sector to not cross + * page boundary. Enforce it by requiring buffers to be sector + * aligned, which works iff sector_size is not larger than + * PAGE_SIZE. ATAPI devices also need the alignment as + * IDENTIFY_PACKET is executed as ATA_PROT_PIO. + */ + if (sdev->sector_size > PAGE_SIZE) + ata_dev_printk(dev, KERN_WARNING, + "sector_size=%u > PAGE_SIZE, PIO may malfunction\n", + sdev->sector_size); + + blk_queue_update_dma_alignment(sdev->request_queue, + sdev->sector_size - 1); + if (dev->flags & ATA_DFLAG_AN) set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events); diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index d7e57db36bc..538ec38ba99 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -25,7 +25,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt366" -#define DRV_VERSION "0.6.9" +#define DRV_VERSION "0.6.10" struct hpt_clock { u8 xfer_mode; @@ -160,8 +160,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, while (list[i] != NULL) { if (!strcmp(list[i], model_num)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); + pr_warning(DRV_NAME ": %s is not supported for %s.\n", + modestr, list[i]); return 1; } i++; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index efdd18bc866..4c5b5183225 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -24,7 +24,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.6.18" +#define DRV_VERSION "0.6.22" struct hpt_clock { u8 xfer_speed; @@ -229,8 +229,8 @@ static int hpt_dma_blacklisted(const struct ata_device *dev, char *modestr, while (list[i] != NULL) { if (!strcmp(list[i], model_num)) { - printk(KERN_WARNING DRV_NAME ": %s is not supported for %s.\n", - modestr, list[i]); + pr_warning(DRV_NAME ": %s is not supported for %s.\n", + modestr, list[i]); return 1; } i++; @@ -642,7 +642,6 @@ static struct ata_port_operations hpt372_port_ops = { static struct ata_port_operations hpt374_fn1_port_ops = { .inherits = &hpt372_port_ops, .cable_detect = hpt374_fn1_cable_detect, - .prereset = hpt37x_pre_reset, }; /** @@ -803,7 +802,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) .udma_mask = ATA_UDMA6, .port_ops = &hpt302_port_ops }; - /* HPT374 - UDMA100, function 1 uses different prereset method */ + /* HPT374 - UDMA100, function 1 uses different cable_detect method */ static const struct ata_port_info info_hpt374_fn0 = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, @@ -838,7 +837,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (rc) return rc; - if (dev->device == PCI_DEVICE_ID_TTI_HPT366) { + switch (dev->device) { + case PCI_DEVICE_ID_TTI_HPT366: /* May be a later chip in disguise. Check */ /* Older chips are in the HPT366 driver. Ignore them */ if (rev < 3) @@ -863,54 +863,50 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) chip_table = &hpt372; break; default: - printk(KERN_ERR "pata_hpt37x: Unknown HPT366 subtype, " + pr_err(DRV_NAME ": Unknown HPT366 subtype, " "please report (%d).\n", rev); return -ENODEV; } - } else { - switch (dev->device) { - case PCI_DEVICE_ID_TTI_HPT372: - /* 372N if rev >= 2 */ - if (rev >= 2) - return -ENODEV; - ppi[0] = &info_hpt372; - chip_table = &hpt372a; - break; - case PCI_DEVICE_ID_TTI_HPT302: - /* 302N if rev > 1 */ - if (rev > 1) - return -ENODEV; - ppi[0] = &info_hpt302; - /* Check this */ - chip_table = &hpt302; - break; - case PCI_DEVICE_ID_TTI_HPT371: - if (rev > 1) - return -ENODEV; - ppi[0] = &info_hpt302; - chip_table = &hpt371; - /* - * Single channel device, master is not present - * but the BIOS (or us for non x86) must mark it - * absent - */ - pci_read_config_byte(dev, 0x50, &mcr1); - mcr1 &= ~0x04; - pci_write_config_byte(dev, 0x50, mcr1); - break; - case PCI_DEVICE_ID_TTI_HPT374: - chip_table = &hpt374; - if (!(PCI_FUNC(dev->devfn) & 1)) - *ppi = &info_hpt374_fn0; - else - *ppi = &info_hpt374_fn1; - break; - default: - printk(KERN_ERR - "pata_hpt37x: PCI table is bogus, please report (%d).\n", - dev->device); - return -ENODEV; - } + break; + case PCI_DEVICE_ID_TTI_HPT372: + /* 372N if rev >= 2 */ + if (rev >= 2) + return -ENODEV; + ppi[0] = &info_hpt372; + chip_table = &hpt372a; + break; + case PCI_DEVICE_ID_TTI_HPT302: + /* 302N if rev > 1 */ + if (rev > 1) + return -ENODEV; + ppi[0] = &info_hpt302; + /* Check this */ + chip_table = &hpt302; + break; + case PCI_DEVICE_ID_TTI_HPT371: + if (rev > 1) + return -ENODEV; + ppi[0] = &info_hpt302; + chip_table = &hpt371; + /* + * Single channel device, master is not present but the BIOS + * (or us for non x86) must mark it absent + */ + pci_read_config_byte(dev, 0x50, &mcr1); + mcr1 &= ~0x04; + pci_write_config_byte(dev, 0x50, mcr1); + break; + case PCI_DEVICE_ID_TTI_HPT374: + chip_table = &hpt374; + if (!(PCI_FUNC(dev->devfn) & 1)) + *ppi = &info_hpt374_fn0; + else + *ppi = &info_hpt374_fn1; + break; + default: + pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n", + dev->device); + return -ENODEV; } /* Ok so this is a chip we support */ @@ -957,8 +953,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) u8 sr; u32 total = 0; - printk(KERN_WARNING - "pata_hpt37x: BIOS has not set timing clocks.\n"); + pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n"); /* This is the process the HPT371 BIOS is reported to use */ for (i = 0; i < 128; i++) { @@ -1014,7 +1009,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) (f_high << 16) | f_low | 0x100); } if (adjust == 8) { - printk(KERN_ERR "pata_hpt37x: DPLL did not stabilize!\n"); + pr_err(DRV_NAME ": DPLL did not stabilize!\n"); return -ENODEV; } if (dpll == 3) @@ -1022,8 +1017,8 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) else private_data = (void *)hpt37x_timings_50; - printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using %dMHz DPLL.\n", - MHz[clock_slot], MHz[dpll]); + pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n", + MHz[clock_slot], MHz[dpll]); } else { private_data = (void *)chip_table->clocks[clock_slot]; /* @@ -1036,8 +1031,9 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) ppi[0] = &info_hpt370_33; if (clock_slot < 2 && ppi[0] == &info_hpt370a) ppi[0] = &info_hpt370a_33; - printk(KERN_INFO "pata_hpt37x: %s using %dMHz bus clock.\n", - chip_table->name, MHz[clock_slot]); + + pr_info(DRV_NAME ": %s using %dMHz bus clock.\n", + chip_table->name, MHz[clock_slot]); } /* Now kick off ATA set up */ diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index d2239bbdb79..eca68caf5f4 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -25,7 +25,7 @@ #include <linux/libata.h> #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3.13" +#define DRV_VERSION "0.3.14" enum { HPT_PCI_FAST = (1 << 31), @@ -418,7 +418,7 @@ static int hpt3x2n_pci_clock(struct pci_dev *pdev) u16 sr; u32 total = 0; - printk(KERN_WARNING "pata_hpt3x2n: BIOS clock data not set.\n"); + pr_warning(DRV_NAME ": BIOS clock data not set.\n"); /* This is the process the HPT371 BIOS is reported to use */ for (i = 0; i < 128; i++) { @@ -528,8 +528,7 @@ hpt372n: ppi[0] = &info_hpt372n; break; default: - printk(KERN_ERR - "pata_hpt3x2n: PCI table is bogus please report (%d).\n", + pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n", dev->device); return -ENODEV; } @@ -579,12 +578,11 @@ hpt372n: pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low); } if (adjust == 8) { - printk(KERN_ERR "pata_hpt3x2n: DPLL did not stabilize!\n"); + pr_err(DRV_NAME ": DPLL did not stabilize!\n"); return -ENODEV; } - printk(KERN_INFO "pata_hpt37x: bus clock %dMHz, using 66MHz DPLL.\n", - pci_mhz); + pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz); /* * Set our private data up. We only need a few flags diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 8cc536e49a0..d7d8026cde9 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -610,7 +610,7 @@ static struct scsi_host_template mpc52xx_ata_sht = { }; static struct ata_port_operations mpc52xx_ata_port_ops = { - .inherits = &ata_sff_port_ops, + .inherits = &ata_bmdma_port_ops, .sff_dev_select = mpc52xx_ata_dev_select, .set_piomode = mpc52xx_ata_set_piomode, .set_dmamode = mpc52xx_ata_set_dmamode, diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 2aef5cd3acf..49e5e99917e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -6310,6 +6310,9 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) static bool apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; + /* Dell Precision M6300 * DCB entry 2: 02025312 00000010 * DCB entry 3: 02026312 00000020 @@ -6327,6 +6330,18 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) return false; } + /* GeForce3 Ti 200 + * + * DCB reports an LVDS output that should be TMDS: + * DCB entry 1: f2005014 ffffffff + */ + if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { + if (*conn == 0xf2005014 && *conf == 0xffffffff) { + fabricate_dcb_output(dcb, OUTPUT_TMDS, 1, 1, 1); + return false; + } + } + return true; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 01bffc4412d..9821fcacc3d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -848,9 +848,6 @@ extern void nv10_mem_put_tile_region(struct drm_device *dev, struct nouveau_fence *fence); extern const struct ttm_mem_type_manager_func nouveau_vram_manager; -/* nvc0_vram.c */ -extern const struct ttm_mem_type_manager_func nvc0_vram_manager; - /* nouveau_notifier.c */ extern int nouveau_notifier_init_channel(struct nouveau_channel *); extern void nouveau_notifier_takedown_channel(struct nouveau_channel *); diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 7ecc4adc1e4..8d9968e1cba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -265,8 +265,8 @@ nouveau_temp_probe_i2c(struct drm_device *dev) struct i2c_board_info info[] = { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, { I2C_BOARD_INFO("w83781d", 0x2d) }, - { I2C_BOARD_INFO("f75375", 0x2e) }, { I2C_BOARD_INFO("adt7473", 0x2e) }, + { I2C_BOARD_INFO("f75375", 0x2e) }, { I2C_BOARD_INFO("lm99", 0x4c) }, { } }; diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 2d7ea75a09d..37e21d2be95 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -256,6 +256,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo; int i, hdr = (dev_priv->chipset == 0x50) ? 0x200 : 0x20; unsigned long flags; @@ -265,6 +266,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) return; spin_lock_irqsave(&dev_priv->context_switch_lock, flags); + pfifo->reassign(dev, false); pgraph->fifo_access(dev, false); if (pgraph->channel(dev) == chan) @@ -275,6 +277,7 @@ nv50_graph_destroy_context(struct nouveau_channel *chan) dev_priv->engine.instmem.flush(dev); pgraph->fifo_access(dev, true); + pfifo->reassign(dev, true); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); nouveau_gpuobj_ref(NULL, &chan->ramin_grctx); diff --git a/drivers/gpu/drm/nouveau/nv50_vm.c b/drivers/gpu/drm/nouveau/nv50_vm.c index 38e523e1099..459ff08241e 100644 --- a/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/drivers/gpu/drm/nouveau/nv50_vm.c @@ -45,11 +45,6 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, } if (phys & 1) { - if (dev_priv->vram_sys_base) { - phys += dev_priv->vram_sys_base; - phys |= 0x30; - } - if (coverage <= 32 * 1024 * 1024) phys |= 0x60; else if (coverage <= 64 * 1024 * 1024) diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index e6ea7d83187..eb18a7e89f5 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -31,6 +31,7 @@ #include "nvc0_graph.h" static void nvc0_graph_isr(struct drm_device *); +static void nvc0_runk140_isr(struct drm_device *); static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); void @@ -281,6 +282,7 @@ nvc0_graph_destroy(struct drm_device *dev) return; nouveau_irq_unregister(dev, 12); + nouveau_irq_unregister(dev, 25); nouveau_gpuobj_ref(NULL, &priv->unk4188b8); nouveau_gpuobj_ref(NULL, &priv->unk4188b4); @@ -390,6 +392,7 @@ nvc0_graph_create(struct drm_device *dev) } nouveau_irq_register(dev, 12, nvc0_graph_isr); + nouveau_irq_register(dev, 25, nvc0_runk140_isr); NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ @@ -512,8 +515,8 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) nv_wr32(dev, TP_UNIT(gpc, tp, 0x224), 0xc0000000); nv_wr32(dev, TP_UNIT(gpc, tp, 0x48c), 0xc0000000); nv_wr32(dev, TP_UNIT(gpc, tp, 0x084), 0xc0000000); - nv_wr32(dev, TP_UNIT(gpc, tp, 0xe44), 0x001ffffe); - nv_wr32(dev, TP_UNIT(gpc, tp, 0xe4c), 0x0000000f); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x644), 0x001ffffe); + nv_wr32(dev, TP_UNIT(gpc, tp, 0x64c), 0x0000000f); } nv_wr32(dev, GPC_UNIT(gpc, 0x2c90), 0xffffffff); nv_wr32(dev, GPC_UNIT(gpc, 0x2c94), 0xffffffff); @@ -777,3 +780,19 @@ nvc0_graph_isr(struct drm_device *dev) nv_wr32(dev, 0x400500, 0x00010001); } + +static void +nvc0_runk140_isr(struct drm_device *dev) +{ + u32 units = nv_rd32(dev, 0x00017c) & 0x1f; + + while (units) { + u32 unit = ffs(units) - 1; + u32 reg = 0x140000 + unit * 0x2000; + u32 st0 = nv_mask(dev, reg + 0x1020, 0, 0); + u32 st1 = nv_mask(dev, reg + 0x1420, 0, 0); + + NV_INFO(dev, "PRUNK140: %d 0x%08x 0x%08x\n", unit, st0, st1); + units &= ~(1 << unit); + } +} diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c index b9e68b2d30a..f880ff776db 100644 --- a/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c @@ -1830,7 +1830,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) for (tp = 0, id = 0; tp < 4; tp++) { for (gpc = 0; gpc < priv->gpc_nr; gpc++) { - if (tp <= priv->tp_nr[gpc]) { + if (tp < priv->tp_nr[gpc]) { nv_wr32(dev, TP_UNIT(gpc, tp, 0x698), id); nv_wr32(dev, TP_UNIT(gpc, tp, 0x4e8), id); nv_wr32(dev, GPC_UNIT(gpc, 0x0c10 + tp * 4), id); diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index d3ca17080df..842954fe74c 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -994,6 +994,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, struct radeon_bo *rbo; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); int r; /* no fb bound */ @@ -1045,11 +1046,17 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, case 16: fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_16BPP) | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB565)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN16); +#endif break; case 24: case 32: fb_format = (EVERGREEN_GRPH_DEPTH(EVERGREEN_GRPH_DEPTH_32BPP) | EVERGREEN_GRPH_FORMAT(EVERGREEN_GRPH_FORMAT_ARGB8888)); +#ifdef __BIG_ENDIAN + fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_8IN32); +#endif break; default: DRM_ERROR("Unsupported screen depth %d\n", @@ -1094,6 +1101,7 @@ static int evergreen_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, (u32) fb_location & EVERGREEN_GRPH_SURFACE_ADDRESS_MASK); WREG32(EVERGREEN_GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + WREG32(EVERGREEN_GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); WREG32(EVERGREEN_GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); @@ -1150,6 +1158,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *target_fb; uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; + u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; int r; /* no fb bound */ @@ -1203,12 +1212,18 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_16BIT; +#endif break; case 24: case 32: fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; +#ifdef __BIG_ENDIAN + fb_swap = R600_D1GRPH_SWAP_ENDIAN_32BIT; +#endif break; default: DRM_ERROR("Unsupported screen depth %d\n", @@ -1248,6 +1263,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, (u32) fb_location); WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); + if (rdev->family >= CHIP_R600) + WREG32(R600_D1GRPH_SWAP_CONTROL + radeon_crtc->crtc_offset, fb_swap); WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 4e7778d44b8..695de9a3850 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -187,9 +187,9 @@ static int dp_link_clock_for_mode_clock(u8 dpcd[DP_DPCD_SIZE], int mode_clock) int dp_mode_valid(u8 dpcd[DP_DPCD_SIZE], int mode_clock) { int lanes = dp_lanes_for_mode_clock(dpcd, mode_clock); - int bw = dp_lanes_for_mode_clock(dpcd, mode_clock); + int dp_clock = dp_link_clock_for_mode_clock(dpcd, mode_clock); - if ((lanes == 0) || (bw == 0)) + if ((lanes == 0) || (dp_clock == 0)) return MODE_CLOCK_HIGH; return MODE_OK; diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index b758dc7f2f2..d4d4db49a8b 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -232,7 +232,7 @@ draw_auto(struct radeon_device *rdev) } -/* emits 30 */ +/* emits 34 */ static void set_default_state(struct radeon_device *rdev) { @@ -245,6 +245,8 @@ set_default_state(struct radeon_device *rdev) int num_hs_threads, num_ls_threads; int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; int num_hs_stack_entries, num_ls_stack_entries; + u64 gpu_addr; + int dwords; switch (rdev->family) { case CHIP_CEDAR: @@ -497,6 +499,14 @@ set_default_state(struct radeon_device *rdev) radeon_ring_write(rdev, 0x00000000); radeon_ring_write(rdev, 0x00000000); + /* emit an IB pointing at default state */ + dwords = ALIGN(rdev->r600_blit.state_len, 0x10); + gpu_addr = rdev->r600_blit.shader_gpu_addr + rdev->r600_blit.state_offset; + radeon_ring_write(rdev, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); + radeon_ring_write(rdev, gpu_addr & 0xFFFFFFFC); + radeon_ring_write(rdev, upper_32_bits(gpu_addr) & 0xFF); + radeon_ring_write(rdev, dwords); + } static inline uint32_t i2f(uint32_t input) @@ -527,8 +537,10 @@ static inline uint32_t i2f(uint32_t input) int evergreen_blit_init(struct radeon_device *rdev) { u32 obj_size; - int r; + int r, dwords; void *ptr; + u32 packet2s[16]; + int num_packet2s = 0; /* pin copy shader into vram if already initialized */ if (rdev->r600_blit.shader_obj) @@ -536,8 +548,17 @@ int evergreen_blit_init(struct radeon_device *rdev) mutex_init(&rdev->r600_blit.mutex); rdev->r600_blit.state_offset = 0; - rdev->r600_blit.state_len = 0; - obj_size = 0; + + rdev->r600_blit.state_len = evergreen_default_size; + + dwords = rdev->r600_blit.state_len; + while (dwords & 0xf) { + packet2s[num_packet2s++] = PACKET2(0); + dwords++; + } + + obj_size = dwords * 4; + obj_size = ALIGN(obj_size, 256); rdev->r600_blit.vs_offset = obj_size; obj_size += evergreen_vs_size * 4; @@ -567,6 +588,12 @@ int evergreen_blit_init(struct radeon_device *rdev) return r; } + memcpy_toio(ptr + rdev->r600_blit.state_offset, + evergreen_default_state, rdev->r600_blit.state_len * 4); + + if (num_packet2s) + memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4), + packet2s, num_packet2s * 4); memcpy(ptr + rdev->r600_blit.vs_offset, evergreen_vs, evergreen_vs_size * 4); memcpy(ptr + rdev->r600_blit.ps_offset, evergreen_ps, evergreen_ps_size * 4); radeon_bo_kunmap(rdev->r600_blit.shader_obj); @@ -652,7 +679,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) /* calculate number of loops correctly */ ring_size = num_loops * dwords_per_loop; /* set default + shaders */ - ring_size += 46; /* shaders + def state */ + ring_size += 50; /* shaders + def state */ ring_size += 10; /* fence emit for VB IB */ ring_size += 5; /* done copy */ ring_size += 10; /* fence emit for done copy */ @@ -660,7 +687,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes) if (r) return r; - set_default_state(rdev); /* 30 */ + set_default_state(rdev); /* 34 */ set_shaders(rdev); /* 16 */ return 0; } diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 5968dde243e..5f15820efe1 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1031,8 +1031,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) WREG32(RADEON_CP_CSQ_MODE, REG_SET(RADEON_INDIRECT2_START, indirect2_start) | REG_SET(RADEON_INDIRECT1_START, indirect1_start)); - WREG32(0x718, 0); - WREG32(0x744, 0x00004D4D); + WREG32(RADEON_CP_RB_WPTR_DELAY, 0); + WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D); WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); radeon_ring_start(rdev); r = radeon_ring_test(rdev); @@ -2347,10 +2347,10 @@ void r100_vga_set_state(struct radeon_device *rdev, bool state) temp = RREG32(RADEON_CONFIG_CNTL); if (state == false) { - temp &= ~(1<<8); - temp |= (1<<9); + temp &= ~RADEON_CFG_VGA_RAM_EN; + temp |= RADEON_CFG_VGA_IO_DIS; } else { - temp &= ~(1<<9); + temp &= ~RADEON_CFG_VGA_IO_DIS; } WREG32(RADEON_CONFIG_CNTL, temp); } diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index cf862ca580b..55fe5ba7def 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -69,6 +69,9 @@ void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) mb(); } +#define R300_PTE_WRITEABLE (1 << 2) +#define R300_PTE_READABLE (1 << 3) + int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; @@ -78,7 +81,7 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) } addr = (lower_32_bits(addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 24) | - 0xc; + R300_PTE_WRITEABLE | R300_PTE_READABLE; /* on x86 we want this to be CPU endian, on powerpc * on powerpc without HW swappers, it'll get swapped on way * into VRAM - so no need for cpu_to_le32 on VRAM tables */ @@ -135,7 +138,7 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev) WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start); WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); /* Clear error */ - WREG32_PCIE(0x18, 0); + WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0); tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); tmp |= RADEON_PCIE_TX_GART_EN; tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index c387346f93a..0b59ed7c7d2 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -96,7 +96,7 @@ void r420_pipes_init(struct radeon_device *rdev) "programming pipes. Bad things might happen.\n"); } /* get max number of pipes */ - gb_pipe_select = RREG32(0x402C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); num_pipes = ((gb_pipe_select >> 12) & 3) + 1; /* SE chips have 1 pipe */ diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 3c8677f9e38..2ce80d97656 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -79,8 +79,8 @@ static void r520_gpu_init(struct radeon_device *rdev) WREG32(0x4128, 0xFF); } r420_pipes_init(rdev); - gb_pipe_select = RREG32(0x402C); - tmp = RREG32(0x170C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); pipe_select_current = (tmp >> 2) & 3; tmp = (1 << pipe_select_current) | (((gb_pipe_select >> 8) & 0xF) << 4); diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h index 33cda016b08..f869897c745 100644 --- a/drivers/gpu/drm/radeon/r600_reg.h +++ b/drivers/gpu/drm/radeon/r600_reg.h @@ -81,7 +81,11 @@ #define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720 #define R600_LOW_VID_LOWER_GPIO_CNTL 0x724 - +#define R600_D1GRPH_SWAP_CONTROL 0x610C +# define R600_D1GRPH_SWAP_ENDIAN_NONE (0 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_16BIT (1 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_32BIT (2 << 0) +# define R600_D1GRPH_SWAP_ENDIAN_64BIT (3 << 0) #define R600_HDP_NONSURFACE_BASE 0x2c04 diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 8fd184286c0..5e90984d5ad 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -641,7 +641,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if (drm_detect_monitor_audio(radeon_connector->edid)) { + if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; @@ -655,7 +655,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if (drm_detect_monitor_audio(radeon_connector->edid)) { + if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; @@ -673,7 +673,7 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; - else if (drm_detect_monitor_audio(radeon_connector->edid)) { + else if (drm_detect_monitor_audio(radeon_connector->edid) && radeon_audio) { /* fix me */ if (ASIC_IS_DCE4(rdev)) return ATOM_ENCODER_MODE_DVI; diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 98321298cff..8387d32caaa 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -247,6 +247,8 @@ void radeon_driver_preclose_kms(struct drm_device *dev, struct radeon_device *rdev = dev->dev_private; if (rdev->hyperz_filp == file_priv) rdev->hyperz_filp = NULL; + if (rdev->cmask_filp == file_priv) + rdev->cmask_filp = NULL; } /* diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index 3cd4dace57c..ec93a75369e 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -375,6 +375,8 @@ #define RADEON_CONFIG_APER_SIZE 0x0108 #define RADEON_CONFIG_BONDS 0x00e8 #define RADEON_CONFIG_CNTL 0x00e0 +# define RADEON_CFG_VGA_RAM_EN (1 << 8) +# define RADEON_CFG_VGA_IO_DIS (1 << 9) # define RADEON_CFG_ATI_REV_A11 (0 << 16) # define RADEON_CFG_ATI_REV_A12 (1 << 16) # define RADEON_CFG_ATI_REV_A13 (2 << 16) diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 5512e4e5e63..c76283d9eb3 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -203,6 +203,9 @@ void rs400_gart_fini(struct radeon_device *rdev) radeon_gart_table_ram_free(rdev); } +#define RS400_PTE_WRITEABLE (1 << 2) +#define RS400_PTE_READABLE (1 << 3) + int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) { uint32_t entry; @@ -213,7 +216,7 @@ int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) entry = (lower_32_bits(addr) & PAGE_MASK) | ((upper_32_bits(addr) & 0xff) << 4) | - 0xc; + RS400_PTE_WRITEABLE | RS400_PTE_READABLE; entry = cpu_to_le32(entry); rdev->gart.table.ram.ptr[i] = entry; return 0; @@ -226,8 +229,8 @@ int rs400_mc_wait_for_idle(struct radeon_device *rdev) for (i = 0; i < rdev->usec_timeout; i++) { /* read MC_STATUS */ - tmp = RREG32(0x0150); - if (tmp & (1 << 2)) { + tmp = RREG32(RADEON_MC_STATUS); + if (tmp & RADEON_MC_IDLE) { return 0; } DRM_UDELAY(1); @@ -241,7 +244,7 @@ void rs400_gpu_init(struct radeon_device *rdev) r420_pipes_init(rdev); if (rs400_mc_wait_for_idle(rdev)) { printk(KERN_WARNING "rs400: Failed to wait MC idle while " - "programming pipes. Bad things might happen. %08x\n", RREG32(0x150)); + "programming pipes. Bad things might happen. %08x\n", RREG32(RADEON_MC_STATUS)); } } @@ -300,9 +303,9 @@ static int rs400_debugfs_gart_info(struct seq_file *m, void *data) seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp); tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION); seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp); - tmp = RREG32_MC(0x100); + tmp = RREG32_MC(RS690_MCCFG_FB_LOCATION); seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp); - tmp = RREG32(0x134); + tmp = RREG32(RS690_HDP_FB_LOCATION); seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp); } else { tmp = RREG32(RADEON_AGP_BASE); diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 5d569f41f4a..64b57af9371 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -69,13 +69,13 @@ void rv515_ring_start(struct radeon_device *rdev) ISYNC_CPSCRATCH_IDLEGUI); radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0)); radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN); - radeon_ring_write(rdev, PACKET0(0x170C, 0)); - radeon_ring_write(rdev, 1 << 31); + radeon_ring_write(rdev, PACKET0(R300_DST_PIPE_CONFIG, 0)); + radeon_ring_write(rdev, R300_PIPE_AUTO_CONFIG); radeon_ring_write(rdev, PACKET0(GB_SELECT, 0)); radeon_ring_write(rdev, 0); radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0)); radeon_ring_write(rdev, 0); - radeon_ring_write(rdev, PACKET0(0x42C8, 0)); + radeon_ring_write(rdev, PACKET0(R500_SU_REG_DEST, 0)); radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0)); radeon_ring_write(rdev, 0); @@ -153,8 +153,8 @@ void rv515_gpu_init(struct radeon_device *rdev) } rv515_vga_render_disable(rdev); r420_pipes_init(rdev); - gb_pipe_select = RREG32(0x402C); - tmp = RREG32(0x170C); + gb_pipe_select = RREG32(R400_GB_PIPE_SELECT); + tmp = RREG32(R300_DST_PIPE_CONFIG); pipe_select_current = (tmp >> 2) & 3; tmp = (1 << pipe_select_current) | (((gb_pipe_select >> 8) & 0xF) << 4); diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c index 939476659ad..ac471b77c18 100644 --- a/drivers/input/keyboard/tegra-kbc.c +++ b/drivers/input/keyboard/tegra-kbc.c @@ -86,7 +86,7 @@ static const u32 tegra_kbc_default_keymap[] = { KEY(0, 5, KEY_Z), KEY(0, 7, KEY_FN), - KEY(1, 7, KEY_MENU), + KEY(1, 7, KEY_LEFTMETA), KEY(2, 6, KEY_RIGHTALT), KEY(2, 7, KEY_LEFTALT), @@ -355,8 +355,8 @@ static void tegra_kbc_config_pins(struct tegra_kbc *kbc) for (i = 0; i < KBC_MAX_GPIO; i++) { u32 r_shft = 5 * (i % 6); u32 c_shft = 4 * (i % 8); - u32 r_mask = 0x1f << r_shift; - u32 c_mask = 0x0f << c_shift; + u32 r_mask = 0x1f << r_shft; + u32 c_mask = 0x0f << c_shft; u32 r_offs = (i / 6) * 4 + KBC_ROW_CFG0_0; u32 c_offs = (i / 8) * 4 + KBC_COL_CFG0_0; u32 row_cfg = readl(kbc->mmio + r_offs); diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index da392c22fc6..aa186cf6c51 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -755,23 +755,26 @@ static int synaptics_reconnect(struct psmouse *psmouse) { struct synaptics_data *priv = psmouse->private; struct synaptics_data old_priv = *priv; + int retry = 0; + int error; - psmouse_reset(psmouse); + do { + psmouse_reset(psmouse); + error = synaptics_detect(psmouse, 0); + } while (error && ++retry < 3); - if (synaptics_detect(psmouse, 0)) + if (error) return -1; + if (retry > 1) + printk(KERN_DEBUG "Synaptics reconnected after %d tries\n", + retry); + if (synaptics_query_hardware(psmouse)) { printk(KERN_ERR "Unable to query Synaptics hardware.\n"); return -1; } - if (old_priv.identity != priv->identity || - old_priv.model_id != priv->model_id || - old_priv.capabilities != priv->capabilities || - old_priv.ext_cap != priv->ext_cap) - return -1; - if (synaptics_set_absolute_mode(psmouse)) { printk(KERN_ERR "Unable to initialize Synaptics hardware.\n"); return -1; @@ -782,6 +785,19 @@ static int synaptics_reconnect(struct psmouse *psmouse) return -1; } + if (old_priv.identity != priv->identity || + old_priv.model_id != priv->model_id || + old_priv.capabilities != priv->capabilities || + old_priv.ext_cap != priv->ext_cap) { + printk(KERN_ERR "Synaptics hardware appears to be different: " + "id(%ld-%ld), model(%ld-%ld), caps(%lx-%lx), ext(%lx-%lx).\n", + old_priv.identity, priv->identity, + old_priv.model_id, priv->model_id, + old_priv.capabilities, priv->capabilities, + old_priv.ext_cap, priv->ext_cap); + return -1; + } + return 0; } diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 72be8a02118..512a2f4ada0 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -458,21 +458,27 @@ static int ir_getkeycode(struct input_dev *idev, index = ir_lookup_by_scancode(rc_map, scancode); } - if (index >= rc_map->len) { - if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) - IR_dprintk(1, "unknown key for scancode 0x%04x\n", - scancode); + if (index < rc_map->len) { + entry = &rc_map->scan[index]; + + ke->index = index; + ke->keycode = entry->keycode; + ke->len = sizeof(entry->scancode); + memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); + + } else if (!(ke->flags & INPUT_KEYMAP_BY_INDEX)) { + /* + * We do not really know the valid range of scancodes + * so let's respond with KEY_RESERVED to anything we + * do not have mapping for [yet]. + */ + ke->index = index; + ke->keycode = KEY_RESERVED; + } else { retval = -EINVAL; goto out; } - entry = &rc_map->scan[index]; - - ke->index = index; - ke->keycode = entry->keycode; - ke->len = sizeof(entry->scancode); - memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode)); - retval = 0; out: diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index f49e49dc592..5ebe280225d 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -672,33 +672,7 @@ static int io_init(struct ubi_device *ubi) ubi->nor_flash = 1; } - /* - * Set UBI min. I/O size (@ubi->min_io_size). We use @mtd->writebufsize - * for these purposes, not @mtd->writesize. At the moment this does not - * matter for NAND, because currently @mtd->writebufsize is equivalent to - * @mtd->writesize for all NANDs. However, some CFI NOR flashes may - * have @mtd->writebufsize which is multiple of @mtd->writesize. - * - * The reason we use @mtd->writebufsize for @ubi->min_io_size is that - * UBI and UBIFS recovery algorithms rely on the fact that if there was - * an unclean power cut, then we can find offset of the last corrupted - * node, align the offset to @ubi->min_io_size, read the rest of the - * eraseblock starting from this offset, and check whether there are - * only 0xFF bytes. If yes, then we are probably dealing with a - * corruption caused by a power cut, if not, then this is probably some - * severe corruption. - * - * Thus, we have to use the maximum write unit size of the flash, which - * is @mtd->writebufsize, because @mtd->writesize is the minimum write - * size, not the maximum. - */ - if (ubi->mtd->type == MTD_NANDFLASH) - ubi_assert(ubi->mtd->writebufsize == ubi->mtd->writesize); - else if (ubi->mtd->type == MTD_NORFLASH) - ubi_assert(ubi->mtd->writebufsize % ubi->mtd->writesize == 0); - - ubi->min_io_size = ubi->mtd->writebufsize; - + ubi->min_io_size = ubi->mtd->writesize; ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; /* diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index f374c5961b3..a91d510a798 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -26,7 +26,6 @@ #include <linux/sfi.h> #include <asm/mrst.h> #include <asm/intel_scu_ipc.h> -#include <asm/mrst.h> /* IPC defines the following message types */ #define IPCMSG_WATCHDOG_TIMER 0xF8 /* Set Kernel Watchdog Threshold */ diff --git a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c index 0e298dba9fc..29b8ab44ea4 100644 --- a/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c +++ b/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c @@ -360,8 +360,8 @@ int PSSendOps(void *arg) status = 1; goto complete; } - len = (firmware->size > MAX_BDADDR_FORMAT_LENGTH)? MAX_BDADDR_FORMAT_LENGTH: firmware->size; - memcpy(config_bdaddr, firmware->data,len); + len = min(firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1); + memcpy(config_bdaddr, firmware->data, len); config_bdaddr[len] = '\0'; write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING); A_RELEASE_FIRMWARE(firmware); diff --git a/drivers/staging/brcm80211/sys/wl_mac80211.c b/drivers/staging/brcm80211/sys/wl_mac80211.c index bdd629d72a7..f1235884cc5 100644 --- a/drivers/staging/brcm80211/sys/wl_mac80211.c +++ b/drivers/staging/brcm80211/sys/wl_mac80211.c @@ -209,11 +209,8 @@ static void wl_ops_stop(struct ieee80211_hw *hw) struct wl_info *wl = hw->priv; ASSERT(wl); WL_LOCK(wl); - wl_down(wl); ieee80211_stop_queues(hw); WL_UNLOCK(wl); - - return; } static int @@ -246,7 +243,14 @@ wl_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) static void wl_ops_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { - return; + struct wl_info *wl; + + wl = HW_TO_WL(hw); + + /* put driver in down state */ + WL_LOCK(wl); + wl_down(wl); + WL_UNLOCK(wl); } static int @@ -779,7 +783,7 @@ static struct wl_info *wl_attach(u16 vendor, u16 device, unsigned long regs, wl_found++; return wl; - fail: +fail: wl_free(wl); fail1: return NULL; @@ -1090,7 +1094,6 @@ wl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return 0; } -#ifdef LINUXSTA_PS static int wl_suspend(struct pci_dev *pdev, pm_message_t state) { struct wl_info *wl; @@ -1105,11 +1108,12 @@ static int wl_suspend(struct pci_dev *pdev, pm_message_t state) return -ENODEV; } + /* only need to flag hw is down for proper resume */ WL_LOCK(wl); - wl_down(wl); wl->pub->hw_up = false; WL_UNLOCK(wl); - pci_save_state(pdev, wl->pci_psstate); + + pci_save_state(pdev); pci_disable_device(pdev); return pci_set_power_state(pdev, PCI_D3hot); } @@ -1133,7 +1137,7 @@ static int wl_resume(struct pci_dev *pdev) if (err) return err; - pci_restore_state(pdev, wl->pci_psstate); + pci_restore_state(pdev); err = pci_enable_device(pdev); if (err) @@ -1145,13 +1149,12 @@ static int wl_resume(struct pci_dev *pdev) if ((val & 0x0000ff00) != 0) pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - WL_LOCK(wl); - err = wl_up(wl); - WL_UNLOCK(wl); - + /* + * done. driver will be put in up state + * in wl_ops_add_interface() call. + */ return err; } -#endif /* LINUXSTA_PS */ static void wl_remove(struct pci_dev *pdev) { @@ -1184,14 +1187,12 @@ static void wl_remove(struct pci_dev *pdev) } static struct pci_driver wl_pci_driver = { - .name = "brcm80211", - .probe = wl_pci_probe, -#ifdef LINUXSTA_PS - .suspend = wl_suspend, - .resume = wl_resume, -#endif /* LINUXSTA_PS */ - .remove = __devexit_p(wl_remove), - .id_table = wl_id_table, + .name = "brcm80211", + .probe = wl_pci_probe, + .suspend = wl_suspend, + .resume = wl_resume, + .remove = __devexit_p(wl_remove), + .id_table = wl_id_table, }; /** diff --git a/drivers/staging/brcm80211/sys/wlc_mac80211.c b/drivers/staging/brcm80211/sys/wlc_mac80211.c index 1d5d01ac0a9..a1303863686 100644 --- a/drivers/staging/brcm80211/sys/wlc_mac80211.c +++ b/drivers/staging/brcm80211/sys/wlc_mac80211.c @@ -5126,7 +5126,6 @@ wlc_sendpkt_mac80211(struct wlc_info *wlc, struct sk_buff *sdu, fifo = prio2fifo[prio]; ASSERT((uint) skb_headroom(sdu) >= TXOFF); - ASSERT(!(sdu->cloned)); ASSERT(!(sdu->next)); ASSERT(!(sdu->prev)); ASSERT(fifo < NFIFO); diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 4d1868d04ba..0728c3c0cb0 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -575,7 +575,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase, /* grab our IRQ */ if (irq) { isr_flags = 0; - if (thisboard->bustype == pci_bustype) + if (thisboard->bustype == pci_bustype + || thisboard->bustype == pcmcia_bustype) isr_flags |= IRQF_SHARED; if (request_irq(irq, labpc_interrupt, isr_flags, driver_labpc.driver_name, dev)) { diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c index b3d05fcfe6d..4fb809485d9 100644 --- a/drivers/staging/hv/blkvsc_drv.c +++ b/drivers/staging/hv/blkvsc_drv.c @@ -368,6 +368,7 @@ static int blkvsc_probe(struct device *device) blkdev->gd->first_minor = 0; blkdev->gd->fops = &block_ops; blkdev->gd->private_data = blkdev; + blkdev->gd->driverfs_dev = &(blkdev->device_ctx->device); sprintf(blkdev->gd->disk_name, "hd%c", 'a' + devnum); blkvsc_do_inquiry(blkdev); diff --git a/drivers/staging/hv/netvsc.c b/drivers/staging/hv/netvsc.c index df9cd131e95..0edbe7483a4 100644 --- a/drivers/staging/hv/netvsc.c +++ b/drivers/staging/hv/netvsc.c @@ -1279,7 +1279,7 @@ static void netvsc_channel_cb(void *context) /* ASSERT(device); */ packet = kzalloc(NETVSC_PACKET_SIZE * sizeof(unsigned char), - GFP_KERNEL); + GFP_ATOMIC); if (!packet) return; buffer = packet; diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 0147b407512..54706a16dc0 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -358,7 +358,6 @@ static int netvsc_probe(struct device *device) /* Set initial state */ netif_carrier_off(net); - netif_stop_queue(net); net_device_ctx = netdev_priv(net); net_device_ctx->device_ctx = device_ctx; diff --git a/drivers/staging/iio/adc/ad7476_core.c b/drivers/staging/iio/adc/ad7476_core.c index deb68c8a6e1..b8b54da67c6 100644 --- a/drivers/staging/iio/adc/ad7476_core.c +++ b/drivers/staging/iio/adc/ad7476_core.c @@ -68,7 +68,7 @@ static ssize_t ad7476_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7476_show_scale, NULL, 0); diff --git a/drivers/staging/iio/adc/ad7887_core.c b/drivers/staging/iio/adc/ad7887_core.c index 685908995d4..5d85efab658 100644 --- a/drivers/staging/iio/adc/ad7887_core.c +++ b/drivers/staging/iio/adc/ad7887_core.c @@ -68,7 +68,7 @@ static ssize_t ad7887_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad7887_show_scale, NULL, 0); diff --git a/drivers/staging/iio/adc/ad799x_core.c b/drivers/staging/iio/adc/ad799x_core.c index 6309d521a86..89ccf375a18 100644 --- a/drivers/staging/iio/adc/ad799x_core.c +++ b/drivers/staging/iio/adc/ad799x_core.c @@ -432,7 +432,7 @@ static ssize_t ad799x_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->int_vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(in_scale, S_IRUGO, ad799x_show_scale, NULL, 0); diff --git a/drivers/staging/iio/dac/ad5446.c b/drivers/staging/iio/dac/ad5446.c index e3387cd3114..0f87ecac82f 100644 --- a/drivers/staging/iio/dac/ad5446.c +++ b/drivers/staging/iio/dac/ad5446.c @@ -87,7 +87,7 @@ static ssize_t ad5446_show_scale(struct device *dev, /* Corresponds to Vref / 2^(bits) */ unsigned int scale_uv = (st->vref_mv * 1000) >> st->chip_info->bits; - return sprintf(buf, "%d.%d\n", scale_uv / 1000, scale_uv % 1000); + return sprintf(buf, "%d.%03d\n", scale_uv / 1000, scale_uv % 1000); } static IIO_DEVICE_ATTR(out_scale, S_IRUGO, ad5446_show_scale, NULL, 0); diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c index 701561d6b6f..236dd36d349 100644 --- a/drivers/staging/rt2860/rt_main_dev.c +++ b/drivers/staging/rt2860/rt_main_dev.c @@ -484,8 +484,6 @@ struct net_device *RtmpPhyNetDevInit(struct rt_rtmp_adapter *pAd, net_dev->ml_priv = (void *)pAd; pAd->net_dev = net_dev; - netif_stop_queue(net_dev); - return net_dev; } diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c index ee68d51caa4..322bf49ee90 100644 --- a/drivers/staging/rt2860/usb_main_dev.c +++ b/drivers/staging/rt2860/usb_main_dev.c @@ -106,6 +106,7 @@ struct usb_device_id rtusb_usb_id[] = { {USB_DEVICE(0x0411, 0x016f)}, /* MelCo.,Inc. WLI-UC-G301N */ {USB_DEVICE(0x1737, 0x0070)}, /* Linksys WUSB100 */ {USB_DEVICE(0x1737, 0x0071)}, /* Linksys WUSB600N */ + {USB_DEVICE(0x1737, 0x0078)}, /* Linksys WUSB100v2 */ {USB_DEVICE(0x0411, 0x00e8)}, /* Buffalo WLI-UC-G300N */ {USB_DEVICE(0x050d, 0x815c)}, /* Belkin F5D8053 */ {USB_DEVICE(0x100D, 0x9031)}, /* Motorola 2770 */ diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 32088a641eb..84be383abec 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -128,12 +128,13 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) u8 *ptmpchar = NULL, *ppayload, *ptr; struct tx_desc *ptx_desc; u32 txdscp_sz = sizeof(struct tx_desc); + u8 ret = _FAIL; ulfilelength = rtl871x_open_fw(padapter, &phfwfile_hdl, &pmappedfw); if (pmappedfw && (ulfilelength > 0)) { update_fwhdr(&fwhdr, pmappedfw); if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL) - goto exit_fail; + goto firmware_rel; fill_fwpriv(padapter, &fwhdr.fwpriv); /* firmware check ok */ maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ? @@ -141,7 +142,7 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) maxlen += txdscp_sz; ptmpchar = _malloc(maxlen + FWBUFF_ALIGN_SZ); if (ptmpchar == NULL) - return _FAIL; + goto firmware_rel; ptx_desc = (struct tx_desc *)(ptmpchar + FWBUFF_ALIGN_SZ - ((addr_t)(ptmpchar) & (FWBUFF_ALIGN_SZ - 1))); @@ -273,11 +274,13 @@ static u8 rtl8712_dl_fw(struct _adapter *padapter) goto exit_fail; } else goto exit_fail; - return _SUCCESS; + ret = _SUCCESS; exit_fail: kfree(ptmpchar); - return _FAIL; +firmware_rel: + release_firmware((struct firmware *)phfwfile_hdl); + return ret; } uint rtl8712_hal_init(struct _adapter *padapter) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index a692ee88b9e..21ce2af447b 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -47,54 +47,123 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, static void r871xu_dev_remove(struct usb_interface *pusb_intf); static struct usb_device_id rtl871x_usb_id_tbl[] = { - /*92SU - * Realtek */ - {USB_DEVICE(0x0bda, 0x8171)}, - {USB_DEVICE(0x0bda, 0x8172)}, + +/* RTL8188SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8171)}, {USB_DEVICE(0x0bda, 0x8173)}, - {USB_DEVICE(0x0bda, 0x8174)}, {USB_DEVICE(0x0bda, 0x8712)}, {USB_DEVICE(0x0bda, 0x8713)}, {USB_DEVICE(0x0bda, 0xC512)}, - /* Abocom */ + /* Abocom */ {USB_DEVICE(0x07B8, 0x8188)}, + /* ASUS */ + {USB_DEVICE(0x0B05, 0x1786)}, + {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ + /* Belkin */ + {USB_DEVICE(0x050D, 0x945A)}, /* Corega */ - {USB_DEVICE(0x07aa, 0x0047)}, - /* Dlink */ - {USB_DEVICE(0x07d1, 0x3303)}, - {USB_DEVICE(0x07d1, 0x3302)}, - {USB_DEVICE(0x07d1, 0x3300)}, - /* Dlink for Skyworth */ - {USB_DEVICE(0x14b2, 0x3300)}, - {USB_DEVICE(0x14b2, 0x3301)}, - {USB_DEVICE(0x14b2, 0x3302)}, + {USB_DEVICE(0x07AA, 0x0047)}, + /* D-Link */ + {USB_DEVICE(0x2001, 0x3306)}, + {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */ + /* Edimax */ + {USB_DEVICE(0x7392, 0x7611)}, /* EnGenius */ {USB_DEVICE(0x1740, 0x9603)}, - {USB_DEVICE(0x1740, 0x9605)}, + /* Hawking */ + {USB_DEVICE(0x0E66, 0x0016)}, + /* Hercules */ + {USB_DEVICE(0x06F8, 0xE034)}, + {USB_DEVICE(0x06F8, 0xE032)}, + /* Logitec */ + {USB_DEVICE(0x0789, 0x0167)}, + /* PCI */ + {USB_DEVICE(0x2019, 0xAB28)}, + {USB_DEVICE(0x2019, 0xED16)}, + /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x0057)}, + {USB_DEVICE(0x0DF6, 0x0045)}, + {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */ + {USB_DEVICE(0x0DF6, 0x004B)}, + {USB_DEVICE(0x0DF6, 0x0063)}, + /* Sweex */ + {USB_DEVICE(0x177F, 0x0154)}, + /* Thinkware */ + {USB_DEVICE(0x0BDA, 0x5077)}, + /* Toshiba */ + {USB_DEVICE(0x1690, 0x0752)}, + /* - */ + {USB_DEVICE(0x20F4, 0x646B)}, + {USB_DEVICE(0x083A, 0xC512)}, + +/* RTL8191SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8172)}, + /* Amigo */ + {USB_DEVICE(0x0EB0, 0x9061)}, + /* ASUS/EKB */ + {USB_DEVICE(0x0BDA, 0x8172)}, + {USB_DEVICE(0x13D3, 0x3323)}, + {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3342)}, + /* ASUS/EKBLenovo */ + {USB_DEVICE(0x13D3, 0x3333)}, + {USB_DEVICE(0x13D3, 0x3334)}, + {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */ + /* ASUS/Media BOX */ + {USB_DEVICE(0x13D3, 0x3309)}, /* Belkin */ - {USB_DEVICE(0x050d, 0x815F)}, - {USB_DEVICE(0x050d, 0x945A)}, - {USB_DEVICE(0x050d, 0x845A)}, - /* Guillemot */ - {USB_DEVICE(0x06f8, 0xe031)}, + {USB_DEVICE(0x050D, 0x815F)}, + /* D-Link */ + {USB_DEVICE(0x07D1, 0x3302)}, + {USB_DEVICE(0x07D1, 0x3300)}, + {USB_DEVICE(0x07D1, 0x3303)}, /* Edimax */ - {USB_DEVICE(0x7392, 0x7611)}, {USB_DEVICE(0x7392, 0x7612)}, - {USB_DEVICE(0x7392, 0x7622)}, - /* Sitecom */ - {USB_DEVICE(0x0DF6, 0x0045)}, + /* EnGenius */ + {USB_DEVICE(0x1740, 0x9605)}, + /* Guillemot */ + {USB_DEVICE(0x06F8, 0xE031)}, /* Hawking */ {USB_DEVICE(0x0E66, 0x0015)}, - {USB_DEVICE(0x0E66, 0x0016)}, - {USB_DEVICE(0x0b05, 0x1786)}, - {USB_DEVICE(0x0b05, 0x1791)}, /* 11n mode disable */ - + /* Mediao */ {USB_DEVICE(0x13D3, 0x3306)}, - {USB_DEVICE(0x13D3, 0x3309)}, + /* PCI */ + {USB_DEVICE(0x2019, 0xED18)}, + {USB_DEVICE(0x2019, 0x4901)}, + /* Sitecom */ + {USB_DEVICE(0x0DF6, 0x0058)}, + {USB_DEVICE(0x0DF6, 0x0049)}, + {USB_DEVICE(0x0DF6, 0x004C)}, + {USB_DEVICE(0x0DF6, 0x0064)}, + /* Skyworth */ + {USB_DEVICE(0x14b2, 0x3300)}, + {USB_DEVICE(0x14b2, 0x3301)}, + {USB_DEVICE(0x14B2, 0x3302)}, + /* - */ + {USB_DEVICE(0x04F2, 0xAFF2)}, + {USB_DEVICE(0x04F2, 0xAFF5)}, + {USB_DEVICE(0x04F2, 0xAFF6)}, + {USB_DEVICE(0x13D3, 0x3339)}, + {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */ + {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */ {USB_DEVICE(0x13D3, 0x3310)}, - {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */ {USB_DEVICE(0x13D3, 0x3325)}, - {USB_DEVICE(0x083A, 0xC512)}, + +/* RTL8192SU */ + /* Realtek */ + {USB_DEVICE(0x0BDA, 0x8174)}, + {USB_DEVICE(0x0BDA, 0x8174)}, + /* Belkin */ + {USB_DEVICE(0x050D, 0x845A)}, + /* Corega */ + {USB_DEVICE(0x07AA, 0x0051)}, + /* Edimax */ + {USB_DEVICE(0x7392, 0x7622)}, + /* NEC */ + {USB_DEVICE(0x0409, 0x02B6)}, {} }; @@ -103,8 +172,20 @@ MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl); static struct specific_device_id specific_device_id_tbl[] = { {.idVendor = 0x0b05, .idProduct = 0x1791, .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x0df6, .idProduct = 0x0059, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3306, + .flags = SPEC_DEV_ID_DISABLE_HT}, {.idVendor = 0x13D3, .idProduct = 0x3311, .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3335, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3336, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3340, + .flags = SPEC_DEV_ID_DISABLE_HT}, + {.idVendor = 0x13d3, .idProduct = 0x3341, + .flags = SPEC_DEV_ID_DISABLE_HT}, {} }; diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c index 408bb9b3303..07a7f543259 100644 --- a/drivers/staging/speakup/kobjects.c +++ b/drivers/staging/speakup/kobjects.c @@ -332,7 +332,7 @@ static ssize_t silent_store(struct kobject *kobj, struct kobj_attribute *attr, unsigned long flags; len = strlen(buf); - if (len > 0 || len < 3) { + if (len > 0 && len < 3) { ch = buf[0]; if (ch == '\n') ch = '0'; diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c index e8f047e86a3..80183a7e662 100644 --- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c +++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c @@ -986,12 +986,6 @@ static int __devinit synaptics_rmi4_probe input_set_abs_params(rmi4_data->input_dev, ABS_MT_TOUCH_MAJOR, 0, MAX_TOUCH_MAJOR, 0, 0); - retval = input_register_device(rmi4_data->input_dev); - if (retval) { - dev_err(&client->dev, "%s:input register failed\n", __func__); - goto err_input_register; - } - /* Clear interrupts */ synaptics_rmi4_i2c_block_read(rmi4_data, rmi4_data->fn01_data_base_addr + 1, intr_status, @@ -1003,15 +997,20 @@ static int __devinit synaptics_rmi4_probe if (retval) { dev_err(&client->dev, "%s:Unable to get attn irq %d\n", __func__, platformdata->irq_number); - goto err_request_irq; + goto err_unset_clientdata; + } + + retval = input_register_device(rmi4_data->input_dev); + if (retval) { + dev_err(&client->dev, "%s:input register failed\n", __func__); + goto err_free_irq; } return retval; -err_request_irq: +err_free_irq: free_irq(platformdata->irq_number, rmi4_data); - input_unregister_device(rmi4_data->input_dev); -err_input_register: +err_unset_clientdata: i2c_set_clientdata(client, NULL); err_query_dev: if (platformdata->regulator_en) { diff --git a/drivers/staging/tidspbridge/core/io_sm.c b/drivers/staging/tidspbridge/core/io_sm.c index 571864555dd..27e0aa81a58 100644 --- a/drivers/staging/tidspbridge/core/io_sm.c +++ b/drivers/staging/tidspbridge/core/io_sm.c @@ -949,7 +949,7 @@ func_end: * Calls the Bridge's CHNL_ISR to determine if this interrupt is ours, then * schedules a DPC to dispatch I/O. */ -void io_mbox_msg(u32 msg) +int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg) { struct io_mgr *pio_mgr; struct dev_object *dev_obj; @@ -959,9 +959,9 @@ void io_mbox_msg(u32 msg) dev_get_io_mgr(dev_obj, &pio_mgr); if (!pio_mgr) - return; + return NOTIFY_BAD; - pio_mgr->intr_val = (u16)msg; + pio_mgr->intr_val = (u16)((u32)msg); if (pio_mgr->intr_val & MBX_PM_CLASS) io_dispatch_pm(pio_mgr); @@ -973,7 +973,7 @@ void io_mbox_msg(u32 msg) spin_unlock_irqrestore(&pio_mgr->dpc_lock, flags); tasklet_schedule(&pio_mgr->dpc_tasklet); } - return; + return NOTIFY_OK; } /* diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c index a3b0a183d57..a3f69f6f505 100644 --- a/drivers/staging/tidspbridge/core/tiomap3430.c +++ b/drivers/staging/tidspbridge/core/tiomap3430.c @@ -223,6 +223,10 @@ static struct bridge_drv_interface drv_interface_fxns = { bridge_msg_set_queue_id, }; +static struct notifier_block dsp_mbox_notifier = { + .notifier_call = io_mbox_msg, +}; + static inline void flush_all(struct bridge_dev_context *dev_context) { if (dev_context->dw_brd_state == BRD_DSP_HIBERNATION || @@ -553,7 +557,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, * Enable Mailbox events and also drain any pending * stale messages. */ - dev_context->mbox = omap_mbox_get("dsp"); + dev_context->mbox = omap_mbox_get("dsp", &dsp_mbox_notifier); if (IS_ERR(dev_context->mbox)) { dev_context->mbox = NULL; pr_err("%s: Failed to get dsp mailbox handle\n", @@ -563,8 +567,6 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt, } if (!status) { - dev_context->mbox->rxq->callback = (int (*)(void *))io_mbox_msg; - /*PM_IVA2GRPSEL_PER = 0xC0;*/ temp = readl(resources->dw_per_pm_base + 0xA8); temp = (temp & 0xFFFFFF30) | 0xC0; @@ -685,7 +687,7 @@ static int bridge_brd_stop(struct bridge_dev_context *dev_ctxt) /* Disable the mailbox interrupts */ if (dev_context->mbox) { omap_mbox_disable_irq(dev_context->mbox, IRQ_RX); - omap_mbox_put(dev_context->mbox); + omap_mbox_put(dev_context->mbox, &dsp_mbox_notifier); dev_context->mbox = NULL; } /* Reset IVA2 clocks*/ @@ -786,10 +788,7 @@ static int bridge_dev_create(struct bridge_dev_context pt_attrs = kzalloc(sizeof(struct pg_table_attrs), GFP_KERNEL); if (pt_attrs != NULL) { - /* Assuming that we use only DSP's memory map - * until 0x4000:0000 , we would need only 1024 - * L1 enties i.e L1 size = 4K */ - pt_attrs->l1_size = 0x1000; + pt_attrs->l1_size = SZ_16K; /* 4096 entries of 32 bits */ align_size = pt_attrs->l1_size; /* Align sizes are expected to be power of 2 */ /* we like to get aligned on L1 table size */ diff --git a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h index 18aec55d864..8242c70e09d 100644 --- a/drivers/staging/tidspbridge/include/dspbridge/io_sm.h +++ b/drivers/staging/tidspbridge/include/dspbridge/io_sm.h @@ -72,22 +72,17 @@ extern void io_dpc(unsigned long ref_data); /* * ======== io_mbox_msg ======== * Purpose: - * Main interrupt handler for the shared memory Bridge channel manager. - * Calls the Bridge's chnlsm_isr to determine if this interrupt is ours, - * then schedules a DPC to dispatch I/O. + * Main message handler for the shared memory Bridge channel manager. + * Determine if this message is ours, then schedules a DPC to + * dispatch I/O. * Parameters: - * ref_data: Pointer to the channel manager object for this board. - * Set in an initial call to ISR_Install(). + * self: Pointer to its own notifier_block struct. + * len: Length of message. + * msg: Message code received. * Returns: - * TRUE if interrupt handled; FALSE otherwise. - * Requires: - * Must be in locked memory if executing in kernel mode. - * Must only call functions which are in locked memory if Kernel mode. - * Must only call asynchronous services. - * Interrupts are disabled and EOI for this interrupt has been sent. - * Ensures: + * NOTIFY_OK if handled; NOTIFY_BAD otherwise. */ -void io_mbox_msg(u32 msg); +int io_mbox_msg(struct notifier_block *self, unsigned long len, void *msg); /* * ======== io_request_chnl ======== diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h index 30dbfb6d16f..d73267961ef 100644 --- a/drivers/staging/usbip/stub.h +++ b/drivers/staging/usbip/stub.h @@ -32,6 +32,7 @@ struct stub_device { struct usb_interface *interface; + struct usb_device *udev; struct list_head list; struct usbip_device ud; diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c index b186b5fed2b..a7ce51cc890 100644 --- a/drivers/staging/usbip/stub_dev.c +++ b/drivers/staging/usbip/stub_dev.c @@ -258,10 +258,11 @@ static void stub_shutdown_connection(struct usbip_device *ud) static void stub_device_reset(struct usbip_device *ud) { struct stub_device *sdev = container_of(ud, struct stub_device, ud); - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; int ret; usbip_udbg("device reset"); + ret = usb_lock_device_for_reset(udev, sdev->interface); if (ret < 0) { dev_err(&udev->dev, "lock for reset\n"); @@ -309,7 +310,8 @@ static void stub_device_unusable(struct usbip_device *ud) * * Allocates and initializes a new stub_device struct. */ -static struct stub_device *stub_device_alloc(struct usb_interface *interface) +static struct stub_device *stub_device_alloc(struct usb_device *udev, + struct usb_interface *interface) { struct stub_device *sdev; int busnum = interface_to_busnum(interface); @@ -324,7 +326,8 @@ static struct stub_device *stub_device_alloc(struct usb_interface *interface) return NULL; } - sdev->interface = interface; + sdev->interface = usb_get_intf(interface); + sdev->udev = usb_get_dev(udev); /* * devid is defined with devnum when this driver is first allocated. @@ -450,11 +453,12 @@ static int stub_probe(struct usb_interface *interface, return err; } + usb_get_intf(interface); return 0; } /* ok. this is my device. */ - sdev = stub_device_alloc(interface); + sdev = stub_device_alloc(udev, interface); if (!sdev) return -ENOMEM; @@ -476,6 +480,8 @@ static int stub_probe(struct usb_interface *interface, dev_err(&interface->dev, "create sysfs files for %s\n", udev_busid); usb_set_intfdata(interface, NULL); + usb_put_intf(interface); + busid_priv->interf_count = 0; busid_priv->sdev = NULL; @@ -545,6 +551,7 @@ static void stub_disconnect(struct usb_interface *interface) if (busid_priv->interf_count > 1) { busid_priv->interf_count--; shutdown_busid(busid_priv); + usb_put_intf(interface); return; } @@ -554,6 +561,9 @@ static void stub_disconnect(struct usb_interface *interface) /* 1. shutdown the current connection */ shutdown_busid(busid_priv); + usb_put_dev(sdev->udev); + usb_put_intf(interface); + /* 3. free sdev */ busid_priv->sdev = NULL; stub_device_free(sdev); diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c index 3de6fd2539d..ae6ac82754a 100644 --- a/drivers/staging/usbip/stub_rx.c +++ b/drivers/staging/usbip/stub_rx.c @@ -364,7 +364,7 @@ static struct stub_priv *stub_priv_alloc(struct stub_device *sdev, static int get_pipe(struct stub_device *sdev, int epnum, int dir) { - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; struct usb_host_endpoint *ep; struct usb_endpoint_descriptor *epd = NULL; @@ -484,7 +484,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev, int ret; struct stub_priv *priv; struct usbip_device *ud = &sdev->ud; - struct usb_device *udev = interface_to_usbdev(sdev->interface); + struct usb_device *udev = sdev->udev; int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction); diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 41a1fe5138f..afc3b1a7188 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h @@ -100,9 +100,6 @@ struct vhci_hcd { * But, the index of this array begins from 0. */ struct vhci_device vdev[VHCI_NPORTS]; - - /* vhci_device which has not been assiged its address yet */ - int pending_port; }; @@ -119,6 +116,9 @@ void rh_port_disconnect(int rhport); void vhci_rx_loop(struct usbip_task *ut); void vhci_tx_loop(struct usbip_task *ut); +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, + __u32 seqnum); + #define hardware (&the_controller->pdev.dev) static inline struct vhci_device *port_to_vdev(__u32 port) diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 08bd26a245d..a35fe61268d 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -138,8 +138,6 @@ void rh_port_connect(int rhport, enum usb_device_speed speed) * the_controller->vdev[rhport].ud.status = VDEV_CONNECT; * spin_unlock(&the_controller->vdev[rhport].ud.lock); */ - the_controller->pending_port = rhport; - spin_unlock_irqrestore(&the_controller->lock, flags); usb_hcd_poll_rh_status(vhci_to_hcd(the_controller)); @@ -559,6 +557,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, struct device *dev = &urb->dev->dev; int ret = 0; unsigned long flags; + struct vhci_device *vdev; usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n", hcd, urb, mem_flags); @@ -574,6 +573,18 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, return urb->status; } + vdev = port_to_vdev(urb->dev->portnum-1); + + /* refuse enqueue for dead connection */ + spin_lock(&vdev->ud.lock); + if (vdev->ud.status == VDEV_ST_NULL || vdev->ud.status == VDEV_ST_ERROR) { + usbip_uerr("enqueue for inactive port %d\n", vdev->rhport); + spin_unlock(&vdev->ud.lock); + spin_unlock_irqrestore(&the_controller->lock, flags); + return -ENODEV; + } + spin_unlock(&vdev->ud.lock); + ret = usb_hcd_link_urb_to_ep(hcd, urb); if (ret) goto no_need_unlink; @@ -592,8 +603,6 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, __u8 type = usb_pipetype(urb->pipe); struct usb_ctrlrequest *ctrlreq = (struct usb_ctrlrequest *) urb->setup_packet; - struct vhci_device *vdev = - port_to_vdev(the_controller->pending_port); if (type != PIPE_CONTROL || !ctrlreq) { dev_err(dev, "invalid request to devnum 0\n"); @@ -607,7 +616,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, dev_info(dev, "SetAddress Request (%d) to port %d\n", ctrlreq->wValue, vdev->rhport); - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); spin_lock(&vdev->ud.lock); vdev->ud.status = VDEV_ST_USED; @@ -627,8 +638,9 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, "Get_Descriptor to device 0 " "(get max pipe size)\n"); - /* FIXME: reference count? (usb_get_dev()) */ - vdev->udev = urb->dev; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = usb_get_dev(urb->dev); goto out; default: @@ -805,7 +817,6 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) return 0; } - static void vhci_device_unlink_cleanup(struct vhci_device *vdev) { struct vhci_unlink *unlink, *tmp; @@ -813,11 +824,34 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) spin_lock(&vdev->priv_lock); list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { + usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum); list_del(&unlink->list); kfree(unlink); } list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { + struct urb *urb; + + /* give back URB of unanswered unlink request */ + usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum); + + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + if (!urb) { + usbip_uinfo("the urb (seqnum %lu) was already given back\n", + unlink->unlink_seqnum); + list_del(&unlink->list); + kfree(unlink); + continue; + } + + urb->status = -ENODEV; + + spin_lock(&the_controller->lock); + usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); + spin_unlock(&the_controller->lock); + + usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); + list_del(&unlink->list); kfree(unlink); } @@ -887,6 +921,10 @@ static void vhci_device_reset(struct usbip_device *ud) vdev->speed = 0; vdev->devid = 0; + if (vdev->udev) + usb_put_dev(vdev->udev); + vdev->udev = NULL; + ud->tcp_socket = NULL; ud->status = VDEV_ST_NULL; diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 8147d7202b2..bf699147094 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c @@ -23,16 +23,14 @@ #include "vhci.h" -/* get URB from transmitted urb queue */ -static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, +/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */ +struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum) { struct vhci_priv *priv, *tmp; struct urb *urb = NULL; int status; - spin_lock(&vdev->priv_lock); - list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { if (priv->seqnum == seqnum) { urb = priv->urb; @@ -63,8 +61,6 @@ static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, } } - spin_unlock(&vdev->priv_lock); - return urb; } @@ -74,9 +70,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, struct usbip_device *ud = &vdev->ud; struct urb *urb; + spin_lock(&vdev->priv_lock); urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); + spin_unlock(&vdev->priv_lock); if (!urb) { usbip_uerr("cannot find a urb of seqnum %u\n", @@ -161,7 +159,12 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } + spin_lock(&vdev->priv_lock); + urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); + + spin_unlock(&vdev->priv_lock); + if (!urb) { /* * I get the result of a unlink request. But, it seems that I @@ -190,6 +193,19 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, return; } +static int vhci_priv_tx_empty(struct vhci_device *vdev) +{ + int empty = 0; + + spin_lock(&vdev->priv_lock); + + empty = list_empty(&vdev->priv_rx); + + spin_unlock(&vdev->priv_lock); + + return empty; +} + /* recv a pdu */ static void vhci_rx_pdu(struct usbip_device *ud) { @@ -202,11 +218,29 @@ static void vhci_rx_pdu(struct usbip_device *ud) memset(&pdu, 0, sizeof(pdu)); - /* 1. receive a pdu header */ ret = usbip_xmit(0, ud->tcp_socket, (char *) &pdu, sizeof(pdu), 0); + if (ret < 0) { + if (ret == -ECONNRESET) + usbip_uinfo("connection reset by peer\n"); + else if (ret == -EAGAIN) { + /* ignore if connection was idle */ + if (vhci_priv_tx_empty(vdev)) + return; + usbip_uinfo("connection timed out with pending urbs\n"); + } else if (ret != -ERESTARTSYS) + usbip_uinfo("xmit failed %d\n", ret); + + usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); + return; + } + if (ret == 0) { + usbip_uinfo("connection closed"); + usbip_event_add(ud, VDEV_EVENT_DOWN); + return; + } if (ret != sizeof(pdu)) { - usbip_uerr("receiving pdu failed! size is %d, should be %d\n", + usbip_uerr("received pdu size is %d, should be %d\n", ret, (unsigned int)sizeof(pdu)); usbip_event_add(ud, VDEV_EVENT_ERROR_TCP); return; diff --git a/drivers/staging/vme/bridges/Module.symvers b/drivers/staging/vme/bridges/Module.symvers deleted file mode 100644 index e69de29bb2d..00000000000 --- a/drivers/staging/vme/bridges/Module.symvers +++ /dev/null diff --git a/drivers/staging/xgifb/vb_setmode.c b/drivers/staging/xgifb/vb_setmode.c index 7016fdd2509..e19b932492e 100644 --- a/drivers/staging/xgifb/vb_setmode.c +++ b/drivers/staging/xgifb/vb_setmode.c @@ -3954,8 +3954,8 @@ void XGI_GetCRT2ResInfo(unsigned short ModeNo, unsigned short ModeIdIndex, unsigned char XGI_IsLCDDualLink(struct vb_device_info *pVBInfo) { - if ((((pVBInfo->VBInfo & SetCRT2ToLCD) | SetCRT2ToLCDA)) - && (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ + if ((pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) && + (pVBInfo->LCDInfo & SetLCDDualLink)) /* shampoo0129 */ return 1; return 0; @@ -8773,7 +8773,7 @@ unsigned short XGI_GetVCLK2Ptr(unsigned short ModeNo, if (pVBInfo->IF_DEF_LVDS == 0) { CRT2Index = CRT2Index >> 6; /* for LCD */ - if (((pVBInfo->VBInfo & SetCRT2ToLCD) | SetCRT2ToLCDA)) { /*301b*/ + if (pVBInfo->VBInfo & (SetCRT2ToLCD | SetCRT2ToLCDA)) { /*301b*/ if (pVBInfo->LCDResInfo != Panel1024x768) VCLKIndex = LCDXlat2VCLK[CRT2Index]; else diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index 47d32281032..52fc0c9a636 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -581,8 +581,9 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, __u8 __user *buf, size_t nr) { struct n_hdlc *n_hdlc = tty2n_hdlc(tty); - int ret; + int ret = 0; struct n_hdlc_buf *rbuf; + DECLARE_WAITQUEUE(wait, current); if (debuglevel >= DEBUG_LEVEL_INFO) printk("%s(%d)n_hdlc_tty_read() called\n",__FILE__,__LINE__); @@ -598,57 +599,55 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, return -EFAULT; } - tty_lock(); + add_wait_queue(&tty->read_wait, &wait); for (;;) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - tty_unlock(); - return -EIO; + ret = -EIO; + break; } + if (tty_hung_up_p(file)) + break; - n_hdlc = tty2n_hdlc (tty); - if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || - tty != n_hdlc->tty) { - tty_unlock(); - return 0; - } + set_current_state(TASK_INTERRUPTIBLE); rbuf = n_hdlc_buf_get(&n_hdlc->rx_buf_list); - if (rbuf) + if (rbuf) { + if (rbuf->count > nr) { + /* too large for caller's buffer */ + ret = -EOVERFLOW; + } else { + if (copy_to_user(buf, rbuf->buf, rbuf->count)) + ret = -EFAULT; + else + ret = rbuf->count; + } + + if (n_hdlc->rx_free_buf_list.count > + DEFAULT_RX_BUF_COUNT) + kfree(rbuf); + else + n_hdlc_buf_put(&n_hdlc->rx_free_buf_list, rbuf); break; + } /* no data */ if (file->f_flags & O_NONBLOCK) { - tty_unlock(); - return -EAGAIN; + ret = -EAGAIN; + break; } - - interruptible_sleep_on (&tty->read_wait); + + schedule(); + if (signal_pending(current)) { - tty_unlock(); - return -EINTR; + ret = -EINTR; + break; } } - - if (rbuf->count > nr) - /* frame too large for caller's buffer (discard frame) */ - ret = -EOVERFLOW; - else { - /* Copy the data to the caller's buffer */ - if (copy_to_user(buf, rbuf->buf, rbuf->count)) - ret = -EFAULT; - else - ret = rbuf->count; - } - - /* return HDLC buffer to free list unless the free list */ - /* count has exceeded the default value, in which case the */ - /* buffer is freed back to the OS to conserve memory */ - if (n_hdlc->rx_free_buf_list.count > DEFAULT_RX_BUF_COUNT) - kfree(rbuf); - else - n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); - tty_unlock(); + + remove_wait_queue(&tty->read_wait, &wait); + __set_current_state(TASK_RUNNING); + return ret; } /* end of n_hdlc_tty_read() */ @@ -691,14 +690,15 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, count = maxframe; } - tty_lock(); - add_wait_queue(&tty->write_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); + + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); - /* Allocate transmit buffer */ - /* sleep until transmit buffer available */ - while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { + tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list); + if (tbuf) + break; + if (file->f_flags & O_NONBLOCK) { error = -EAGAIN; break; @@ -719,7 +719,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, } } - set_current_state(TASK_RUNNING); + __set_current_state(TASK_RUNNING); remove_wait_queue(&tty->write_wait, &wait); if (!error) { @@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); n_hdlc_send_frames(n_hdlc,tty); } - tty_unlock(); + return error; } /* end of n_hdlc_tty_write() */ diff --git a/drivers/tty/serial/8250.c b/drivers/tty/serial/8250.c index b25e6e49053..3975df6f7fd 100644 --- a/drivers/tty/serial/8250.c +++ b/drivers/tty/serial/8250.c @@ -236,7 +236,8 @@ static const struct serial8250_config uart_config[] = { .fifo_size = 128, .tx_loadsz = 128, .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, - .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP, + /* UART_CAP_EFR breaks billionon CF bluetooth card. */ + .flags = UART_CAP_FIFO | UART_CAP_SLEEP, }, [PORT_16654] = { .name = "ST16654", diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index b1682d7f1d8..2b8334601c8 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1518,6 +1518,7 @@ config SERIAL_BCM63XX_CONSOLE config SERIAL_GRLIB_GAISLER_APBUART tristate "GRLIB APBUART serial support" depends on OF + select SERIAL_CORE ---help--- Add support for the GRLIB APBUART serial port. diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6158eae0f64..0065da4b11c 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3257,7 +3257,7 @@ static ssize_t show_cons_active(struct device *dev, ssize_t count = 0; console_lock(); - for (c = console_drivers; c; c = c->next) { + for_each_console(c) { if (!c->device) continue; if (!c->write) @@ -3306,7 +3306,7 @@ int __init tty_init(void) if (IS_ERR(consdev)) consdev = NULL; else - device_create_file(consdev, &dev_attr_active); + WARN_ON(device_create_file(consdev, &dev_attr_active) < 0); #ifdef CONFIG_VT vty_init(&console_fops); diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index b230bd3f056..147ede3423d 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -2994,7 +2994,7 @@ int __init vty_init(const struct file_operations *console_fops) if (IS_ERR(tty0dev)) tty0dev = NULL; else - device_create_file(tty0dev, &dev_attr_active); + WARN_ON(device_create_file(tty0dev, &dev_attr_active) < 0); vcs_init(); @@ -3545,7 +3545,7 @@ int register_con_driver(const struct consw *csw, int first, int last) /* already registered */ if (con_driver->con == csw) - retval = -EINVAL; + retval = -EBUSY; } if (retval) @@ -3656,7 +3656,12 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt) int err; err = register_con_driver(csw, first, last); - + /* if we get an busy error we still want to bind the console driver + * and return success, as we may have unbound the console driver + Â * but not unregistered it. + */ + if (err == -EBUSY) + err = 0; if (!err) bind_con_driver(csw, first, last, deflt); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 6ee4451bfe2..47085e5879a 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -342,7 +342,7 @@ static ssize_t wdm_write goto outnp; } - if (!file->f_flags && O_NONBLOCK) + if (!(file->f_flags & O_NONBLOCK)) r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); else diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 9da25056302..df502a98d0d 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -192,12 +192,12 @@ int usb_create_ep_devs(struct device *parent, ep_dev->dev.parent = parent; ep_dev->dev.release = ep_device_release; dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); - device_enable_async_suspend(&ep_dev->dev); retval = device_register(&ep_dev->dev); if (retval) goto error_register; + device_enable_async_suspend(&ep_dev->dev); endpoint->ep_dev = ep_dev; return retval; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index b55d46070a2..f71e8e307e0 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -405,7 +405,12 @@ static int suspend_common(struct device *dev, bool do_wakeup) return retval; } - synchronize_irq(pci_dev->irq); + /* If MSI-X is enabled, the driver will have synchronized all vectors + * in pci_suspend(). If MSI or legacy PCI is enabled, that will be + * synchronized here. + */ + if (!hcd->msix_enabled) + synchronize_irq(pci_dev->irq); /* Downstream ports from this root hub should already be quiesced, so * there will be no DMA activity. Now we can shut down the upstream diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b98efae6a1c..4310cc4b1cb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -676,6 +676,8 @@ static void hub_init_func3(struct work_struct *ws); static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) { struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd; + int ret; int port1; int status; bool need_debounce_delay = false; @@ -714,6 +716,25 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) usb_autopm_get_interface_no_resume( to_usb_interface(hub->intfdev)); return; /* Continues at init2: below */ + } else if (type == HUB_RESET_RESUME) { + /* The internal host controller state for the hub device + * may be gone after a host power loss on system resume. + * Update the device's info so the HW knows it's a hub. + */ + hcd = bus_to_hcd(hdev->bus); + if (hcd->driver->update_hub_device) { + ret = hcd->driver->update_hub_device(hcd, hdev, + &hub->tt, GFP_NOIO); + if (ret < 0) { + dev_err(hub->intfdev, "Host not " + "accepting hub info " + "update.\n"); + dev_err(hub->intfdev, "LS/FS devices " + "and hubs may not work " + "under this hub\n."); + } + } + hub_power_on(hub, true); } else { hub_power_on(hub, true); } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 1dc9739277b..06bb9d4587e 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -509,7 +509,7 @@ config USB_LANGWELL select USB_GADGET_SELECTED config USB_GADGET_EG20T - boolean "Intel EG20T(Topcliff) USB Device controller" + boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC" depends on PCI select USB_GADGET_DUALSPEED help @@ -525,6 +525,11 @@ config USB_GADGET_EG20T This driver dose not support interrupt transfer or isochronous transfer modes. + This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is + for IVI(In-Vehicle Infotainment) use. + ML7213 is companion chip for Intel Atom E6xx series. + ML7213 is completely compatible for Intel EG20T PCH. + config USB_EG20T tristate depends on USB_GADGET_EG20T diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 31656a2b4ab..a1c67ae1572 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -76,10 +76,21 @@ static DEFINE_SPINLOCK(udc_lock); /* control endpoint description */ static const struct usb_endpoint_descriptor -ctrl_endpt_desc = { +ctrl_endpt_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_CONTROL, + .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), +}; + +static const struct usb_endpoint_descriptor +ctrl_endpt_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, .wMaxPacketSize = cpu_to_le16(CTRL_PAYLOAD_MAX), }; @@ -265,10 +276,10 @@ static int hw_device_init(void __iomem *base) hw_bank.size /= sizeof(u32); reg = hw_aread(ABS_DCCPARAMS, DCCPARAMS_DEN) >> ffs_nr(DCCPARAMS_DEN); - if (reg == 0 || reg > ENDPT_MAX) - return -ENODEV; + hw_ep_max = reg * 2; /* cache hw ENDPT_MAX */ - hw_ep_max = reg; /* cache hw ENDPT_MAX */ + if (hw_ep_max == 0 || hw_ep_max > ENDPT_MAX) + return -ENODEV; /* setup lock mode ? */ @@ -1197,16 +1208,17 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr, } spin_lock_irqsave(udc->lock, flags); - for (i = 0; i < hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < hw_ep_max/2; i++) { + struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i]; + struct ci13xxx_ep *mEpTx = &udc->ci13xxx_ep[i + hw_ep_max/2]; n += scnprintf(buf + n, PAGE_SIZE - n, "EP=%02i: RX=%08X TX=%08X\n", - i, (u32)mEp->qh[RX].dma, (u32)mEp->qh[TX].dma); + i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma); for (j = 0; j < (sizeof(struct ci13xxx_qh)/sizeof(u32)); j++) { n += scnprintf(buf + n, PAGE_SIZE - n, " %04X: %08X %08X\n", j, - *((u32 *)mEp->qh[RX].ptr + j), - *((u32 *)mEp->qh[TX].ptr + j)); + *((u32 *)mEpRx->qh.ptr + j), + *((u32 *)mEpTx->qh.ptr + j)); } } spin_unlock_irqrestore(udc->lock, flags); @@ -1293,7 +1305,7 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr, unsigned long flags; struct list_head *ptr = NULL; struct ci13xxx_req *req = NULL; - unsigned i, j, k, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); + unsigned i, j, n = 0, qSize = sizeof(struct ci13xxx_td)/sizeof(u32); dbg_trace("[%s] %p\n", __func__, buf); if (attr == NULL || buf == NULL) { @@ -1303,22 +1315,20 @@ static ssize_t show_requests(struct device *dev, struct device_attribute *attr, spin_lock_irqsave(udc->lock, flags); for (i = 0; i < hw_ep_max; i++) - for (k = RX; k <= TX; k++) - list_for_each(ptr, &udc->ci13xxx_ep[i].qh[k].queue) - { - req = list_entry(ptr, - struct ci13xxx_req, queue); + list_for_each(ptr, &udc->ci13xxx_ep[i].qh.queue) + { + req = list_entry(ptr, struct ci13xxx_req, queue); + + n += scnprintf(buf + n, PAGE_SIZE - n, + "EP=%02i: TD=%08X %s\n", + i % hw_ep_max/2, (u32)req->dma, + ((i < hw_ep_max/2) ? "RX" : "TX")); + for (j = 0; j < qSize; j++) n += scnprintf(buf + n, PAGE_SIZE - n, - "EP=%02i: TD=%08X %s\n", - i, (u32)req->dma, - ((k == RX) ? "RX" : "TX")); - - for (j = 0; j < qSize; j++) - n += scnprintf(buf + n, PAGE_SIZE - n, - " %04X: %08X\n", j, - *((u32 *)req->ptr + j)); - } + " %04X: %08X\n", j, + *((u32 *)req->ptr + j)); + } spin_unlock_irqrestore(udc->lock, flags); return n; @@ -1467,12 +1477,12 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq) * At this point it's guaranteed exclusive access to qhead * (endpt is not primed) so it's no need to use tripwire */ - mEp->qh[mEp->dir].ptr->td.next = mReq->dma; /* TERMINATE = 0 */ - mEp->qh[mEp->dir].ptr->td.token &= ~TD_STATUS; /* clear status */ + mEp->qh.ptr->td.next = mReq->dma; /* TERMINATE = 0 */ + mEp->qh.ptr->td.token &= ~TD_STATUS; /* clear status */ if (mReq->req.zero == 0) - mEp->qh[mEp->dir].ptr->cap |= QH_ZLT; + mEp->qh.ptr->cap |= QH_ZLT; else - mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; + mEp->qh.ptr->cap &= ~QH_ZLT; wmb(); /* synchronize before ep prime */ @@ -1542,11 +1552,11 @@ __acquires(mEp->lock) hw_ep_flush(mEp->num, mEp->dir); - while (!list_empty(&mEp->qh[mEp->dir].queue)) { + while (!list_empty(&mEp->qh.queue)) { /* pop oldest request */ struct ci13xxx_req *mReq = \ - list_entry(mEp->qh[mEp->dir].queue.next, + list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); list_del_init(&mReq->queue); mReq->req.status = -ESHUTDOWN; @@ -1571,8 +1581,6 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) { struct usb_ep *ep; struct ci13xxx *udc = container_of(gadget, struct ci13xxx, gadget); - struct ci13xxx_ep *mEp = container_of(gadget->ep0, - struct ci13xxx_ep, ep); trace("%p", gadget); @@ -1583,7 +1591,8 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) gadget_for_each_ep(ep, gadget) { usb_ep_fifo_flush(ep); } - usb_ep_fifo_flush(gadget->ep0); + usb_ep_fifo_flush(&udc->ep0out.ep); + usb_ep_fifo_flush(&udc->ep0in.ep); udc->driver->disconnect(gadget); @@ -1591,11 +1600,12 @@ static int _gadget_stop_activity(struct usb_gadget *gadget) gadget_for_each_ep(ep, gadget) { usb_ep_disable(ep); } - usb_ep_disable(gadget->ep0); + usb_ep_disable(&udc->ep0out.ep); + usb_ep_disable(&udc->ep0in.ep); - if (mEp->status != NULL) { - usb_ep_free_request(gadget->ep0, mEp->status); - mEp->status = NULL; + if (udc->status != NULL) { + usb_ep_free_request(&udc->ep0in.ep, udc->status); + udc->status = NULL; } return 0; @@ -1614,7 +1624,6 @@ static void isr_reset_handler(struct ci13xxx *udc) __releases(udc->lock) __acquires(udc->lock) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[0]; int retval; trace("%p", udc); @@ -1635,11 +1644,15 @@ __acquires(udc->lock) if (retval) goto done; - retval = usb_ep_enable(&mEp->ep, &ctrl_endpt_desc); + retval = usb_ep_enable(&udc->ep0out.ep, &ctrl_endpt_out_desc); + if (retval) + goto done; + + retval = usb_ep_enable(&udc->ep0in.ep, &ctrl_endpt_in_desc); if (!retval) { - mEp->status = usb_ep_alloc_request(&mEp->ep, GFP_ATOMIC); - if (mEp->status == NULL) { - usb_ep_disable(&mEp->ep); + udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC); + if (udc->status == NULL) { + usb_ep_disable(&udc->ep0out.ep); retval = -ENOMEM; } } @@ -1672,16 +1685,17 @@ static void isr_get_status_complete(struct usb_ep *ep, struct usb_request *req) /** * isr_get_status_response: get_status request response - * @ep: endpoint + * @udc: udc struct * @setup: setup request packet * * This function returns an error code */ -static int isr_get_status_response(struct ci13xxx_ep *mEp, +static int isr_get_status_response(struct ci13xxx *udc, struct usb_ctrlrequest *setup) __releases(mEp->lock) __acquires(mEp->lock) { + struct ci13xxx_ep *mEp = &udc->ep0in; struct usb_request *req = NULL; gfp_t gfp_flags = GFP_ATOMIC; int dir, num, retval; @@ -1736,27 +1750,23 @@ __acquires(mEp->lock) /** * isr_setup_status_phase: queues the status phase of a setup transation - * @mEp: endpoint + * @udc: udc struct * * This function returns an error code */ -static int isr_setup_status_phase(struct ci13xxx_ep *mEp) +static int isr_setup_status_phase(struct ci13xxx *udc) __releases(mEp->lock) __acquires(mEp->lock) { int retval; + struct ci13xxx_ep *mEp; - trace("%p", mEp); - - /* mEp is always valid & configured */ - - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + trace("%p", udc); - mEp->status->no_interrupt = 1; + mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in; spin_unlock(mEp->lock); - retval = usb_ep_queue(&mEp->ep, mEp->status, GFP_ATOMIC); + retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC); spin_lock(mEp->lock); return retval; @@ -1778,11 +1788,11 @@ __acquires(mEp->lock) trace("%p", mEp); - if (list_empty(&mEp->qh[mEp->dir].queue)) + if (list_empty(&mEp->qh.queue)) return -EINVAL; /* pop oldest request */ - mReq = list_entry(mEp->qh[mEp->dir].queue.next, + mReq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); list_del_init(&mReq->queue); @@ -1794,10 +1804,10 @@ __acquires(mEp->lock) dbg_done(_usb_addr(mEp), mReq->ptr->token, retval); - if (!list_empty(&mEp->qh[mEp->dir].queue)) { + if (!list_empty(&mEp->qh.queue)) { struct ci13xxx_req* mReqEnq; - mReqEnq = list_entry(mEp->qh[mEp->dir].queue.next, + mReqEnq = list_entry(mEp->qh.queue.next, struct ci13xxx_req, queue); _hardware_enqueue(mEp, mReqEnq); } @@ -1836,16 +1846,14 @@ __acquires(udc->lock) int type, num, err = -EINVAL; struct usb_ctrlrequest req; - if (mEp->desc == NULL) continue; /* not configured */ - if ((mEp->dir == RX && hw_test_and_clear_complete(i)) || - (mEp->dir == TX && hw_test_and_clear_complete(i + 16))) { + if (hw_test_and_clear_complete(i)) { err = isr_tr_complete_low(mEp); if (mEp->type == USB_ENDPOINT_XFER_CONTROL) { if (err > 0) /* needs status phase */ - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); if (err < 0) { dbg_event(_usb_addr(mEp), "ERROR", err); @@ -1866,15 +1874,22 @@ __acquires(udc->lock) continue; } + /* + * Flush data and handshake transactions of previous + * setup packet. + */ + _ep_nuke(&udc->ep0out); + _ep_nuke(&udc->ep0in); + /* read_setup_packet */ do { hw_test_and_set_setup_guard(); - memcpy(&req, &mEp->qh[RX].ptr->setup, sizeof(req)); + memcpy(&req, &mEp->qh.ptr->setup, sizeof(req)); } while (!hw_test_and_clear_setup_guard()); type = req.bRequestType; - mEp->dir = (type & USB_DIR_IN) ? TX : RX; + udc->ep0_dir = (type & USB_DIR_IN) ? TX : RX; dbg_setup(_usb_addr(mEp), &req); @@ -1895,7 +1910,7 @@ __acquires(udc->lock) if (err) break; } - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; case USB_REQ_GET_STATUS: if (type != (USB_DIR_IN|USB_RECIP_DEVICE) && @@ -1905,7 +1920,7 @@ __acquires(udc->lock) if (le16_to_cpu(req.wLength) != 2 || le16_to_cpu(req.wValue) != 0) break; - err = isr_get_status_response(mEp, &req); + err = isr_get_status_response(udc, &req); break; case USB_REQ_SET_ADDRESS: if (type != (USB_DIR_OUT|USB_RECIP_DEVICE)) @@ -1916,7 +1931,7 @@ __acquires(udc->lock) err = hw_usb_set_address((u8)le16_to_cpu(req.wValue)); if (err) break; - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; case USB_REQ_SET_FEATURE: if (type != (USB_DIR_OUT|USB_RECIP_ENDPOINT) && @@ -1932,12 +1947,12 @@ __acquires(udc->lock) spin_lock(udc->lock); if (err) break; - err = isr_setup_status_phase(mEp); + err = isr_setup_status_phase(udc); break; default: delegate: if (req.wLength == 0) /* no data phase */ - mEp->dir = TX; + udc->ep0_dir = TX; spin_unlock(udc->lock); err = udc->driver->setup(&udc->gadget, &req); @@ -1968,7 +1983,7 @@ static int ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { struct ci13xxx_ep *mEp = container_of(ep, struct ci13xxx_ep, ep); - int direction, retval = 0; + int retval = 0; unsigned long flags; trace("%p, %p", ep, desc); @@ -1982,7 +1997,7 @@ static int ep_enable(struct usb_ep *ep, mEp->desc = desc; - if (!list_empty(&mEp->qh[mEp->dir].queue)) + if (!list_empty(&mEp->qh.queue)) warn("enabling a non-empty endpoint!"); mEp->dir = usb_endpoint_dir_in(desc) ? TX : RX; @@ -1991,29 +2006,22 @@ static int ep_enable(struct usb_ep *ep, mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); - direction = mEp->dir; - do { - dbg_event(_usb_addr(mEp), "ENABLE", 0); + dbg_event(_usb_addr(mEp), "ENABLE", 0); - mEp->qh[mEp->dir].ptr->cap = 0; + mEp->qh.ptr->cap = 0; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->qh[mEp->dir].ptr->cap |= QH_IOS; - else if (mEp->type == USB_ENDPOINT_XFER_ISOC) - mEp->qh[mEp->dir].ptr->cap &= ~QH_MULT; - else - mEp->qh[mEp->dir].ptr->cap &= ~QH_ZLT; - - mEp->qh[mEp->dir].ptr->cap |= - (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; - mEp->qh[mEp->dir].ptr->td.next |= TD_TERMINATE; /* needed? */ - - retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); + if (mEp->type == USB_ENDPOINT_XFER_CONTROL) + mEp->qh.ptr->cap |= QH_IOS; + else if (mEp->type == USB_ENDPOINT_XFER_ISOC) + mEp->qh.ptr->cap &= ~QH_MULT; + else + mEp->qh.ptr->cap &= ~QH_ZLT; - if (mEp->type == USB_ENDPOINT_XFER_CONTROL) - mEp->dir = (mEp->dir == TX) ? RX : TX; + mEp->qh.ptr->cap |= + (mEp->ep.maxpacket << ffs_nr(QH_MAX_PKT)) & QH_MAX_PKT; + mEp->qh.ptr->td.next |= TD_TERMINATE; /* needed? */ - } while (mEp->dir != direction); + retval |= hw_ep_enable(mEp->num, mEp->dir, mEp->type); spin_unlock_irqrestore(mEp->lock, flags); return retval; @@ -2146,7 +2154,7 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, spin_lock_irqsave(mEp->lock, flags); if (mEp->type == USB_ENDPOINT_XFER_CONTROL && - !list_empty(&mEp->qh[mEp->dir].queue)) { + !list_empty(&mEp->qh.queue)) { _ep_nuke(mEp); retval = -EOVERFLOW; warn("endpoint ctrl %X nuked", _usb_addr(mEp)); @@ -2170,9 +2178,9 @@ static int ep_queue(struct usb_ep *ep, struct usb_request *req, /* push request */ mReq->req.status = -EINPROGRESS; mReq->req.actual = 0; - list_add_tail(&mReq->queue, &mEp->qh[mEp->dir].queue); + list_add_tail(&mReq->queue, &mEp->qh.queue); - if (list_is_singular(&mEp->qh[mEp->dir].queue)) + if (list_is_singular(&mEp->qh.queue)) retval = _hardware_enqueue(mEp, mReq); if (retval == -EALREADY) { @@ -2199,7 +2207,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req) trace("%p, %p", ep, req); if (ep == NULL || req == NULL || mEp->desc == NULL || - list_empty(&mReq->queue) || list_empty(&mEp->qh[mEp->dir].queue)) + list_empty(&mReq->queue) || list_empty(&mEp->qh.queue)) return -EINVAL; spin_lock_irqsave(mEp->lock, flags); @@ -2244,7 +2252,7 @@ static int ep_set_halt(struct usb_ep *ep, int value) #ifndef STALL_IN /* g_file_storage MS compliant but g_zero fails chapter 9 compliance */ if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX && - !list_empty(&mEp->qh[mEp->dir].queue)) { + !list_empty(&mEp->qh.queue)) { spin_unlock_irqrestore(mEp->lock, flags); return -EAGAIN; } @@ -2355,7 +2363,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) if (is_active) { pm_runtime_get_sync(&_gadget->dev); hw_device_reset(udc); - hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); + hw_device_state(udc->ep0out.qh.dma); } else { hw_device_state(0); if (udc->udc_driver->notify_event) @@ -2390,7 +2398,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, int (*bind)(struct usb_gadget *)) { struct ci13xxx *udc = _udc; - unsigned long i, k, flags; + unsigned long flags; + int i, j; int retval = -ENOMEM; trace("%p", driver); @@ -2427,45 +2436,46 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, info("hw_ep_max = %d", hw_ep_max); - udc->driver = driver; udc->gadget.dev.driver = NULL; retval = 0; - for (i = 0; i < hw_ep_max; i++) { - struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; + for (i = 0; i < hw_ep_max/2; i++) { + for (j = RX; j <= TX; j++) { + int k = i + j * hw_ep_max/2; + struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[k]; - scnprintf(mEp->name, sizeof(mEp->name), "ep%i", (int)i); + scnprintf(mEp->name, sizeof(mEp->name), "ep%i%s", i, + (j == TX) ? "in" : "out"); - mEp->lock = udc->lock; - mEp->device = &udc->gadget.dev; - mEp->td_pool = udc->td_pool; + mEp->lock = udc->lock; + mEp->device = &udc->gadget.dev; + mEp->td_pool = udc->td_pool; - mEp->ep.name = mEp->name; - mEp->ep.ops = &usb_ep_ops; - mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; + mEp->ep.name = mEp->name; + mEp->ep.ops = &usb_ep_ops; + mEp->ep.maxpacket = CTRL_PAYLOAD_MAX; - /* this allocation cannot be random */ - for (k = RX; k <= TX; k++) { - INIT_LIST_HEAD(&mEp->qh[k].queue); + INIT_LIST_HEAD(&mEp->qh.queue); spin_unlock_irqrestore(udc->lock, flags); - mEp->qh[k].ptr = dma_pool_alloc(udc->qh_pool, - GFP_KERNEL, - &mEp->qh[k].dma); + mEp->qh.ptr = dma_pool_alloc(udc->qh_pool, GFP_KERNEL, + &mEp->qh.dma); spin_lock_irqsave(udc->lock, flags); - if (mEp->qh[k].ptr == NULL) + if (mEp->qh.ptr == NULL) retval = -ENOMEM; else - memset(mEp->qh[k].ptr, 0, - sizeof(*mEp->qh[k].ptr)); - } - if (i == 0) - udc->gadget.ep0 = &mEp->ep; - else + memset(mEp->qh.ptr, 0, sizeof(*mEp->qh.ptr)); + + /* skip ep0 out and in endpoints */ + if (i == 0) + continue; + list_add_tail(&mEp->ep.ep_list, &udc->gadget.ep_list); + } } if (retval) goto done; + udc->gadget.ep0 = &udc->ep0in.ep; /* bind gadget */ driver->driver.bus = NULL; udc->gadget.dev.driver = &driver->driver; @@ -2479,6 +2489,7 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, goto done; } + udc->driver = driver; pm_runtime_get_sync(&udc->gadget.dev); if (udc->udc_driver->flags & CI13XXX_PULLUP_ON_VBUS) { if (udc->vbus_active) { @@ -2490,14 +2501,12 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, } } - retval = hw_device_state(udc->ci13xxx_ep[0].qh[RX].dma); + retval = hw_device_state(udc->ep0out.qh.dma); if (retval) pm_runtime_put_sync(&udc->gadget.dev); done: spin_unlock_irqrestore(udc->lock, flags); - if (retval) - usb_gadget_unregister_driver(driver); return retval; } EXPORT_SYMBOL(usb_gadget_probe_driver); @@ -2510,7 +2519,7 @@ EXPORT_SYMBOL(usb_gadget_probe_driver); int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { struct ci13xxx *udc = _udc; - unsigned long i, k, flags; + unsigned long i, flags; trace("%p", driver); @@ -2546,17 +2555,14 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) for (i = 0; i < hw_ep_max; i++) { struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; - if (i == 0) - udc->gadget.ep0 = NULL; - else if (!list_empty(&mEp->ep.ep_list)) + if (!list_empty(&mEp->ep.ep_list)) list_del_init(&mEp->ep.ep_list); - for (k = RX; k <= TX; k++) - if (mEp->qh[k].ptr != NULL) - dma_pool_free(udc->qh_pool, - mEp->qh[k].ptr, mEp->qh[k].dma); + if (mEp->qh.ptr != NULL) + dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); } + udc->gadget.ep0 = NULL; udc->driver = NULL; spin_unlock_irqrestore(udc->lock, flags); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index f61fed07f76..a2492b65f98 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -20,7 +20,7 @@ * DEFINE *****************************************************************************/ #define CI13XXX_PAGE_SIZE 4096ul /* page size for TD's */ -#define ENDPT_MAX (16) +#define ENDPT_MAX (32) #define CTRL_PAYLOAD_MAX (64) #define RX (0) /* similar to USB_DIR_OUT but can be used as an index */ #define TX (1) /* similar to USB_DIR_IN but can be used as an index */ @@ -88,8 +88,7 @@ struct ci13xxx_ep { struct list_head queue; struct ci13xxx_qh *ptr; dma_addr_t dma; - } qh[2]; - struct usb_request *status; + } qh; int wedge; /* global resources */ @@ -119,9 +118,13 @@ struct ci13xxx { struct dma_pool *qh_pool; /* DMA pool for queue heads */ struct dma_pool *td_pool; /* DMA pool for transfer descs */ + struct usb_request *status; /* ep0 status request */ struct usb_gadget gadget; /* USB slave device */ struct ci13xxx_ep ci13xxx_ep[ENDPT_MAX]; /* extended endpts */ + u32 ep0_dir; /* ep0 direction */ +#define ep0out ci13xxx_ep[0] +#define ep0in ci13xxx_ep[16] struct usb_gadget_driver *driver; /* 3rd party gadget driver */ struct ci13xxx_udc_driver *udc_driver; /* device controller driver */ diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index f6ff8456d52..1ba4befe336 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -928,8 +928,9 @@ unknown: */ switch (ctrl->bRequestType & USB_RECIP_MASK) { case USB_RECIP_INTERFACE: - if (cdev->config) - f = cdev->config->interface[intf]; + if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; break; case USB_RECIP_ENDPOINT: diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index 0c8dd81dddc..b120dbb64d0 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -198,10 +198,10 @@ #define PCH_UDC_BRLEN 0x0F /* Burst length */ #define PCH_UDC_THLEN 0x1F /* Threshold length */ /* Value of EP Buffer Size */ -#define UDC_EP0IN_BUFF_SIZE 64 -#define UDC_EPIN_BUFF_SIZE 512 -#define UDC_EP0OUT_BUFF_SIZE 64 -#define UDC_EPOUT_BUFF_SIZE 512 +#define UDC_EP0IN_BUFF_SIZE 16 +#define UDC_EPIN_BUFF_SIZE 256 +#define UDC_EP0OUT_BUFF_SIZE 16 +#define UDC_EPOUT_BUFF_SIZE 256 /* Value of EP maximum packet size */ #define UDC_EP0IN_MAX_PKT_SIZE 64 #define UDC_EP0OUT_MAX_PKT_SIZE 64 @@ -351,7 +351,7 @@ struct pch_udc_dev { struct pci_pool *data_requests; struct pci_pool *stp_requests; dma_addr_t dma_addr; - unsigned long ep0out_buf[64]; + void *ep0out_buf; struct usb_ctrlrequest setup_data; unsigned long phys_addr; void __iomem *base_addr; @@ -361,6 +361,8 @@ struct pch_udc_dev { #define PCH_UDC_PCI_BAR 1 #define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808 +#define PCI_VENDOR_ID_ROHM 0x10DB +#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D static const char ep0_string[] = "ep0in"; static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */ @@ -1219,11 +1221,11 @@ static void complete_req(struct pch_udc_ep *ep, struct pch_udc_request *req, dev = ep->dev; if (req->dma_mapped) { if (ep->in) - pci_unmap_single(dev->pdev, req->req.dma, - req->req.length, PCI_DMA_TODEVICE); + dma_unmap_single(&dev->pdev->dev, req->req.dma, + req->req.length, DMA_TO_DEVICE); else - pci_unmap_single(dev->pdev, req->req.dma, - req->req.length, PCI_DMA_FROMDEVICE); + dma_unmap_single(&dev->pdev->dev, req->req.dma, + req->req.length, DMA_FROM_DEVICE); req->dma_mapped = 0; req->req.dma = DMA_ADDR_INVALID; } @@ -1414,7 +1416,6 @@ static void pch_udc_start_rxrequest(struct pch_udc_ep *ep, pch_udc_clear_dma(ep->dev, DMA_DIR_RX); td_data = req->td_data; - ep->td_data = req->td_data; /* Set the status bits for all descriptors */ while (1) { td_data->status = (td_data->status & ~PCH_UDC_BUFF_STS) | @@ -1613,15 +1614,19 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, if (usbreq->length && ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) { if (ep->in) - usbreq->dma = pci_map_single(dev->pdev, usbreq->buf, - usbreq->length, PCI_DMA_TODEVICE); + usbreq->dma = dma_map_single(&dev->pdev->dev, + usbreq->buf, + usbreq->length, + DMA_TO_DEVICE); else - usbreq->dma = pci_map_single(dev->pdev, usbreq->buf, - usbreq->length, PCI_DMA_FROMDEVICE); + usbreq->dma = dma_map_single(&dev->pdev->dev, + usbreq->buf, + usbreq->length, + DMA_FROM_DEVICE); req->dma_mapped = 1; } if (usbreq->length > 0) { - retval = prepare_dma(ep, req, gfp); + retval = prepare_dma(ep, req, GFP_ATOMIC); if (retval) goto probe_end; } @@ -1646,7 +1651,6 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq, pch_udc_wait_ep_stall(ep); pch_udc_ep_clear_nak(ep); pch_udc_enable_ep_interrupts(ep->dev, (1 << ep->num)); - pch_udc_set_dma(dev, DMA_DIR_TX); } } /* Now add this request to the ep's pending requests */ @@ -1926,6 +1930,7 @@ static void pch_udc_complete_receiver(struct pch_udc_ep *ep) PCH_UDC_BS_DMA_DONE) return; pch_udc_clear_dma(ep->dev, DMA_DIR_RX); + pch_udc_ep_set_ddptr(ep, 0); if ((req->td_data_last->status & PCH_UDC_RXTX_STS) != PCH_UDC_RTS_SUCC) { dev_err(&dev->pdev->dev, "Invalid RXTX status (0x%08x) " @@ -1963,7 +1968,7 @@ static void pch_udc_svc_data_in(struct pch_udc_dev *dev, int ep_num) u32 epsts; struct pch_udc_ep *ep; - ep = &dev->ep[2*ep_num]; + ep = &dev->ep[UDC_EPIN_IDX(ep_num)]; epsts = ep->epsts; ep->epsts = 0; @@ -2008,7 +2013,7 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) struct pch_udc_ep *ep; struct pch_udc_request *req = NULL; - ep = &dev->ep[2*ep_num + 1]; + ep = &dev->ep[UDC_EPOUT_IDX(ep_num)]; epsts = ep->epsts; ep->epsts = 0; @@ -2025,10 +2030,11 @@ static void pch_udc_svc_data_out(struct pch_udc_dev *dev, int ep_num) } if (epsts & UDC_EPSTS_HE) return; - if (epsts & UDC_EPSTS_RSS) + if (epsts & UDC_EPSTS_RSS) { pch_udc_ep_set_stall(ep); pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); + } if (epsts & UDC_EPSTS_RCS) { if (!dev->prot_stall) { pch_udc_ep_clear_stall(ep); @@ -2060,8 +2066,10 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev) { u32 epsts; struct pch_udc_ep *ep; + struct pch_udc_ep *ep_out; ep = &dev->ep[UDC_EP0IN_IDX]; + ep_out = &dev->ep[UDC_EP0OUT_IDX]; epsts = ep->epsts; ep->epsts = 0; @@ -2073,8 +2081,16 @@ static void pch_udc_svc_control_in(struct pch_udc_dev *dev) return; if (epsts & UDC_EPSTS_HE) return; - if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) + if ((epsts & UDC_EPSTS_TDC) && (!dev->stall)) { pch_udc_complete_transfer(ep); + pch_udc_clear_dma(dev, DMA_DIR_RX); + ep_out->td_data->status = (ep_out->td_data->status & + ~PCH_UDC_BUFF_STS) | + PCH_UDC_BS_HST_RDY; + pch_udc_ep_clear_nak(ep_out); + pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_ep_set_rrdy(ep_out); + } /* On IN interrupt, provide data if we have any */ if ((epsts & UDC_EPSTS_IN) && !(epsts & UDC_EPSTS_TDC) && !(epsts & UDC_EPSTS_TXEMPTY)) @@ -2102,11 +2118,9 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) dev->stall = 0; dev->ep[UDC_EP0IN_IDX].halted = 0; dev->ep[UDC_EP0OUT_IDX].halted = 0; - /* In data not ready */ - pch_udc_ep_set_nak(&(dev->ep[UDC_EP0IN_IDX])); dev->setup_data = ep->td_stp->request; pch_udc_init_setup_buff(ep->td_stp); - pch_udc_clear_dma(dev, DMA_DIR_TX); + pch_udc_clear_dma(dev, DMA_DIR_RX); pch_udc_ep_fifo_flush(&(dev->ep[UDC_EP0IN_IDX]), dev->ep[UDC_EP0IN_IDX].in); if ((dev->setup_data.bRequestType & USB_DIR_IN)) @@ -2122,14 +2136,23 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) setup_supported = dev->driver->setup(&dev->gadget, &dev->setup_data); spin_lock(&dev->lock); + + if (dev->setup_data.bRequestType & USB_DIR_IN) { + ep->td_data->status = (ep->td_data->status & + ~PCH_UDC_BUFF_STS) | + PCH_UDC_BS_HST_RDY; + pch_udc_ep_set_ddptr(ep, ep->td_data_phys); + } /* ep0 in returns data on IN phase */ if (setup_supported >= 0 && setup_supported < UDC_EP0IN_MAX_PKT_SIZE) { pch_udc_ep_clear_nak(&(dev->ep[UDC_EP0IN_IDX])); /* Gadget would have queued a request when * we called the setup */ - pch_udc_set_dma(dev, DMA_DIR_RX); - pch_udc_ep_clear_nak(ep); + if (!(dev->setup_data.bRequestType & USB_DIR_IN)) { + pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_ep_clear_nak(ep); + } } else if (setup_supported < 0) { /* if unsupported request, then stall */ pch_udc_ep_set_stall(&(dev->ep[UDC_EP0IN_IDX])); @@ -2142,22 +2165,13 @@ static void pch_udc_svc_control_out(struct pch_udc_dev *dev) } } else if ((((stat & UDC_EPSTS_OUT_MASK) >> UDC_EPSTS_OUT_SHIFT) == UDC_EPSTS_OUT_DATA) && !dev->stall) { - if (list_empty(&ep->queue)) { - dev_err(&dev->pdev->dev, "%s: No request\n", __func__); - ep->td_data->status = (ep->td_data->status & - ~PCH_UDC_BUFF_STS) | - PCH_UDC_BS_HST_RDY; - pch_udc_set_dma(dev, DMA_DIR_RX); - } else { - /* control write */ - /* next function will pickuo an clear the status */ + pch_udc_clear_dma(dev, DMA_DIR_RX); + pch_udc_ep_set_ddptr(ep, 0); + if (!list_empty(&ep->queue)) { ep->epsts = stat; - - pch_udc_svc_data_out(dev, 0); - /* re-program desc. pointer for possible ZLPs */ - pch_udc_ep_set_ddptr(ep, ep->td_data_phys); - pch_udc_set_dma(dev, DMA_DIR_RX); + pch_udc_svc_data_out(dev, PCH_UDC_EP0); } + pch_udc_set_dma(dev, DMA_DIR_RX); } pch_udc_ep_set_rrdy(ep); } @@ -2174,7 +2188,7 @@ static void pch_udc_postsvc_epinters(struct pch_udc_dev *dev, int ep_num) struct pch_udc_ep *ep; struct pch_udc_request *req; - ep = &dev->ep[2*ep_num]; + ep = &dev->ep[UDC_EPIN_IDX(ep_num)]; if (!list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct pch_udc_request, queue); pch_udc_enable_ep_interrupts(ep->dev, @@ -2196,13 +2210,13 @@ static void pch_udc_read_all_epstatus(struct pch_udc_dev *dev, u32 ep_intr) for (i = 0; i < PCH_UDC_USED_EP_NUM; i++) { /* IN */ if (ep_intr & (0x1 << i)) { - ep = &dev->ep[2*i]; + ep = &dev->ep[UDC_EPIN_IDX(i)]; ep->epsts = pch_udc_read_ep_status(ep); pch_udc_clear_ep_status(ep, ep->epsts); } /* OUT */ if (ep_intr & (0x10000 << i)) { - ep = &dev->ep[2*i+1]; + ep = &dev->ep[UDC_EPOUT_IDX(i)]; ep->epsts = pch_udc_read_ep_status(ep); pch_udc_clear_ep_status(ep, ep->epsts); } @@ -2563,9 +2577,6 @@ static void pch_udc_pcd_reinit(struct pch_udc_dev *dev) dev->ep[UDC_EP0IN_IDX].ep.maxpacket = UDC_EP0IN_MAX_PKT_SIZE; dev->ep[UDC_EP0OUT_IDX].ep.maxpacket = UDC_EP0OUT_MAX_PKT_SIZE; - dev->dma_addr = pci_map_single(dev->pdev, dev->ep0out_buf, 256, - PCI_DMA_FROMDEVICE); - /* remove ep0 in and out from the list. They have own pointer */ list_del_init(&dev->ep[UDC_EP0IN_IDX].ep.ep_list); list_del_init(&dev->ep[UDC_EP0OUT_IDX].ep.ep_list); @@ -2637,6 +2648,13 @@ static int init_dma_pools(struct pch_udc_dev *dev) dev->ep[UDC_EP0IN_IDX].td_stp_phys = 0; dev->ep[UDC_EP0IN_IDX].td_data = NULL; dev->ep[UDC_EP0IN_IDX].td_data_phys = 0; + + dev->ep0out_buf = kzalloc(UDC_EP0OUT_BUFF_SIZE * 4, GFP_KERNEL); + if (!dev->ep0out_buf) + return -ENOMEM; + dev->dma_addr = dma_map_single(&dev->pdev->dev, dev->ep0out_buf, + UDC_EP0OUT_BUFF_SIZE * 4, + DMA_FROM_DEVICE); return 0; } @@ -2700,7 +2718,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) pch_udc_disable_interrupts(dev, UDC_DEVINT_MSK); - /* Assues that there are no pending requets with this driver */ + /* Assures that there are no pending requests with this driver */ + driver->disconnect(&dev->gadget); driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; dev->driver = NULL; @@ -2750,6 +2769,11 @@ static void pch_udc_remove(struct pci_dev *pdev) pci_pool_destroy(dev->stp_requests); } + if (dev->dma_addr) + dma_unmap_single(&dev->pdev->dev, dev->dma_addr, + UDC_EP0OUT_BUFF_SIZE * 4, DMA_FROM_DEVICE); + kfree(dev->ep0out_buf); + pch_udc_exit(dev); if (dev->irq_registered) @@ -2792,11 +2816,7 @@ static int pch_udc_resume(struct pci_dev *pdev) int ret; pci_set_power_state(pdev, PCI_D0); - ret = pci_restore_state(pdev); - if (ret) { - dev_err(&pdev->dev, "%s: pci_restore_state failed\n", __func__); - return ret; - } + pci_restore_state(pdev); ret = pci_enable_device(pdev); if (ret) { dev_err(&pdev->dev, "%s: pci_enable_device failed\n", __func__); @@ -2914,6 +2934,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = { .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, .class_mask = 0xffffffff, }, + { + PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7213_IOH_UDC), + .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe, + .class_mask = 0xffffffff, + }, { 0 }, }; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 2fc8636316c..12ff6cffedc 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -131,31 +131,31 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static ushort __initdata idVendor; +static ushort idVendor; module_param(idVendor, ushort, S_IRUGO); MODULE_PARM_DESC(idVendor, "USB Vendor ID"); -static ushort __initdata idProduct; +static ushort idProduct; module_param(idProduct, ushort, S_IRUGO); MODULE_PARM_DESC(idProduct, "USB Product ID"); -static ushort __initdata bcdDevice; +static ushort bcdDevice; module_param(bcdDevice, ushort, S_IRUGO); MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); -static char *__initdata iManufacturer; +static char *iManufacturer; module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); -static char *__initdata iProduct; +static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); -static char *__initdata iSerialNum; +static char *iSerialNum; module_param(iSerialNum, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); -static char *__initdata iPNPstring; +static char *iPNPstring; module_param(iPNPstring, charp, S_IRUGO); MODULE_PARM_DESC(iPNPstring, "MFG:linux;MDL:g_printer;CLS:PRINTER;SN:1;"); @@ -1596,13 +1596,12 @@ cleanup(void) int status; mutex_lock(&usb_printer_gadget.lock_printer_io); - class_destroy(usb_gadget_class); - unregister_chrdev_region(g_printer_devno, 2); - status = usb_gadget_unregister_driver(&printer_driver); if (status) ERROR(dev, "usb_gadget_unregister_driver %x\n", status); + unregister_chrdev_region(g_printer_devno, 2); + class_destroy(usb_gadget_class); mutex_unlock(&usb_printer_gadget.lock_printer_io); } module_exit(cleanup); diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 86e42892016..5c761df7fa8 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -52,7 +52,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, struct resource *res; int irq; int retval; - unsigned int temp; pr_debug("initializing FSL-SOC USB Controller\n"); @@ -126,18 +125,6 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, goto err3; } - /* - * Check if it is MPC5121 SoC, otherwise set pdata->have_sysif_regs - * flag for 83xx or 8536 system interface registers. - */ - if (pdata->big_endian_mmio) - temp = in_be32(hcd->regs + FSL_SOC_USB_ID); - else - temp = in_le32(hcd->regs + FSL_SOC_USB_ID); - - if ((temp & ID_MSK) != (~((temp & NID_MSK) >> 8) & ID_MSK)) - pdata->have_sysif_regs = 1; - /* Enable USB controller, 83xx or 8536 */ if (pdata->have_sysif_regs) setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4); diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 2c835379522..3fabed33d94 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -19,9 +19,6 @@ #define _EHCI_FSL_H /* offsets for the non-ehci registers in the FSL SOC USB controller */ -#define FSL_SOC_USB_ID 0x0 -#define ID_MSK 0x3f -#define NID_MSK 0x3f00 #define FSL_SOC_USB_ULPIVP 0x170 #define FSL_SOC_USB_PORTSC1 0x184 #define PORT_PTS_MSK (3<<30) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 6fee3cd58ef..74dcf49bd01 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -572,6 +572,8 @@ static int ehci_init(struct usb_hcd *hcd) ehci->iaa_watchdog.function = ehci_iaa_watchdog; ehci->iaa_watchdog.data = (unsigned long) ehci; + hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -579,11 +581,20 @@ static int ehci_init(struct usb_hcd *hcd) ehci->periodic_size = DEFAULT_I_TDPS; INIT_LIST_HEAD(&ehci->cached_itd_list); INIT_LIST_HEAD(&ehci->cached_sitd_list); + + if (HCC_PGM_FRAMELISTLEN(hcc_params)) { + /* periodic schedule size can be smaller than default */ + switch (EHCI_TUNE_FLS) { + case 0: ehci->periodic_size = 1024; break; + case 1: ehci->periodic_size = 512; break; + case 2: ehci->periodic_size = 256; break; + default: BUG(); + } + } if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) return retval; /* controllers may cache some of the periodic schedule ... */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); if (HCC_ISOC_CACHE(hcc_params)) // full frame cache ehci->i_thresh = 2 + 8; else // N microframes cached @@ -637,12 +648,6 @@ static int ehci_init(struct usb_hcd *hcd) /* periodic schedule size can be smaller than default */ temp &= ~(3 << 2); temp |= (EHCI_TUNE_FLS << 2); - switch (EHCI_TUNE_FLS) { - case 0: ehci->periodic_size = 1024; break; - case 1: ehci->periodic_size = 512; break; - case 2: ehci->periodic_size = 256; break; - default: BUG(); - } } if (HCC_LPM(hcc_params)) { /* support link power management EHCI 1.1 addendum */ diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index fa59b26fc5b..c8e360d7d97 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -21,10 +21,13 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/usb/otg.h> +#include <linux/usb/ulpi.h> #include <linux/slab.h> #include <mach/mxc_ehci.h> +#include <asm/mach-types.h> + #define ULPI_VIEWPORT_OFFSET 0x170 struct ehci_mxc_priv { @@ -114,6 +117,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct resource *res; int irq, ret; + unsigned int flags; struct ehci_mxc_priv *priv; struct device *dev = &pdev->dev; struct ehci_hcd *ehci; @@ -177,8 +181,8 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) clk_enable(priv->ahbclk); } - /* "dr" device has its own clock */ - if (pdev->id == 0) { + /* "dr" device has its own clock on i.MX51 */ + if (cpu_is_mx51() && (pdev->id == 0)) { priv->phy1clk = clk_get(dev, "usb_phy1"); if (IS_ERR(priv->phy1clk)) { ret = PTR_ERR(priv->phy1clk); @@ -240,6 +244,23 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (ret) goto err_add; + if (pdata->otg) { + /* + * efikamx and efikasb have some hardware bug which is + * preventing usb to work unless CHRGVBUS is set. + * It's in violation of USB specs + */ + if (machine_is_mx51_efikamx() || machine_is_mx51_efikasb()) { + flags = otg_io_read(pdata->otg, ULPI_OTG_CTRL); + flags |= ULPI_OTG_CTRL_CHRGVBUS; + ret = otg_io_write(pdata->otg, flags, ULPI_OTG_CTRL); + if (ret) { + dev_err(dev, "unable to set CHRVBUS\n"); + goto err_add; + } + } + } + return 0; err_add: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 76179c39c0e..bed07d4aab0 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -44,28 +44,35 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) return 0; } -static int ehci_quirk_amd_SB800(struct ehci_hcd *ehci) +static int ehci_quirk_amd_hudson(struct ehci_hcd *ehci) { struct pci_dev *amd_smbus_dev; u8 rev = 0; amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); - if (!amd_smbus_dev) - return 0; - - pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); - if (rev < 0x40) { - pci_dev_put(amd_smbus_dev); - amd_smbus_dev = NULL; - return 0; + if (amd_smbus_dev) { + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x40) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } + } else { + amd_smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x780b, NULL); + if (!amd_smbus_dev) + return 0; + pci_read_config_byte(amd_smbus_dev, PCI_REVISION_ID, &rev); + if (rev < 0x11 || rev > 0x18) { + pci_dev_put(amd_smbus_dev); + amd_smbus_dev = NULL; + return 0; + } } if (!amd_nb_dev) amd_nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (!amd_nb_dev) - ehci_err(ehci, "QUIRK: unable to get AMD NB device\n"); - ehci_info(ehci, "QUIRK: Enable AMD SB800 L1 fix\n"); + ehci_info(ehci, "QUIRK: Enable exception for AMD Hudson ASPM\n"); pci_dev_put(amd_smbus_dev); amd_smbus_dev = NULL; @@ -131,7 +138,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd) /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - if (ehci_quirk_amd_SB800(ehci)) + if (ehci_quirk_amd_hudson(ehci)) ehci->amd_l1_fix = 1; retval = ehci_halt(ehci); diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 574b99ea070..79a66d622f9 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -262,19 +262,24 @@ static void fsl_usb2_mpc5121_exit(struct platform_device *pdev) } } -struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { +static struct fsl_usb2_platform_data fsl_usb2_mpc5121_pd = { .big_endian_desc = 1, .big_endian_mmio = 1, .es = 1, + .have_sysif_regs = 0, .le_setup_buf = 1, .init = fsl_usb2_mpc5121_init, .exit = fsl_usb2_mpc5121_exit, }; #endif /* CONFIG_PPC_MPC512x */ +static struct fsl_usb2_platform_data fsl_usb2_mpc8xxx_pd = { + .have_sysif_regs = 1, +}; + static const struct of_device_id fsl_usb2_mph_dr_of_match[] = { - { .compatible = "fsl-usb2-mph", }, - { .compatible = "fsl-usb2-dr", }, + { .compatible = "fsl-usb2-mph", .data = &fsl_usb2_mpc8xxx_pd, }, + { .compatible = "fsl-usb2-dr", .data = &fsl_usb2_mpc8xxx_pd, }, #ifdef CONFIG_PPC_MPC512x { .compatible = "fsl,mpc5121-usb2-dr", .data = &fsl_usb2_mpc5121_pd, }, #endif diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index df558f6f84e..3e8211c1ce5 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -308,11 +308,8 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { - u32 temp; - xhci_dbg(xhci, "// Ding dong!\n"); - temp = xhci_readl(xhci, &xhci->dba->doorbell[0]) & DB_MASK; - xhci_writel(xhci, temp | DB_TARGET_HOST, &xhci->dba->doorbell[0]); + xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ xhci_readl(xhci, &xhci->dba->doorbell[0]); } @@ -322,26 +319,24 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int ep_index, unsigned int stream_id) { - struct xhci_virt_ep *ep; - unsigned int ep_state; - u32 field; __u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id]; + struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; + unsigned int ep_state = ep->ep_state; - ep = &xhci->devs[slot_id]->eps[ep_index]; - ep_state = ep->ep_state; /* Don't ring the doorbell for this endpoint if there are pending - * cancellations because the we don't want to interrupt processing. + * cancellations because we don't want to interrupt processing. * We don't want to restart any stream rings if there's a set dequeue * pointer command pending because the device can choose to start any * stream once the endpoint is on the HW schedule. * FIXME - check all the stream rings for pending cancellations. */ - if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING) - && !(ep_state & EP_HALTED)) { - field = xhci_readl(xhci, db_addr) & DB_MASK; - field |= EPI_TO_DB(ep_index) | STREAM_ID_TO_DB(stream_id); - xhci_writel(xhci, field, db_addr); - } + if ((ep_state & EP_HALT_PENDING) || (ep_state & SET_DEQ_PENDING) || + (ep_state & EP_HALTED)) + return; + xhci_writel(xhci, DB_VALUE(ep_index, stream_id), db_addr); + /* The CPU has better things to do at this point than wait for a + * write-posting flush. It'll get there soon enough. + */ } /* Ring the doorbell for any rings with pending URBs */ @@ -1188,7 +1183,7 @@ static void handle_port_status(struct xhci_hcd *xhci, addr = &xhci->op_regs->port_status_base + NUM_PORT_REGS * (port_id - 1); temp = xhci_readl(xhci, addr); - if ((temp & PORT_CONNECT) && (hcd->state == HC_STATE_SUSPENDED)) { + if (hcd->state == HC_STATE_SUSPENDED) { xhci_dbg(xhci, "resume root hub\n"); usb_hcd_resume_root_hub(hcd); } @@ -1710,8 +1705,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, /* Others already handled above */ break; } - dev_dbg(&td->urb->dev->dev, - "ep %#x - asked for %d bytes, " + xhci_dbg(xhci, "ep %#x - asked for %d bytes, " "%d bytes untransferred\n", td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, @@ -2389,7 +2383,8 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb) } xhci_dbg(xhci, "\n"); if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %d, sglist used, num_trbs = %d\n", + xhci_dbg(xhci, "ep %#x - urb len = %d, sglist used, " + "num_trbs = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, num_trbs); @@ -2414,14 +2409,17 @@ static void check_trb_math(struct urb *urb, int num_trbs, int running_total) static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index, unsigned int stream_id, int start_cycle, - struct xhci_generic_trb *start_trb, struct xhci_td *td) + struct xhci_generic_trb *start_trb) { /* * Pass all the TRBs to the hardware at once and make sure this write * isn't reordered. */ wmb(); - start_trb->field[3] |= start_cycle; + if (start_cycle) + start_trb->field[3] |= start_cycle; + else + start_trb->field[3] &= ~0x1; xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id); } @@ -2449,7 +2447,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { - if (!printk_ratelimit()) + if (printk_ratelimit()) dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", @@ -2551,9 +2549,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u32 remainder = 0; /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) + if (first_trb) { first_trb = false; - else + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; /* Chain all the TRBs together; clear the chain bit in the last @@ -2625,7 +2625,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2671,7 +2671,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */ if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d), addr = %#llx, num_trbs = %d\n", + xhci_dbg(xhci, "ep %#x - urb len = %#x (%d), " + "addr = %#llx, num_trbs = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, urb->transfer_buffer_length, @@ -2711,9 +2712,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field = 0; /* Don't change the cycle bit of the first TRB until later */ - if (first_trb) + if (first_trb) { first_trb = false; - else + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; /* Chain all the TRBs together; clear the chain bit in the last @@ -2757,7 +2760,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, check_trb_math(urb, num_trbs, running_total); giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2818,13 +2821,17 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /* Queue setup TRB - see section 6.4.1.2.1 */ /* FIXME better way to translate setup_packet into two u32 fields? */ setup = (struct usb_ctrlrequest *) urb->setup_packet; + field = 0; + field |= TRB_IDT | TRB_TYPE(TRB_SETUP); + if (start_cycle == 0) + field |= 0x1; queue_trb(xhci, ep_ring, false, true, /* FIXME endianness is probably going to bite my ass here. */ setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16, setup->wIndex | setup->wLength << 16, TRB_LEN(8) | TRB_INTR_TARGET(0), /* Immediate data in pointer */ - TRB_IDT | TRB_TYPE(TRB_SETUP)); + field); /* If there's data, queue data TRBs */ field = 0; @@ -2859,7 +2866,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field | TRB_IOC | TRB_TYPE(TRB_STATUS) | ep_ring->cycle_state); giveback_first_trb(xhci, slot_id, ep_index, 0, - start_cycle, start_trb, td); + start_cycle, start_trb); return 0; } @@ -2900,6 +2907,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, int running_total, trb_buff_len, td_len, td_remain_len, ret; u64 start_addr, addr; int i, j; + bool more_trbs_coming; ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; @@ -2910,7 +2918,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } if (!in_interrupt()) - dev_dbg(&urb->dev->dev, "ep %#x - urb len = %#x (%d)," + xhci_dbg(xhci, "ep %#x - urb len = %#x (%d)," " addr = %#llx, num_tds = %d\n", urb->ep->desc.bEndpointAddress, urb->transfer_buffer_length, @@ -2950,7 +2958,10 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, field |= TRB_TYPE(TRB_ISOC); /* Assume URB_ISO_ASAP is set */ field |= TRB_SIA; - if (i > 0) + if (i == 0) { + if (start_cycle == 0) + field |= 0x1; + } else field |= ep_ring->cycle_state; first_trb = false; } else { @@ -2965,9 +2976,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, */ if (j < trbs_per_td - 1) { field |= TRB_CHAIN; + more_trbs_coming = true; } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; + more_trbs_coming = false; } /* Calculate TRB length */ @@ -2980,7 +2993,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, length_field = TRB_LEN(trb_buff_len) | remainder | TRB_INTR_TARGET(0); - queue_trb(xhci, ep_ring, false, false, + queue_trb(xhci, ep_ring, false, more_trbs_coming, lower_32_bits(addr), upper_32_bits(addr), length_field, @@ -3003,10 +3016,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } } - wmb(); - start_trb->field[3] |= start_cycle; - - xhci_ring_ep_doorbell(xhci, slot_id, ep_index, urb->stream_id); + giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id, + start_cycle, start_trb); return 0; } @@ -3064,7 +3075,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, * to set the polling interval (once the API is added). */ if (xhci_interval != ep_interval) { - if (!printk_ratelimit()) + if (printk_ratelimit()) dev_dbg(&urb->dev->dev, "Driver uses different interval" " (%d microframe%s) than xHCI " "(%d microframe%s)\n", diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 45e4a3108cc..34cf4e16587 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -226,7 +226,8 @@ static int xhci_setup_msi(struct xhci_hcd *xhci) static int xhci_setup_msix(struct xhci_hcd *xhci) { int i, ret = 0; - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); /* * calculate number of msi-x vectors supported. @@ -265,6 +266,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci) goto disable_msix; } + hcd->msix_enabled = 1; return ret; disable_msix: @@ -280,7 +282,8 @@ free_entries: /* Free any IRQs and disable MSI-X */ static void xhci_cleanup_msix(struct xhci_hcd *xhci) { - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct pci_dev *pdev = to_pci_dev(hcd->self.controller); xhci_free_irq(xhci); @@ -292,6 +295,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) pci_disable_msi(pdev); } + hcd->msix_enabled = 0; return; } @@ -508,9 +512,10 @@ void xhci_stop(struct usb_hcd *hcd) spin_lock_irq(&xhci->lock); xhci_halt(xhci); xhci_reset(xhci); - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); + #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING /* Tell the event ring poll function not to reschedule */ xhci->zombie = 1; @@ -544,9 +549,10 @@ void xhci_shutdown(struct usb_hcd *hcd) spin_lock_irq(&xhci->lock); xhci_halt(xhci); - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); + xhci_dbg(xhci, "xhci_shutdown completed - status = %x\n", xhci_readl(xhci, &xhci->op_regs->status)); } @@ -647,6 +653,7 @@ int xhci_suspend(struct xhci_hcd *xhci) int rc = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + int i; spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -677,10 +684,15 @@ int xhci_suspend(struct xhci_hcd *xhci) spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } - /* step 5: remove core well power */ - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + /* step 5: remove core well power */ + /* synchronize irq when using MSI-X */ + if (xhci->msix_entries) { + for (i = 0; i < xhci->msix_count; i++) + synchronize_irq(xhci->msix_entries[i].vector); + } + return rc; } @@ -694,7 +706,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) { u32 command, temp = 0; struct usb_hcd *hcd = xhci_to_hcd(xhci); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); int old_state, retval; old_state = hcd->state; @@ -729,9 +740,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "Stop HCD\n"); xhci_halt(xhci); xhci_reset(xhci); - if (hibernated) - xhci_cleanup_msix(xhci); spin_unlock_irq(&xhci->lock); + xhci_cleanup_msix(xhci); #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING /* Tell the event ring poll function not to reschedule */ @@ -765,30 +775,6 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) return retval; } - spin_unlock_irq(&xhci->lock); - /* Re-setup MSI-X */ - if (hcd->irq) - free_irq(hcd->irq, hcd); - hcd->irq = -1; - - retval = xhci_setup_msix(xhci); - if (retval) - /* fall back to msi*/ - retval = xhci_setup_msi(xhci); - - if (retval) { - /* fall back to legacy interrupt*/ - retval = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, - hcd->irq_descr, hcd); - if (retval) { - xhci_err(xhci, "request interrupt %d failed\n", - pdev->irq); - return retval; - } - hcd->irq = pdev->irq; - } - - spin_lock_irq(&xhci->lock); /* step 4: set Run/Stop bit */ command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_RUN; @@ -2445,8 +2431,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) xhci_err(xhci, "Error while assigning device slot ID\n"); return 0; } - /* xhci_alloc_virt_device() does not touch rings; no need to lock */ - if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_KERNEL)) { + /* xhci_alloc_virt_device() does not touch rings; no need to lock. + * Use GFP_NOIO, since this function can be called from + * xhci_discover_or_reset_device(), which may be called as part of + * mass storage driver error handling. + */ + if (!xhci_alloc_virt_device(xhci, xhci->slot_id, udev, GFP_NOIO)) { /* Disable slot, if we can do it without mem alloc */ xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n"); spin_lock_irqsave(&xhci->lock, flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 170c367112d..7f236fd2201 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -436,22 +436,18 @@ struct xhci_run_regs { /** * struct doorbell_array * + * Bits 0 - 7: Endpoint target + * Bits 8 - 15: RsvdZ + * Bits 16 - 31: Stream ID + * * Section 5.6 */ struct xhci_doorbell_array { u32 doorbell[256]; }; -#define DB_TARGET_MASK 0xFFFFFF00 -#define DB_STREAM_ID_MASK 0x0000FFFF -#define DB_TARGET_HOST 0x0 -#define DB_STREAM_ID_HOST 0x0 -#define DB_MASK (0xff << 8) - -/* Endpoint Target - bits 0:7 */ -#define EPI_TO_DB(p) (((p) + 1) & 0xff) -#define STREAM_ID_TO_DB(p) (((p) & 0xffff) << 16) - +#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) +#define DB_VALUE_HOST 0x00000000 /** * struct xhci_protocol_caps diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c index 1732d9bc097..1616ad1793a 100644 --- a/drivers/usb/misc/usbled.c +++ b/drivers/usb/misc/usbled.c @@ -45,7 +45,7 @@ struct usb_led { static void change_color(struct usb_led *led) { - int retval; + int retval = 0; unsigned char *buffer; buffer = kmalloc(8, GFP_KERNEL); diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c index 4ff21587ab0..f7a20573803 100644 --- a/drivers/usb/misc/uss720.c +++ b/drivers/usb/misc/uss720.c @@ -776,7 +776,6 @@ static const struct usb_device_id uss720_table[] = { { USB_DEVICE(0x0557, 0x2001) }, { USB_DEVICE(0x0729, 0x1284) }, { USB_DEVICE(0x1293, 0x0002) }, - { USB_DEVICE(0x1293, 0x0002) }, { USB_DEVICE(0x050d, 0x0002) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index e70014ab097..8acf165fe13 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -132,6 +132,8 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) platform_set_drvdata(pdev, nop); + BLOCKING_INIT_NOTIFIER_HEAD(&nop->otg.notifier); + return 0; exit: kfree(nop); diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 059d9ac0ab5..770d799d5af 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -45,7 +45,7 @@ struct ulpi_info { /* ULPI hardcoded IDs, used for probing */ static struct ulpi_info ulpi_ids[] = { ULPI_INFO(ULPI_ID(0x04cc, 0x1504), "NXP ISP1504"), - ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB3319"), + ULPI_INFO(ULPI_ID(0x0424, 0x0006), "SMSC USB331x"), }; static int ulpi_set_otg_flags(struct otg_transceiver *otg) diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 63f7cc45bca..7b8815ddf36 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -486,12 +486,22 @@ static void ch341_read_int_callback(struct urb *urb) if (actual_length >= 4) { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned long flags; + u8 prev_line_status = priv->line_status; spin_lock_irqsave(&priv->lock, flags); priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; if ((data[1] & CH341_MULT_STAT)) priv->multi_status_change = 1; spin_unlock_irqrestore(&priv->lock, flags); + + if ((priv->line_status ^ prev_line_status) & CH341_BIT_DCD) { + struct tty_struct *tty = tty_port_tty_get(&port->port); + if (tty) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & CH341_BIT_DCD); + tty_kref_put(tty); + } + wake_up_interruptible(&priv->delta_msr_wait); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8d7731dbf47..735ea03157a 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,7 +49,6 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); -static int cp210x_carrier_raised(struct usb_serial_port *p); static int debug; @@ -87,7 +86,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ - { USB_DEVICE(0x10C4, 0x8149) }, /* West Mountain Radio Computerized Battery Analyzer */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ @@ -110,7 +108,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ + { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ @@ -165,8 +165,7 @@ static struct usb_serial_driver cp210x_device = { .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, - .dtr_rts = cp210x_dtr_rts, - .carrier_raised = cp210x_carrier_raised + .dtr_rts = cp210x_dtr_rts }; /* Config request types */ @@ -765,15 +764,6 @@ static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) return result; } -static int cp210x_carrier_raised(struct usb_serial_port *p) -{ - unsigned int control; - cp210x_get_config(p, CP210X_GET_MDMSTS, &control, 1); - if (control & CONTROL_DCD) - return 1; - return 0; -} - static void cp210x_break_ctl (struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b92070c103c..666e5a6edd8 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -455,7 +455,6 @@ static int digi_write_room(struct tty_struct *tty); static int digi_chars_in_buffer(struct tty_struct *tty); static int digi_open(struct tty_struct *tty, struct usb_serial_port *port); static void digi_close(struct usb_serial_port *port); -static int digi_carrier_raised(struct usb_serial_port *port); static void digi_dtr_rts(struct usb_serial_port *port, int on); static int digi_startup_device(struct usb_serial *serial); static int digi_startup(struct usb_serial *serial); @@ -511,7 +510,6 @@ static struct usb_serial_driver digi_acceleport_2_device = { .open = digi_open, .close = digi_close, .dtr_rts = digi_dtr_rts, - .carrier_raised = digi_carrier_raised, .write = digi_write, .write_room = digi_write_room, .write_bulk_callback = digi_write_bulk_callback, @@ -1339,14 +1337,6 @@ static void digi_dtr_rts(struct usb_serial_port *port, int on) digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); } -static int digi_carrier_raised(struct usb_serial_port *port) -{ - struct digi_port *priv = usb_get_serial_port_data(port); - if (priv->dp_modem_signals & TIOCM_CD) - return 1; - return 0; -} - static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) { int ret; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a2668d08926..4787c0cd063 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -676,7 +676,17 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, - { USB_DEVICE(ICOM_ID1_VID, ICOM_ID1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C2_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2D_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2VR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP4KVR_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVT_PID) }, + { USB_DEVICE(ICOM_VID, ICOM_ID_RP2KVR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACG_HFDUAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_YEI_SERVOCENTER31_PID) }, { USB_DEVICE(FTDI_VID, FTDI_THORLABS_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index bf086728548..ed160def858 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -569,11 +569,23 @@ #define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* - * Icom ID-1 digital transceiver - */ - -#define ICOM_ID1_VID 0x0C26 -#define ICOM_ID1_PID 0x0004 + * Definitions for Icom Inc. devices + */ +#define ICOM_VID 0x0C26 /* Icom vendor ID */ +/* Note: ID-1 is a communications tranceiver for HAM-radio operators */ +#define ICOM_ID_1_PID 0x0004 /* ID-1 USB to RS-232 */ +/* Note: OPC is an Optional cable to connect an Icom Tranceiver */ +#define ICOM_OPC_U_UC_PID 0x0018 /* OPC-478UC, OPC-1122U cloning cable */ +/* Note: ID-RP* devices are Icom Repeater Devices for HAM-radio */ +#define ICOM_ID_RP2C1_PID 0x0009 /* ID-RP2C Asset 1 to RS-232 */ +#define ICOM_ID_RP2C2_PID 0x000A /* ID-RP2C Asset 2 to RS-232 */ +#define ICOM_ID_RP2D_PID 0x000B /* ID-RP2D configuration port*/ +#define ICOM_ID_RP2VT_PID 0x000C /* ID-RP2V Transmit config port */ +#define ICOM_ID_RP2VR_PID 0x000D /* ID-RP2V Receive config port */ +#define ICOM_ID_RP4KVT_PID 0x0010 /* ID-RP4000V Transmit config port */ +#define ICOM_ID_RP4KVR_PID 0x0011 /* ID-RP4000V Receive config port */ +#define ICOM_ID_RP2KVT_PID 0x0012 /* ID-RP2000V Transmit config port */ +#define ICOM_ID_RP2KVR_PID 0x0013 /* ID-RP2000V Receive config port */ /* * GN Otometrics (http://www.otometrics.com) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e6833e216fc..e4db5ad2bc5 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -479,6 +479,26 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); +/** + * usb_serial_handle_dcd_change - handle a change of carrier detect state + * @port: usb_serial_port structure for the open port + * @tty: tty_struct structure for the port + * @status: new carrier detect status, nonzero if active + */ +void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, unsigned int status) +{ + struct tty_port *port = &usb_port->port; + + dbg("%s - port %d, status %d", __func__, usb_port->number, status); + + if (status) + wake_up_interruptible(&port->open_wait); + else if (tty && !C_CLOCAL(tty)) + tty_hangup(tty); +} +EXPORT_SYMBOL_GPL(usb_serial_handle_dcd_change); + int usb_serial_generic_resume(struct usb_serial *serial) { struct usb_serial_port *port; diff --git a/drivers/usb/serial/io_tables.h b/drivers/usb/serial/io_tables.h index 6ab2a3f97fe..178b22eb32b 100644 --- a/drivers/usb/serial/io_tables.h +++ b/drivers/usb/serial/io_tables.h @@ -199,6 +199,7 @@ static struct usb_serial_driver epic_device = { .name = "epic", }, .description = "EPiC device", + .usb_driver = &io_driver, .id_table = Epic_port_id_table, .num_ports = 1, .open = edge_open, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 12ed594f5f8..99b97c04896 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1275,6 +1275,7 @@ static struct usb_serial_driver iuu_device = { .name = "iuu_phoenix", }, .id_table = id_table, + .usb_driver = &iuu_driver, .num_ports = 1, .bulk_in_size = 512, .bulk_out_size = 512, diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 2d8baf6ac47..ce134dc28dd 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -546,6 +546,7 @@ static struct usb_serial_driver keyspan_pre_device = { .name = "keyspan_no_firm", }, .description = "Keyspan - (without firmware)", + .usb_driver = &keyspan_driver, .id_table = keyspan_pre_ids, .num_ports = 1, .attach = keyspan_fake_startup, @@ -557,6 +558,7 @@ static struct usb_serial_driver keyspan_1port_device = { .name = "keyspan_1", }, .description = "Keyspan 1 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_1port_ids, .num_ports = 1, .open = keyspan_open, @@ -579,6 +581,7 @@ static struct usb_serial_driver keyspan_2port_device = { .name = "keyspan_2", }, .description = "Keyspan 2 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_2port_ids, .num_ports = 2, .open = keyspan_open, @@ -601,6 +604,7 @@ static struct usb_serial_driver keyspan_4port_device = { .name = "keyspan_4", }, .description = "Keyspan 4 port adapter", + .usb_driver = &keyspan_driver, .id_table = keyspan_4port_ids, .num_ports = 4, .open = keyspan_open, diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index a10dd5676cc..554a8693a46 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -679,22 +679,6 @@ static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) } } -static int keyspan_pda_carrier_raised(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - unsigned char modembits; - - /* If we can read the modem status and the DCD is low then - carrier is not raised yet */ - if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) { - if (!(modembits & (1>>6))) - return 0; - } - /* Carrier raised, or we failed (eg disconnected) so - progress accordingly */ - return 1; -} - static int keyspan_pda_open(struct tty_struct *tty, struct usb_serial_port *port) @@ -881,7 +865,6 @@ static struct usb_serial_driver keyspan_pda_device = { .id_table = id_table_std, .num_ports = 1, .dtr_rts = keyspan_pda_dtr_rts, - .carrier_raised = keyspan_pda_carrier_raised, .open = keyspan_pda_open, .close = keyspan_pda_close, .write = keyspan_pda_write, diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c index cf1718394e1..653465f61d4 100644 --- a/drivers/usb/serial/moto_modem.c +++ b/drivers/usb/serial/moto_modem.c @@ -44,6 +44,7 @@ static struct usb_serial_driver moto_device = { .name = "moto-modem", }, .id_table = id_table, + .usb_driver = &moto_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 748778288d9..5f46838dfee 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -382,7 +382,16 @@ static void option_instat_callback(struct urb *urb); #define HAIER_VENDOR_ID 0x201e #define HAIER_PRODUCT_CE100 0x2009 -#define CINTERION_VENDOR_ID 0x0681 +/* Cinterion (formerly Siemens) products */ +#define SIEMENS_VENDOR_ID 0x0681 +#define CINTERION_VENDOR_ID 0x1e2d +#define CINTERION_PRODUCT_HC25_MDM 0x0047 +#define CINTERION_PRODUCT_HC25_MDMNET 0x0040 +#define CINTERION_PRODUCT_HC28_MDM 0x004C +#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */ +#define CINTERION_PRODUCT_EU3_E 0x0051 +#define CINTERION_PRODUCT_EU3_P 0x0052 +#define CINTERION_PRODUCT_PH8 0x0053 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c @@ -944,7 +953,17 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_100F) }, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1011)}, { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_1012)}, - { USB_DEVICE(CINTERION_VENDOR_ID, 0x0047) }, + /* Cinterion */ + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) }, + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, /* HC28 enumerates with Siemens or Cinterion VID depending on FW revision */ + { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 5be866bb7a4..73613205be7 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -157,6 +157,7 @@ static struct usb_serial_driver oti6858_device = { .name = "oti6858", }, .id_table = id_table, + .usb_driver = &oti6858_driver, .num_ports = 1, .open = oti6858_open, .close = oti6858_close, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 8ae4c6cbc38..08c9181b8e4 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -50,6 +50,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MMX) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) }, + { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) }, { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) }, { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) }, @@ -677,9 +678,11 @@ static void pl2303_update_line_status(struct usb_serial_port *port, { struct pl2303_private *priv = usb_get_serial_port_data(port); + struct tty_struct *tty; unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; + u8 prev_line_status; u16 idv, idp; idv = le16_to_cpu(port->serial->dev->descriptor.idVendor); @@ -701,11 +704,20 @@ static void pl2303_update_line_status(struct usb_serial_port *port, /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); + prev_line_status = priv->line_status; priv->line_status = data[status_idx]; spin_unlock_irqrestore(&priv->lock, flags); if (priv->line_status & UART_BREAK_ERROR) usb_serial_handle_break(port); wake_up_interruptible(&priv->delta_msr_wait); + + tty = tty_port_tty_get(&port->port); + if (!tty) + return; + if ((priv->line_status ^ prev_line_status) & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & UART_DCD); + tty_kref_put(tty); } static void pl2303_read_int_callback(struct urb *urb) diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index 43eb9bdad42..1b025f75daf 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -21,6 +21,7 @@ #define PL2303_PRODUCT_ID_MMX 0x0612 #define PL2303_PRODUCT_ID_GPRS 0x0609 #define PL2303_PRODUCT_ID_HCR331 0x331a +#define PL2303_PRODUCT_ID_MOTOROLA 0x0307 #define ATEN_VENDOR_ID 0x0557 #define ATEN_VENDOR_ID2 0x0547 diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 214a3e50429..30b73e68a90 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,6 +36,7 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 +#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -66,6 +67,7 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); @@ -84,6 +86,7 @@ static struct usb_serial_driver qcaux_device = { .name = "qcaux", }, .id_table = id_table, + .usb_driver = &qcaux_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/siemens_mpi.c b/drivers/usb/serial/siemens_mpi.c index cb8195cabfd..74cd4ccdb3f 100644 --- a/drivers/usb/serial/siemens_mpi.c +++ b/drivers/usb/serial/siemens_mpi.c @@ -42,6 +42,7 @@ static struct usb_serial_driver siemens_usb_mpi_device = { .name = "siemens_mpi", }, .id_table = id_table, + .usb_driver = &siemens_usb_mpi_driver, .num_ports = 1, }; diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 765aa983bf5..cbfb70bffdd 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -133,7 +133,7 @@ struct spcp8x5_usb_ctrl_arg { /* how come ??? */ #define UART_STATE 0x08 -#define UART_STATE_TRANSIENT_MASK 0x74 +#define UART_STATE_TRANSIENT_MASK 0x75 #define UART_DCD 0x01 #define UART_DSR 0x02 #define UART_BREAK_ERROR 0x04 @@ -525,6 +525,10 @@ static void spcp8x5_process_read_urb(struct urb *urb) /* overrun is special, not associated with a char */ if (status & UART_OVERRUN_ERROR) tty_insert_flip_char(tty, 0, TTY_OVERRUN); + + if (status & UART_DCD) + usb_serial_handle_dcd_change(port, tty, + priv->line_status & MSR_STATUS_LINE_DCD); } tty_insert_flip_string_fixed_flag(tty, data, tty_flag, @@ -645,6 +649,7 @@ static struct usb_serial_driver spcp8x5_device = { .name = "SPCP8x5", }, .id_table = id_table, + .usb_driver = &spcp8x5_driver, .num_ports = 1, .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6954de50c0f..546a52179be 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1344,11 +1344,15 @@ int usb_serial_register(struct usb_serial_driver *driver) return -ENODEV; fixup_generic(driver); - if (driver->usb_driver) - driver->usb_driver->supports_autosuspend = 1; if (!driver->description) driver->description = driver->driver.name; + if (!driver->usb_driver) { + WARN(1, "Serial driver %s has no usb_driver\n", + driver->description); + return -EINVAL; + } + driver->usb_driver->supports_autosuspend = 1; /* Add this device to our list of devices */ mutex_lock(&table_lock); diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index f2ed6a31be7..95a82148ee8 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -75,6 +75,7 @@ static struct usb_serial_driver debug_device = { .name = "debug", }, .id_table = id_table, + .usb_driver = &debug_driver, .num_ports = 1, .bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE, .break_ctl = usb_debug_break_ctl, diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index c854fdebe0a..2c855302622 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,4 +31,9 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, + "Super Top", + "USB 2.0 SATA BRIDGE", + USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), + #endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index fcc1e32ce25..24bd5d7c3de 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1044,6 +1044,15 @@ UNUSUAL_DEV( 0x084d, 0x0011, 0x0110, 0x0110, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BULK32), +/* Reported by <ttkspam@free.fr> + * The device reports a vendor-specific device class, requiring an + * explicit vendor/product match. + */ +UNUSUAL_DEV( 0x0851, 0x1542, 0x0002, 0x0002, + "MagicPixel", + "FW_Omega2", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, 0), + /* Andrew Lunn <andrew@lunn.ch> * PanDigital Digital Picture Frame. Does not like ALLOW_MEDIUM_REMOVAL * on LUN 4. @@ -1872,6 +1881,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_READ_DISC_INFO ), +/* Patch by Richard Schütz <r.schtz@t-online.de> + * This external hard drive enclosure uses a JMicron chip which + * needs the US_FL_IGNORE_RESIDUE flag to work properly. */ +UNUSUAL_DEV( 0x1e68, 0x001b, 0x0000, 0x0000, + "TrekStor GmbH & Co. KG", + "DataStation maxi g.u", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE | US_FL_SANE_SENSE ), + UNUSUAL_DEV( 0x2116, 0x0320, 0x0001, 0x0001, "ST", "2A", diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 60d27bc9eb8..6b61ded701e 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1560,9 +1560,10 @@ retry_locked: /* NOTE: no side-effects allowed, until we take s_mutex */ revoking = cap->implemented & ~cap->issued; - if (revoking) - dout(" mds%d revoking %s\n", cap->mds, - ceph_cap_string(revoking)); + dout(" mds%d cap %p issued %s implemented %s revoking %s\n", + cap->mds, cap, ceph_cap_string(cap->issued), + ceph_cap_string(cap->implemented), + ceph_cap_string(revoking)); if (cap == ci->i_auth_cap && (cap->issued & CEPH_CAP_FILE_WR)) { @@ -1658,6 +1659,8 @@ ack: if (cap == ci->i_auth_cap && ci->i_dirty_caps) flushing = __mark_caps_flushing(inode, session); + else + flushing = 0; mds = cap->mds; /* remember mds, so we don't repeat */ sent++; @@ -1940,6 +1943,35 @@ void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, } } +static void kick_flushing_inode_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + struct inode *inode) +{ + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_cap *cap; + int delayed = 0; + + spin_lock(&inode->i_lock); + cap = ci->i_auth_cap; + dout("kick_flushing_inode_caps %p flushing %s flush_seq %lld\n", inode, + ceph_cap_string(ci->i_flushing_caps), ci->i_cap_flush_seq); + __ceph_flush_snaps(ci, &session, 1); + if (ci->i_flushing_caps) { + delayed = __send_cap(mdsc, cap, CEPH_CAP_OP_FLUSH, + __ceph_caps_used(ci), + __ceph_caps_wanted(ci), + cap->issued | cap->implemented, + ci->i_flushing_caps, NULL); + if (delayed) { + spin_lock(&inode->i_lock); + __cap_delay_requeue(mdsc, ci); + spin_unlock(&inode->i_lock); + } + } else { + spin_unlock(&inode->i_lock); + } +} + /* * Take references to capabilities we hold, so that we don't release @@ -2687,7 +2719,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, ceph_add_cap(inode, session, cap_id, -1, issued, wanted, seq, mseq, realmino, CEPH_CAP_FLAG_AUTH, NULL /* no caps context */); - try_flush_caps(inode, session, NULL); + kick_flushing_inode_caps(mdsc, session, inode); up_read(&mdsc->snap_rwsem); /* make sure we re-request max_size, if necessary */ @@ -2785,8 +2817,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, case CEPH_CAP_OP_IMPORT: handle_cap_import(mdsc, inode, h, session, snaptrace, snaptrace_len); - ceph_check_caps(ceph_inode(inode), CHECK_CAPS_NODELAY, - session); + ceph_check_caps(ceph_inode(inode), 0, session); goto done_unlocked; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e835eff551e..5625463aa47 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -710,10 +710,6 @@ static int fill_inode(struct inode *inode, ci->i_ceph_flags |= CEPH_I_COMPLETE; ci->i_max_offset = 2; } - - /* it may be better to set st_size in getattr instead? */ - if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), RBYTES)) - inode->i_size = ci->i_rbytes; break; default: pr_err("fill_inode %llx.%llx BAD mode 0%o\n", @@ -1819,7 +1815,11 @@ int ceph_getattr(struct vfsmount *mnt, struct dentry *dentry, else stat->dev = 0; if (S_ISDIR(inode->i_mode)) { - stat->size = ci->i_rbytes; + if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), + RBYTES)) + stat->size = ci->i_rbytes; + else + stat->size = ci->i_files + ci->i_subdirs; stat->blocks = 0; stat->blksize = 65536; } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 1e30d194a8e..a1ee8fa3a8e 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -693,9 +693,11 @@ static int __choose_mds(struct ceph_mds_client *mdsc, dout("choose_mds %p %llx.%llx " "frag %u mds%d (%d/%d)\n", inode, ceph_vinop(inode), - frag.frag, frag.mds, + frag.frag, mds, (int)r, frag.ndist); - return mds; + if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= + CEPH_MDS_STATE_ACTIVE) + return mds; } /* since this file/dir wasn't known to be @@ -708,7 +710,9 @@ static int __choose_mds(struct ceph_mds_client *mdsc, dout("choose_mds %p %llx.%llx " "frag %u mds%d (auth)\n", inode, ceph_vinop(inode), frag.frag, mds); - return mds; + if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= + CEPH_MDS_STATE_ACTIVE) + return mds; } } } diff --git a/fs/ceph/super.c b/fs/ceph/super.c index bf6f0f34082..9c5085465a6 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -290,6 +290,8 @@ static int parse_mount_options(struct ceph_mount_options **pfsopt, fsopt->rsize = CEPH_MOUNT_RSIZE_DEFAULT; fsopt->snapdir_name = kstrdup(CEPH_SNAPDIRNAME_DEFAULT, GFP_KERNEL); + fsopt->caps_wanted_delay_min = CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT; + fsopt->caps_wanted_delay_max = CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT; fsopt->cap_release_safety = CEPH_CAP_RELEASE_SAFETY_DEFAULT; fsopt->max_readdir = CEPH_MAX_READDIR_DEFAULT; fsopt->max_readdir_bytes = CEPH_MAX_READDIR_BYTES_DEFAULT; diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 6e12a6ba5f7..8c9eba6ef9d 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c @@ -219,6 +219,7 @@ static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci, struct rb_node **p; struct rb_node *parent = NULL; struct ceph_inode_xattr *xattr = NULL; + int name_len = strlen(name); int c; p = &ci->i_xattrs.index.rb_node; @@ -226,6 +227,8 @@ static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci, parent = *p; xattr = rb_entry(parent, struct ceph_inode_xattr, node); c = strncmp(name, xattr->name, xattr->name_len); + if (c == 0 && name_len > xattr->name_len) + c = 1; if (c < 0) p = &(*p)->rb_left; else if (c > 0) diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 43b19dd3919..d87558448e3 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_CIFS) += cifs.o cifs-y := cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o inode.o \ link.o misc.o netmisc.o smbdes.o smbencrypt.o transport.o asn1.o \ - md4.o md5.o cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ + cifs_unicode.o nterr.o xattr.o cifsencrypt.o \ readdir.o ioctl.o sess.o export.o cifs-$(CONFIG_CIFS_ACL) += cifsacl.o diff --git a/fs/cifs/README b/fs/cifs/README index 46af99ab361..fe168359082 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -452,6 +452,11 @@ A partial list of the supported mount options follows: if oplock (caching token) is granted and held. Note that direct allows write operations larger than page size to be sent to the server. + strictcache Use for switching on strict cache mode. In this mode the + client read from the cache all the time it has Oplock Level II, + otherwise - read from the server. All written data are stored + in the cache, but if the client doesn't have Exclusive Oplock, + it writes the data to the server. acl Allow setfacl and getfacl to manage posix ACLs if server supports them. (default) noacl Do not allow setfacl and getfacl calls on this mount diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 66f3d50d067..0db5f1de022 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -24,7 +24,6 @@ #include "cifspdu.h" #include "cifsglob.h" #include "cifs_debug.h" -#include "md5.h" #include "cifs_unicode.h" #include "cifsproto.h" #include "ntlmssp.h" @@ -37,11 +36,6 @@ /* Note that the smb header signature field on input contains the sequence number before this function is called */ -extern void mdfour(unsigned char *out, unsigned char *in, int n); -extern void E_md4hash(const unsigned char *passwd, unsigned char *p16); -extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, - unsigned char *p24); - static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, char *signature) { @@ -234,6 +228,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu, /* first calculate 24 bytes ntlm response and then 16 byte session key */ int setup_ntlm_response(struct cifsSesInfo *ses) { + int rc = 0; unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; char temp_key[CIFS_SESS_KEY_SIZE]; @@ -247,13 +242,26 @@ int setup_ntlm_response(struct cifsSesInfo *ses) } ses->auth_key.len = temp_len; - SMBNTencrypt(ses->password, ses->server->cryptkey, + rc = SMBNTencrypt(ses->password, ses->server->cryptkey, ses->auth_key.response + CIFS_SESS_KEY_SIZE); + if (rc) { + cFYI(1, "%s Can't generate NTLM response, error: %d", + __func__, rc); + return rc; + } + + rc = E_md4hash(ses->password, temp_key); + if (rc) { + cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); + return rc; + } - E_md4hash(ses->password, temp_key); - mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); + rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE); + if (rc) + cFYI(1, "%s Can't generate NTLM session key, error: %d", + __func__, rc); - return 0; + return rc; } #ifdef CONFIG_CIFS_WEAK_PW_HASH @@ -700,14 +708,13 @@ cifs_crypto_shash_allocate(struct TCP_Server_Info *server) unsigned int size; server->secmech.hmacmd5 = crypto_alloc_shash("hmac(md5)", 0, 0); - if (!server->secmech.hmacmd5 || - IS_ERR(server->secmech.hmacmd5)) { + if (IS_ERR(server->secmech.hmacmd5)) { cERROR(1, "could not allocate crypto hmacmd5\n"); return PTR_ERR(server->secmech.hmacmd5); } server->secmech.md5 = crypto_alloc_shash("md5", 0, 0); - if (!server->secmech.md5 || IS_ERR(server->secmech.md5)) { + if (IS_ERR(server->secmech.md5)) { cERROR(1, "could not allocate crypto md5\n"); rc = PTR_ERR(server->secmech.md5); goto crypto_allocate_md5_fail; diff --git a/fs/cifs/cifsencrypt.h b/fs/cifs/cifsencrypt.h deleted file mode 100644 index 15d2ec00647..00000000000 --- a/fs/cifs/cifsencrypt.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * fs/cifs/cifsencrypt.h - * - * Copyright (c) International Business Machines Corp., 2005 - * Author(s): Steve French (sfrench@us.ibm.com) - * - * Externs for misc. small encryption routines - * so we do not have to put them in cifsproto.h - * - * This library is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2.1 of the License, or - * (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* md4.c */ -extern void mdfour(unsigned char *out, unsigned char *in, int n); -/* smbdes.c */ -extern void E_P16(unsigned char *p14, unsigned char *p16); -extern void E_P24(unsigned char *p21, const unsigned char *c8, - unsigned char *p24); - - - diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index a8323f1dc1c..f2970136d17 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -600,10 +600,17 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, { struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; ssize_t written; + int rc; written = generic_file_aio_write(iocb, iov, nr_segs, pos); - if (!CIFS_I(inode)->clientCanCacheAll) - filemap_fdatawrite(inode->i_mapping); + + if (CIFS_I(inode)->clientCanCacheAll) + return written; + + rc = filemap_fdatawrite(inode->i_mapping); + if (rc) + cFYI(1, "cifs_file_aio_write: %d rc on %p inode", rc, inode); + return written; } @@ -737,7 +744,7 @@ const struct file_operations cifs_file_strict_ops = { .read = do_sync_read, .write = do_sync_write, .aio_read = cifs_strict_readv, - .aio_write = cifs_file_aio_write, + .aio_write = cifs_strict_writev, .open = cifs_open, .release = cifs_close, .lock = cifs_lock, @@ -793,7 +800,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = { .read = do_sync_read, .write = do_sync_write, .aio_read = cifs_strict_readv, - .aio_write = cifs_file_aio_write, + .aio_write = cifs_strict_writev, .open = cifs_open, .release = cifs_close, .fsync = cifs_strict_fsync, diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index f23206d4653..14789a97304 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -85,7 +85,9 @@ extern ssize_t cifs_user_read(struct file *file, char __user *read_data, extern ssize_t cifs_strict_readv(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, - size_t write_size, loff_t *poffset); + size_t write_size, loff_t *poffset); +extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos); extern int cifs_lock(struct file *, int, struct file_lock *); extern int cifs_fsync(struct file *, int); extern int cifs_strict_fsync(struct file *, int); diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 982895fa761..8096f27ad9a 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -85,6 +85,8 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); extern bool is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *); extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); +extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, + unsigned int bytes_written); extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *, bool); extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); extern unsigned int smbCalcSize(struct smb_hdr *ptr); @@ -373,7 +375,7 @@ extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, extern int cifs_verify_signature(struct smb_hdr *, struct TCP_Server_Info *server, __u32 expected_sequence_number); -extern void SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); +extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); extern int setup_ntlm_response(struct cifsSesInfo *); extern int setup_ntlmv2_rsp(struct cifsSesInfo *, const struct nls_table *); extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); @@ -423,4 +425,11 @@ extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, const unsigned char *path, struct cifs_sb_info *cifs_sb, int xid); +extern int mdfour(unsigned char *, unsigned char *, int); +extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); +extern void SMBencrypt(unsigned char *passwd, const unsigned char *c8, + unsigned char *p24); +extern void E_P16(unsigned char *p14, unsigned char *p16); +extern void E_P24(unsigned char *p21, const unsigned char *c8, + unsigned char *p24); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 0cc3b81c2e8..47d8ff62368 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -55,9 +55,6 @@ /* SMB echo "timeout" -- FIXME: tunable? */ #define SMB_ECHO_INTERVAL (60 * HZ) -extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, - unsigned char *p24); - extern mempool_t *cifs_req_poolp; struct smb_vol { @@ -87,6 +84,7 @@ struct smb_vol { bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ bool server_ino:1; /* use inode numbers from server ie UniqueId */ bool direct_io:1; + bool strict_io:1; /* strict cache behavior */ bool remap:1; /* set to remap seven reserved chars in filenames */ bool posix_paths:1; /* unset to not ask for posix pathnames. */ bool no_linux_ext:1; @@ -1344,6 +1342,8 @@ cifs_parse_mount_options(char *options, const char *devname, vol->direct_io = 1; } else if (strnicmp(data, "forcedirectio", 13) == 0) { vol->direct_io = 1; + } else if (strnicmp(data, "strictcache", 11) == 0) { + vol->strict_io = 1; } else if (strnicmp(data, "noac", 4) == 0) { printk(KERN_WARNING "CIFS: Mount option noac not " "supported. Instead set " @@ -2584,6 +2584,8 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info, if (pvolume_info->multiuser) cifs_sb->mnt_cifs_flags |= (CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_NO_PERM); + if (pvolume_info->strict_io) + cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_STRICT_IO; if (pvolume_info->direct_io) { cFYI(1, "mounting share using direct i/o"); cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_DIRECT_IO; @@ -2985,7 +2987,8 @@ CIFSTCon(unsigned int xid, struct cifsSesInfo *ses, bcc_ptr); else #endif /* CIFS_WEAK_PW_HASH */ - SMBNTencrypt(tcon->password, ses->server->cryptkey, bcc_ptr); + rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, + bcc_ptr); bcc_ptr += CIFS_AUTH_RESP_SIZE; if (ses->capabilities & CAP_UNICODE) { diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d7d65a70678..0de17c1db60 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -848,7 +848,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) } /* update the file size (if needed) after a write */ -static void +void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, unsigned int bytes_written) { @@ -1619,6 +1619,206 @@ int cifs_flush(struct file *file, fl_owner_t id) return rc; } +static int +cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) +{ + int rc = 0; + unsigned long i; + + for (i = 0; i < num_pages; i++) { + pages[i] = alloc_page(__GFP_HIGHMEM); + if (!pages[i]) { + /* + * save number of pages we have already allocated and + * return with ENOMEM error + */ + num_pages = i; + rc = -ENOMEM; + goto error; + } + } + + return rc; + +error: + for (i = 0; i < num_pages; i++) + put_page(pages[i]); + return rc; +} + +static inline +size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) +{ + size_t num_pages; + size_t clen; + + clen = min_t(const size_t, len, wsize); + num_pages = clen / PAGE_CACHE_SIZE; + if (clen % PAGE_CACHE_SIZE) + num_pages++; + + if (cur_len) + *cur_len = clen; + + return num_pages; +} + +static ssize_t +cifs_iovec_write(struct file *file, const struct iovec *iov, + unsigned long nr_segs, loff_t *poffset) +{ + size_t total_written = 0, written = 0; + unsigned long num_pages, npages; + size_t copied, len, cur_len, i; + struct kvec *to_send; + struct page **pages; + struct iov_iter it; + struct inode *inode; + struct cifsFileInfo *open_file; + struct cifsTconInfo *pTcon; + struct cifs_sb_info *cifs_sb; + int xid, rc; + + len = iov_length(iov, nr_segs); + if (!len) + return 0; + + rc = generic_write_checks(file, poffset, &len, 0); + if (rc) + return rc; + + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + num_pages = get_numpages(cifs_sb->wsize, len, &cur_len); + + pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL); + if (!pages) + return -ENOMEM; + + to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL); + if (!to_send) { + kfree(pages); + return -ENOMEM; + } + + rc = cifs_write_allocate_pages(pages, num_pages); + if (rc) { + kfree(pages); + kfree(to_send); + return rc; + } + + xid = GetXid(); + open_file = file->private_data; + pTcon = tlink_tcon(open_file->tlink); + inode = file->f_path.dentry->d_inode; + + iov_iter_init(&it, iov, nr_segs, len, 0); + npages = num_pages; + + do { + size_t save_len = cur_len; + for (i = 0; i < npages; i++) { + copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE); + copied = iov_iter_copy_from_user(pages[i], &it, 0, + copied); + cur_len -= copied; + iov_iter_advance(&it, copied); + to_send[i+1].iov_base = kmap(pages[i]); + to_send[i+1].iov_len = copied; + } + + cur_len = save_len - cur_len; + + do { + if (open_file->invalidHandle) { + rc = cifs_reopen_file(open_file, false); + if (rc != 0) + break; + } + rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, + cur_len, *poffset, &written, + to_send, npages, 0); + } while (rc == -EAGAIN); + + for (i = 0; i < npages; i++) + kunmap(pages[i]); + + if (written) { + len -= written; + total_written += written; + cifs_update_eof(CIFS_I(inode), *poffset, written); + *poffset += written; + } else if (rc < 0) { + if (!total_written) + total_written = rc; + break; + } + + /* get length and number of kvecs of the next write */ + npages = get_numpages(cifs_sb->wsize, len, &cur_len); + } while (len > 0); + + if (total_written > 0) { + spin_lock(&inode->i_lock); + if (*poffset > inode->i_size) + i_size_write(inode, *poffset); + spin_unlock(&inode->i_lock); + } + + cifs_stats_bytes_written(pTcon, total_written); + mark_inode_dirty_sync(inode); + + for (i = 0; i < num_pages; i++) + put_page(pages[i]); + kfree(to_send); + kfree(pages); + FreeXid(xid); + return total_written; +} + +static ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + ssize_t written; + struct inode *inode; + + inode = iocb->ki_filp->f_path.dentry->d_inode; + + /* + * BB - optimize the way when signing is disabled. We can drop this + * extra memory-to-memory copying and use iovec buffers for constructing + * write request. + */ + + written = cifs_iovec_write(iocb->ki_filp, iov, nr_segs, &pos); + if (written > 0) { + CIFS_I(inode)->invalid_mapping = true; + iocb->ki_pos = pos; + } + + return written; +} + +ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, + unsigned long nr_segs, loff_t pos) +{ + struct inode *inode; + + inode = iocb->ki_filp->f_path.dentry->d_inode; + + if (CIFS_I(inode)->clientCanCacheAll) + return generic_file_aio_write(iocb, iov, nr_segs, pos); + + /* + * In strict cache mode we need to write the data to the server exactly + * from the pos to pos+len-1 rather than flush all affected pages + * because it may cause a error with mandatory locks on these pages but + * not on the region from pos to ppos+len-1. + */ + + return cifs_user_writev(iocb, iov, nr_segs, pos); +} + static ssize_t cifs_iovec_read(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *poffset) diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 306769de2fb..02cd60aefbf 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -28,7 +28,6 @@ #include "cifsproto.h" #include "cifs_debug.h" #include "cifs_fs_sb.h" -#include "md5.h" #define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) #define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) @@ -47,6 +46,44 @@ md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15] static int +symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) +{ + int rc; + unsigned int size; + struct crypto_shash *md5; + struct sdesc *sdescmd5; + + md5 = crypto_alloc_shash("md5", 0, 0); + if (IS_ERR(md5)) { + cERROR(1, "%s: Crypto md5 allocation error %d\n", __func__, rc); + return PTR_ERR(md5); + } + size = sizeof(struct shash_desc) + crypto_shash_descsize(md5); + sdescmd5 = kmalloc(size, GFP_KERNEL); + if (!sdescmd5) { + rc = -ENOMEM; + cERROR(1, "%s: Memory allocation failure\n", __func__); + goto symlink_hash_err; + } + sdescmd5->shash.tfm = md5; + sdescmd5->shash.flags = 0x0; + + rc = crypto_shash_init(&sdescmd5->shash); + if (rc) { + cERROR(1, "%s: Could not init md5 shash\n", __func__); + goto symlink_hash_err; + } + crypto_shash_update(&sdescmd5->shash, link_str, link_len); + rc = crypto_shash_final(&sdescmd5->shash, md5_hash); + +symlink_hash_err: + crypto_free_shash(md5); + kfree(sdescmd5); + + return rc; +} + +static int CIFSParseMFSymlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len, @@ -56,7 +93,6 @@ CIFSParseMFSymlink(const u8 *buf, unsigned int link_len; const char *md5_str1; const char *link_str; - struct MD5Context md5_ctx; u8 md5_hash[16]; char md5_str2[34]; @@ -70,9 +106,11 @@ CIFSParseMFSymlink(const u8 *buf, if (rc != 1) return -EINVAL; - cifs_MD5_init(&md5_ctx); - cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); - cifs_MD5_final(md5_hash, &md5_ctx); + rc = symlink_hash(link_len, link_str, md5_hash); + if (rc) { + cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); + return rc; + } snprintf(md5_str2, sizeof(md5_str2), CIFS_MF_SYMLINK_MD5_FORMAT, @@ -94,9 +132,9 @@ CIFSParseMFSymlink(const u8 *buf, static int CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) { + int rc; unsigned int link_len; unsigned int ofs; - struct MD5Context md5_ctx; u8 md5_hash[16]; if (buf_len != CIFS_MF_SYMLINK_FILE_SIZE) @@ -107,9 +145,11 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) if (link_len > CIFS_MF_SYMLINK_LINK_MAXLEN) return -ENAMETOOLONG; - cifs_MD5_init(&md5_ctx); - cifs_MD5_update(&md5_ctx, (const u8 *)link_str, link_len); - cifs_MD5_final(md5_hash, &md5_ctx); + rc = symlink_hash(link_len, link_str, md5_hash); + if (rc) { + cFYI(1, "%s: MD5 hash failure: %d\n", __func__, rc); + return rc; + } snprintf(buf, buf_len, CIFS_MF_SYMLINK_LEN_FORMAT CIFS_MF_SYMLINK_MD5_FORMAT, diff --git a/fs/cifs/md4.c b/fs/cifs/md4.c deleted file mode 100644 index a725c2609d6..00000000000 --- a/fs/cifs/md4.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - Unix SMB/Netbios implementation. - Version 1.9. - a implementation of MD4 designed for use in the SMB authentication protocol - Copyright (C) Andrew Tridgell 1997-1998. - Modified by Steve French (sfrench@us.ibm.com) 2002-2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ -#include <linux/module.h> -#include <linux/fs.h> -#include "cifsencrypt.h" - -/* NOTE: This code makes no attempt to be fast! */ - -static __u32 -F(__u32 X, __u32 Y, __u32 Z) -{ - return (X & Y) | ((~X) & Z); -} - -static __u32 -G(__u32 X, __u32 Y, __u32 Z) -{ - return (X & Y) | (X & Z) | (Y & Z); -} - -static __u32 -H(__u32 X, __u32 Y, __u32 Z) -{ - return X ^ Y ^ Z; -} - -static __u32 -lshift(__u32 x, int s) -{ - x &= 0xFFFFFFFF; - return ((x << s) & 0xFFFFFFFF) | (x >> (32 - s)); -} - -#define ROUND1(a,b,c,d,k,s) (*a) = lshift((*a) + F(*b,*c,*d) + X[k], s) -#define ROUND2(a,b,c,d,k,s) (*a) = lshift((*a) + G(*b,*c,*d) + X[k] + (__u32)0x5A827999,s) -#define ROUND3(a,b,c,d,k,s) (*a) = lshift((*a) + H(*b,*c,*d) + X[k] + (__u32)0x6ED9EBA1,s) - -/* this applies md4 to 64 byte chunks */ -static void -mdfour64(__u32 *M, __u32 *A, __u32 *B, __u32 *C, __u32 *D) -{ - int j; - __u32 AA, BB, CC, DD; - __u32 X[16]; - - - for (j = 0; j < 16; j++) - X[j] = M[j]; - - AA = *A; - BB = *B; - CC = *C; - DD = *D; - - ROUND1(A, B, C, D, 0, 3); - ROUND1(D, A, B, C, 1, 7); - ROUND1(C, D, A, B, 2, 11); - ROUND1(B, C, D, A, 3, 19); - ROUND1(A, B, C, D, 4, 3); - ROUND1(D, A, B, C, 5, 7); - ROUND1(C, D, A, B, 6, 11); - ROUND1(B, C, D, A, 7, 19); - ROUND1(A, B, C, D, 8, 3); - ROUND1(D, A, B, C, 9, 7); - ROUND1(C, D, A, B, 10, 11); - ROUND1(B, C, D, A, 11, 19); - ROUND1(A, B, C, D, 12, 3); - ROUND1(D, A, B, C, 13, 7); - ROUND1(C, D, A, B, 14, 11); - ROUND1(B, C, D, A, 15, 19); - - ROUND2(A, B, C, D, 0, 3); - ROUND2(D, A, B, C, 4, 5); - ROUND2(C, D, A, B, 8, 9); - ROUND2(B, C, D, A, 12, 13); - ROUND2(A, B, C, D, 1, 3); - ROUND2(D, A, B, C, 5, 5); - ROUND2(C, D, A, B, 9, 9); - ROUND2(B, C, D, A, 13, 13); - ROUND2(A, B, C, D, 2, 3); - ROUND2(D, A, B, C, 6, 5); - ROUND2(C, D, A, B, 10, 9); - ROUND2(B, C, D, A, 14, 13); - ROUND2(A, B, C, D, 3, 3); - ROUND2(D, A, B, C, 7, 5); - ROUND2(C, D, A, B, 11, 9); - ROUND2(B, C, D, A, 15, 13); - - ROUND3(A, B, C, D, 0, 3); - ROUND3(D, A, B, C, 8, 9); - ROUND3(C, D, A, B, 4, 11); - ROUND3(B, C, D, A, 12, 15); - ROUND3(A, B, C, D, 2, 3); - ROUND3(D, A, B, C, 10, 9); - ROUND3(C, D, A, B, 6, 11); - ROUND3(B, C, D, A, 14, 15); - ROUND3(A, B, C, D, 1, 3); - ROUND3(D, A, B, C, 9, 9); - ROUND3(C, D, A, B, 5, 11); - ROUND3(B, C, D, A, 13, 15); - ROUND3(A, B, C, D, 3, 3); - ROUND3(D, A, B, C, 11, 9); - ROUND3(C, D, A, B, 7, 11); - ROUND3(B, C, D, A, 15, 15); - - *A += AA; - *B += BB; - *C += CC; - *D += DD; - - *A &= 0xFFFFFFFF; - *B &= 0xFFFFFFFF; - *C &= 0xFFFFFFFF; - *D &= 0xFFFFFFFF; - - for (j = 0; j < 16; j++) - X[j] = 0; -} - -static void -copy64(__u32 *M, unsigned char *in) -{ - int i; - - for (i = 0; i < 16; i++) - M[i] = (in[i * 4 + 3] << 24) | (in[i * 4 + 2] << 16) | - (in[i * 4 + 1] << 8) | (in[i * 4 + 0] << 0); -} - -static void -copy4(unsigned char *out, __u32 x) -{ - out[0] = x & 0xFF; - out[1] = (x >> 8) & 0xFF; - out[2] = (x >> 16) & 0xFF; - out[3] = (x >> 24) & 0xFF; -} - -/* produce a md4 message digest from data of length n bytes */ -void -mdfour(unsigned char *out, unsigned char *in, int n) -{ - unsigned char buf[128]; - __u32 M[16]; - __u32 b = n * 8; - int i; - __u32 A = 0x67452301; - __u32 B = 0xefcdab89; - __u32 C = 0x98badcfe; - __u32 D = 0x10325476; - - while (n > 64) { - copy64(M, in); - mdfour64(M, &A, &B, &C, &D); - in += 64; - n -= 64; - } - - for (i = 0; i < 128; i++) - buf[i] = 0; - memcpy(buf, in, n); - buf[n] = 0x80; - - if (n <= 55) { - copy4(buf + 56, b); - copy64(M, buf); - mdfour64(M, &A, &B, &C, &D); - } else { - copy4(buf + 120, b); - copy64(M, buf); - mdfour64(M, &A, &B, &C, &D); - copy64(M, buf + 64); - mdfour64(M, &A, &B, &C, &D); - } - - for (i = 0; i < 128; i++) - buf[i] = 0; - copy64(M, buf); - - copy4(out, A); - copy4(out + 4, B); - copy4(out + 8, C); - copy4(out + 12, D); - - A = B = C = D = 0; -} diff --git a/fs/cifs/md5.c b/fs/cifs/md5.c deleted file mode 100644 index 98b66a54c31..00000000000 --- a/fs/cifs/md5.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5Context structure, pass it to cifs_MD5_init, call cifs_MD5_update as - * needed on buffers full of bytes, and then call cifs_MD5_final, which - * will fill a supplied 16-byte array with the digest. - */ - -/* This code slightly modified to fit into Samba by - abartlet@samba.org Jun 2001 - and to fit the cifs vfs by - Steve French sfrench@us.ibm.com */ - -#include <linux/string.h> -#include "md5.h" - -static void MD5Transform(__u32 buf[4], __u32 const in[16]); - -/* - * Note: this code is harmless on little-endian machines. - */ -static void -byteReverse(unsigned char *buf, unsigned longs) -{ - __u32 t; - do { - t = (__u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | - ((unsigned) buf[1] << 8 | buf[0]); - *(__u32 *) buf = t; - buf += 4; - } while (--longs); -} - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -cifs_MD5_init(struct MD5Context *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -cifs_MD5_update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) -{ - register __u32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((__u32) len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if (t) { - unsigned char *p = (unsigned char *) ctx->in + t; - - t = 64 - t; - if (len < t) { - memmove(p, buf, len); - return; - } - memmove(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (__u32 *) ctx->in); - buf += t; - len -= t; - } - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memmove(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (__u32 *) ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memmove(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -cifs_MD5_final(unsigned char digest[16], struct MD5Context *ctx) -{ - unsigned int count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (__u32 *) ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count - 8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((__u32 *) ctx->in)[14] = ctx->bits[0]; - ((__u32 *) ctx->in)[15] = ctx->bits[1]; - - MD5Transform(ctx->buf, (__u32 *) ctx->in); - byteReverse((unsigned char *) ctx->buf, 4); - memmove(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) \ - (w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. cifs_MD5_update blocks - * the data and converts bytes into longwords for this routine. - */ -static void -MD5Transform(__u32 buf[4], __u32 const in[16]) -{ - register __u32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -#if 0 /* currently unused */ -/*********************************************************************** - the rfc 2104 version of hmac_md5 initialisation. -***********************************************************************/ -static void -hmac_md5_init_rfc2104(unsigned char *key, int key_len, - struct HMACMD5Context *ctx) -{ - int i; - - /* if key is longer than 64 bytes reset it to key=MD5(key) */ - if (key_len > 64) { - unsigned char tk[16]; - struct MD5Context tctx; - - cifs_MD5_init(&tctx); - cifs_MD5_update(&tctx, key, key_len); - cifs_MD5_final(tk, &tctx); - - key = tk; - key_len = 16; - } - - /* start out by storing key in pads */ - memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); - memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); - memcpy(ctx->k_ipad, key, key_len); - memcpy(ctx->k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - ctx->k_ipad[i] ^= 0x36; - ctx->k_opad[i] ^= 0x5c; - } - - cifs_MD5_init(&ctx->ctx); - cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64); -} -#endif - -/*********************************************************************** - the microsoft version of hmac_md5 initialisation. -***********************************************************************/ -void -hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, - struct HMACMD5Context *ctx) -{ - int i; - - /* if key is longer than 64 bytes truncate it */ - if (key_len > 64) - key_len = 64; - - /* start out by storing key in pads */ - memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad)); - memset(ctx->k_opad, 0, sizeof(ctx->k_opad)); - memcpy(ctx->k_ipad, key, key_len); - memcpy(ctx->k_opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - ctx->k_ipad[i] ^= 0x36; - ctx->k_opad[i] ^= 0x5c; - } - - cifs_MD5_init(&ctx->ctx); - cifs_MD5_update(&ctx->ctx, ctx->k_ipad, 64); -} - -/*********************************************************************** - update hmac_md5 "inner" buffer -***********************************************************************/ -void -hmac_md5_update(const unsigned char *text, int text_len, - struct HMACMD5Context *ctx) -{ - cifs_MD5_update(&ctx->ctx, text, text_len); /* then text of datagram */ -} - -/*********************************************************************** - finish off hmac_md5 "inner" buffer and generate outer one. -***********************************************************************/ -void -hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx) -{ - struct MD5Context ctx_o; - - cifs_MD5_final(digest, &ctx->ctx); - - cifs_MD5_init(&ctx_o); - cifs_MD5_update(&ctx_o, ctx->k_opad, 64); - cifs_MD5_update(&ctx_o, digest, 16); - cifs_MD5_final(digest, &ctx_o); -} - -/*********************************************************** - single function to calculate an HMAC MD5 digest from data. - use the microsoft hmacmd5 init method because the key is 16 bytes. -************************************************************/ -#if 0 /* currently unused */ -static void -hmac_md5(unsigned char key[16], unsigned char *data, int data_len, - unsigned char *digest) -{ - struct HMACMD5Context ctx; - hmac_md5_init_limK_to_64(key, 16, &ctx); - if (data_len != 0) - hmac_md5_update(data, data_len, &ctx); - - hmac_md5_final(digest, &ctx); -} -#endif diff --git a/fs/cifs/md5.h b/fs/cifs/md5.h deleted file mode 100644 index 6fba8cb402f..00000000000 --- a/fs/cifs/md5.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MD5_H -#define MD5_H -#ifndef HEADER_MD5_H -/* Try to avoid clashes with OpenSSL */ -#define HEADER_MD5_H -#endif - -struct MD5Context { - __u32 buf[4]; - __u32 bits[2]; - unsigned char in[64]; -}; -#endif /* !MD5_H */ - -#ifndef _HMAC_MD5_H -struct HMACMD5Context { - struct MD5Context ctx; - unsigned char k_ipad[65]; - unsigned char k_opad[65]; -}; -#endif /* _HMAC_MD5_H */ - -void cifs_MD5_init(struct MD5Context *context); -void cifs_MD5_update(struct MD5Context *context, unsigned char const *buf, - unsigned len); -void cifs_MD5_final(unsigned char digest[16], struct MD5Context *context); - -/* The following definitions come from lib/hmacmd5.c */ - -/* void hmac_md5_init_rfc2104(unsigned char *key, int key_len, - struct HMACMD5Context *ctx);*/ -void hmac_md5_init_limK_to_64(const unsigned char *key, int key_len, - struct HMACMD5Context *ctx); -void hmac_md5_update(const unsigned char *text, int text_len, - struct HMACMD5Context *ctx); -void hmac_md5_final(unsigned char *digest, struct HMACMD5Context *ctx); -/* void hmac_md5(unsigned char key[16], unsigned char *data, int data_len, - unsigned char *digest);*/ diff --git a/fs/cifs/smbdes.c b/fs/cifs/smbdes.c index b6b6dcb500b..04721485925 100644 --- a/fs/cifs/smbdes.c +++ b/fs/cifs/smbdes.c @@ -45,7 +45,6 @@ up with a different answer to the one above) */ #include <linux/slab.h> -#include "cifsencrypt.h" #define uchar unsigned char static uchar perm1[56] = { 57, 49, 41, 33, 25, 17, 9, diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 192ea51af20..b5450e9f40c 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -32,9 +32,8 @@ #include "cifs_unicode.h" #include "cifspdu.h" #include "cifsglob.h" -#include "md5.h" #include "cifs_debug.h" -#include "cifsencrypt.h" +#include "cifsproto.h" #ifndef false #define false 0 @@ -48,14 +47,57 @@ #define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) #define SSVAL(buf,pos,val) SSVALX((buf),(pos),((__u16)(val))) -/*The following definitions come from libsmb/smbencrypt.c */ +/* produce a md4 message digest from data of length n bytes */ +int +mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) +{ + int rc; + unsigned int size; + struct crypto_shash *md4; + struct sdesc *sdescmd4; + + md4 = crypto_alloc_shash("md4", 0, 0); + if (IS_ERR(md4)) { + cERROR(1, "%s: Crypto md4 allocation error %d\n", __func__, rc); + return PTR_ERR(md4); + } + size = sizeof(struct shash_desc) + crypto_shash_descsize(md4); + sdescmd4 = kmalloc(size, GFP_KERNEL); + if (!sdescmd4) { + rc = -ENOMEM; + cERROR(1, "%s: Memory allocation failure\n", __func__); + goto mdfour_err; + } + sdescmd4->shash.tfm = md4; + sdescmd4->shash.flags = 0x0; + + rc = crypto_shash_init(&sdescmd4->shash); + if (rc) { + cERROR(1, "%s: Could not init md4 shash\n", __func__); + goto mdfour_err; + } + crypto_shash_update(&sdescmd4->shash, link_str, link_len); + rc = crypto_shash_final(&sdescmd4->shash, md4_hash); -void SMBencrypt(unsigned char *passwd, const unsigned char *c8, - unsigned char *p24); -void E_md4hash(const unsigned char *passwd, unsigned char *p16); -static void SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, - unsigned char p24[24]); -void SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24); +mdfour_err: + crypto_free_shash(md4); + kfree(sdescmd4); + + return rc; +} + +/* Does the des encryption from the NT or LM MD4 hash. */ +static void +SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, + unsigned char p24[24]) +{ + unsigned char p21[21]; + + memset(p21, '\0', 21); + + memcpy(p21, passwd, 16); + E_P24(p21, c8, p24); +} /* This implements the X/Open SMB password encryption @@ -118,9 +160,10 @@ _my_mbstowcs(__u16 *dst, const unsigned char *src, int len) * Creates the MD4 Hash of the users password in NT UNICODE. */ -void +int E_md4hash(const unsigned char *passwd, unsigned char *p16) { + int rc; int len; __u16 wpwd[129]; @@ -139,8 +182,10 @@ E_md4hash(const unsigned char *passwd, unsigned char *p16) /* Calculate length in bytes */ len = _my_wcslen(wpwd) * sizeof(__u16); - mdfour(p16, (unsigned char *) wpwd, len); + rc = mdfour(p16, (unsigned char *) wpwd, len); memset(wpwd, 0, 129 * 2); + + return rc; } #if 0 /* currently unused */ @@ -212,19 +257,6 @@ ntv2_owf_gen(const unsigned char owf[16], const char *user_n, } #endif -/* Does the des encryption from the NT or LM MD4 hash. */ -static void -SMBOWFencrypt(unsigned char passwd[16], const unsigned char *c8, - unsigned char p24[24]) -{ - unsigned char p21[21]; - - memset(p21, '\0', 21); - - memcpy(p21, passwd, 16); - E_P24(p21, c8, p24); -} - /* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ #if 0 /* currently unused */ static void @@ -242,16 +274,21 @@ NTLMSSPOWFencrypt(unsigned char passwd[8], #endif /* Does the NT MD4 hash then des encryption. */ - -void +int SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) { + int rc; unsigned char p21[21]; memset(p21, '\0', 21); - E_md4hash(passwd, p21); + rc = E_md4hash(passwd, p21); + if (rc) { + cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); + return rc; + } SMBOWFencrypt(p21, c8, p24); + return rc; } diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index b572b672718..326e7475a22 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -1,7 +1,7 @@ /** * mft.c - NTFS kernel mft record operations. Part of the Linux-NTFS project. * - * Copyright (c) 2001-2006 Anton Altaparmakov + * Copyright (c) 2001-2011 Anton Altaparmakov and Tuxera Inc. * Copyright (c) 2002 Richard Russon * * This program/include file is free software; you can redistribute it and/or @@ -2576,6 +2576,8 @@ mft_rec_already_initialized: flush_dcache_page(page); SetPageUptodate(page); if (base_ni) { + MFT_RECORD *m_tmp; + /* * Setup the base mft record in the extent mft record. This * completes initialization of the allocated extent mft record @@ -2588,11 +2590,11 @@ mft_rec_already_initialized: * attach it to the base inode @base_ni and map, pin, and lock * its, i.e. the allocated, mft record. */ - m = map_extent_mft_record(base_ni, bit, &ni); - if (IS_ERR(m)) { + m_tmp = map_extent_mft_record(base_ni, bit, &ni); + if (IS_ERR(m_tmp)) { ntfs_error(vol->sb, "Failed to map allocated extent " "mft record 0x%llx.", (long long)bit); - err = PTR_ERR(m); + err = PTR_ERR(m_tmp); /* Set the mft record itself not in use. */ m->flags &= cpu_to_le16( ~le16_to_cpu(MFT_RECORD_IN_USE)); @@ -2603,6 +2605,7 @@ mft_rec_already_initialized: ntfs_unmap_page(page); goto undo_mftbmp_alloc; } + BUG_ON(m != m_tmp); /* * Make sure the allocated mft record is written out to disk. * No need to set the inode dirty because the caller is going diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index b06ede1d0be..f5e2a19e0f8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c @@ -985,10 +985,22 @@ xfs_ioctl_setattr( /* * Extent size must be a multiple of the appropriate block - * size, if set at all. + * size, if set at all. It must also be smaller than the + * maximum extent size supported by the filesystem. + * + * Also, for non-realtime files, limit the extent size hint to + * half the size of the AGs in the filesystem so alignment + * doesn't result in extents larger than an AG. */ if (fa->fsx_extsize != 0) { - xfs_extlen_t size; + xfs_extlen_t size; + xfs_fsblock_t extsize_fsb; + + extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize); + if (extsize_fsb > MAXEXTLEN) { + code = XFS_ERROR(EINVAL); + goto error_return; + } if (XFS_IS_REALTIME_INODE(ip) || ((mask & FSX_XFLAGS) && @@ -997,6 +1009,10 @@ xfs_ioctl_setattr( mp->m_sb.sb_blocklog; } else { size = mp->m_sb.sb_blocksize; + if (extsize_fsb > mp->m_sb.sb_agblocks / 2) { + code = XFS_ERROR(EINVAL); + goto error_return; + } } if (fa->fsx_extsize % size) { diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index f8e854b4fde..206a2815ced 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c @@ -1863,12 +1863,14 @@ xfs_qm_dqreclaim_one(void) xfs_dquot_t *dqpout; xfs_dquot_t *dqp; int restarts; + int startagain; restarts = 0; dqpout = NULL; /* lockorder: hashchainlock, freelistlock, mplistlock, dqlock, dqflock */ -startagain: +again: + startagain = 0; mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { @@ -1885,13 +1887,10 @@ startagain: ASSERT(! (dqp->dq_flags & XFS_DQ_INACTIVE)); trace_xfs_dqreclaim_want(dqp); - - xfs_dqunlock(dqp); - mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); - if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) - return NULL; XQM_STATS_INC(xqmstats.xs_qm_dqwants); - goto startagain; + restarts++; + startagain = 1; + goto dqunlock; } /* @@ -1906,23 +1905,20 @@ startagain: ASSERT(list_empty(&dqp->q_mplist)); list_del_init(&dqp->q_freelist); xfs_Gqm->qm_dqfrlist_cnt--; - xfs_dqunlock(dqp); dqpout = dqp; XQM_STATS_INC(xqmstats.xs_qm_dqinact_reclaims); - break; + goto dqunlock; } ASSERT(dqp->q_hash); ASSERT(!list_empty(&dqp->q_mplist)); /* - * Try to grab the flush lock. If this dquot is in the process of - * getting flushed to disk, we don't want to reclaim it. + * Try to grab the flush lock. If this dquot is in the process + * of getting flushed to disk, we don't want to reclaim it. */ - if (!xfs_dqflock_nowait(dqp)) { - xfs_dqunlock(dqp); - continue; - } + if (!xfs_dqflock_nowait(dqp)) + goto dqunlock; /* * We have the flush lock so we know that this is not in the @@ -1944,8 +1940,7 @@ startagain: xfs_fs_cmn_err(CE_WARN, mp, "xfs_qm_dqreclaim: dquot %p flush failed", dqp); } - xfs_dqunlock(dqp); /* dqflush unlocks dqflock */ - continue; + goto dqunlock; } /* @@ -1967,13 +1962,8 @@ startagain: */ if (!mutex_trylock(&mp->m_quotainfo->qi_dqlist_lock)) { restarts++; - mutex_unlock(&dqp->q_hash->qh_lock); - xfs_dqfunlock(dqp); - xfs_dqunlock(dqp); - mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); - if (restarts++ >= XFS_QM_RECLAIM_MAX_RESTARTS) - return NULL; - goto startagain; + startagain = 1; + goto qhunlock; } ASSERT(dqp->q_nrefs == 0); @@ -1986,14 +1976,20 @@ startagain: xfs_Gqm->qm_dqfrlist_cnt--; dqpout = dqp; mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); +qhunlock: mutex_unlock(&dqp->q_hash->qh_lock); dqfunlock: xfs_dqfunlock(dqp); +dqunlock: xfs_dqunlock(dqp); if (dqpout) break; if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) - return NULL; + break; + if (startagain) { + mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); + goto again; + } } mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); return dqpout; diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 0ab56b32c7e..d0b3bc72005 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h @@ -75,6 +75,22 @@ typedef unsigned int xfs_alloctype_t; #define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) /* + * When deciding how much space to allocate out of an AG, we limit the + * allocation maximum size to the size the AG. However, we cannot use all the + * blocks in the AG - some are permanently used by metadata. These + * blocks are generally: + * - the AG superblock, AGF, AGI and AGFL + * - the AGF (bno and cnt) and AGI btree root blocks + * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits + * + * The AG headers are sector sized, so the amount of space they take up is + * dependent on filesystem geometry. The others are all single blocks. + */ +#define XFS_ALLOC_AG_MAX_USABLE(mp) \ + ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) + + +/* * Argument structure for xfs_alloc routines. * This is turned into a structure to avoid having 20 arguments passed * down several levels of the stack. diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 4111cd3966c..dc3afd7739f 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -1038,17 +1038,34 @@ xfs_bmap_add_extent_delay_real( * Filling in the middle part of a previous delayed allocation. * Contiguity is impossible here. * This case is avoided almost all the time. + * + * We start with a delayed allocation: + * + * +ddddddddddddddddddddddddddddddddddddddddddddddddddddddd+ + * PREV @ idx + * + * and we are allocating: + * +rrrrrrrrrrrrrrrrr+ + * new + * + * and we set it up for insertion as: + * +ddddddddddddddddddd+rrrrrrrrrrrrrrrrr+ddddddddddddddddd+ + * new + * PREV @ idx LEFT RIGHT + * inserted at idx + 1 */ temp = new->br_startoff - PREV.br_startoff; - trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); - xfs_bmbt_set_blockcount(ep, temp); - r[0] = *new; - r[1].br_state = PREV.br_state; - r[1].br_startblock = 0; - r[1].br_startoff = new_endoff; temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; - r[1].br_blockcount = temp2; - xfs_iext_insert(ip, idx + 1, 2, &r[0], state); + trace_xfs_bmap_pre_update(ip, idx, 0, _THIS_IP_); + xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ + LEFT = *new; + RIGHT.br_state = PREV.br_state; + RIGHT.br_startblock = nullstartblock( + (int)xfs_bmap_worst_indlen(ip, temp2)); + RIGHT.br_startoff = new_endoff; + RIGHT.br_blockcount = temp2; + /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ + xfs_iext_insert(ip, idx + 1, 2, &LEFT, state); ip->i_df.if_lastex = idx + 1; ip->i_d.di_nextents++; if (cur == NULL) @@ -2430,7 +2447,7 @@ xfs_bmap_btalloc_nullfb( startag = ag = 0; pag = xfs_perag_get(mp, ag); - while (*blen < ap->alen) { + while (*blen < args->maxlen) { if (!pag->pagf_init) { error = xfs_alloc_pagf_init(mp, args->tp, ag, XFS_ALLOC_FLAG_TRYLOCK); @@ -2452,7 +2469,7 @@ xfs_bmap_btalloc_nullfb( notinit = 1; if (xfs_inode_is_filestream(ap->ip)) { - if (*blen >= ap->alen) + if (*blen >= args->maxlen) break; if (ap->userdata) { @@ -2498,14 +2515,14 @@ xfs_bmap_btalloc_nullfb( * If the best seen length is less than the request * length, use the best as the minimum. */ - else if (*blen < ap->alen) + else if (*blen < args->maxlen) args->minlen = *blen; /* - * Otherwise we've seen an extent as big as alen, + * Otherwise we've seen an extent as big as maxlen, * use that as the minimum. */ else - args->minlen = ap->alen; + args->minlen = args->maxlen; /* * set the failure fallback case to look in the selected @@ -2573,7 +2590,9 @@ xfs_bmap_btalloc( args.tp = ap->tp; args.mp = mp; args.fsbno = ap->rval; - args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); + + /* Trim the allocation back to the maximum an AG can fit. */ + args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); args.firstblock = ap->firstblock; blen = 0; if (nullfb) { @@ -2621,7 +2640,7 @@ xfs_bmap_btalloc( /* * Adjust for alignment */ - if (blen > args.alignment && blen <= ap->alen) + if (blen > args.alignment && blen <= args.maxlen) args.minlen = blen - args.alignment; args.minalignslop = 0; } else { @@ -2640,7 +2659,7 @@ xfs_bmap_btalloc( * of minlen+alignment+slop doesn't go up * between the calls. */ - if (blen > mp->m_dalign && blen <= ap->alen) + if (blen > mp->m_dalign && blen <= args.maxlen) nextminlen = blen - mp->m_dalign; else nextminlen = args.minlen; @@ -4485,6 +4504,16 @@ xfs_bmapi( /* Figure out the extent size, adjust alen */ extsz = xfs_get_extsz_hint(ip); if (extsz) { + /* + * make sure we don't exceed a single + * extent length when we align the + * extent by reducing length we are + * going to allocate by the maximum + * amount extent size aligment may + * require. + */ + alen = XFS_FILBLKS_MIN(len, + MAXEXTLEN - (2 * extsz - 1)); error = xfs_bmap_extsize_align(mp, &got, &prev, extsz, rt, eof, diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 98c6f73b675..6f8c21ce0d6 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -427,13 +427,15 @@ xfs_buf_item_unpin( if (remove) { /* - * We have to remove the log item from the transaction - * as we are about to release our reference to the - * buffer. If we don't, the unlock that occurs later - * in xfs_trans_uncommit() will ry to reference the + * If we are in a transaction context, we have to + * remove the log item from the transaction as we are + * about to release our reference to the buffer. If we + * don't, the unlock that occurs later in + * xfs_trans_uncommit() will try to reference the * buffer which we no longer have a hold on. */ - xfs_trans_del_item(lip); + if (lip->li_desc) + xfs_trans_del_item(lip); /* * Since the transaction no longer refers to the buffer, diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index 75f2ef60e57..d22e6262343 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c @@ -138,7 +138,8 @@ xfs_efi_item_unpin( if (remove) { ASSERT(!(lip->li_flags & XFS_LI_IN_AIL)); - xfs_trans_del_item(lip); + if (lip->li_desc) + xfs_trans_del_item(lip); xfs_efi_item_free(efip); return; } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 55582bd6665..8a0f044750c 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -337,7 +337,12 @@ xfs_iomap_prealloc_size( int shift = 0; int64_t freesp; - alloc_blocks = XFS_B_TO_FSB(mp, ip->i_size); + /* + * rounddown_pow_of_two() returns an undefined result + * if we pass in alloc_blocks = 0. Hence the "+ 1" to + * ensure we always pass in a non-zero value. + */ + alloc_blocks = XFS_B_TO_FSB(mp, ip->i_size) + 1; alloc_blocks = XFS_FILEOFF_MIN(MAXEXTLEN, rounddown_pow_of_two(alloc_blocks)); diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 916eb7db14d..3bd3291ef8d 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h @@ -191,7 +191,7 @@ void xfs_log_ticket_put(struct xlog_ticket *ticket); xlog_tid_t xfs_log_get_trans_ident(struct xfs_trans *tp); -int xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, +void xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, struct xfs_log_vec *log_vector, xfs_lsn_t *commit_lsn, int flags); bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip); diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c index 9dc8125d04e..9ca59be0897 100644 --- a/fs/xfs/xfs_log_cil.c +++ b/fs/xfs/xfs_log_cil.c @@ -543,7 +543,7 @@ xlog_cil_push( error = xlog_write(log, &lvhdr, tic, &ctx->start_lsn, NULL, 0); if (error) - goto out_abort; + goto out_abort_free_ticket; /* * now that we've written the checkpoint into the log, strictly @@ -569,8 +569,9 @@ restart: } spin_unlock(&cil->xc_cil_lock); + /* xfs_log_done always frees the ticket on error. */ commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, 0); - if (error || commit_lsn == -1) + if (commit_lsn == -1) goto out_abort; /* attach all the transactions w/ busy extents to iclog */ @@ -600,6 +601,8 @@ out_free_ticket: kmem_free(new_ctx); return 0; +out_abort_free_ticket: + xfs_log_ticket_put(tic); out_abort: xlog_cil_committed(ctx, XFS_LI_ABORTED); return XFS_ERROR(EIO); @@ -622,7 +625,7 @@ out_abort: * background commit, returns without it held once background commits are * allowed again. */ -int +void xfs_log_commit_cil( struct xfs_mount *mp, struct xfs_trans *tp, @@ -637,11 +640,6 @@ xfs_log_commit_cil( if (flags & XFS_TRANS_RELEASE_LOG_RES) log_flags = XFS_LOG_REL_PERM_RESERV; - if (XLOG_FORCED_SHUTDOWN(log)) { - xlog_cil_free_logvec(log_vector); - return XFS_ERROR(EIO); - } - /* * do all the hard work of formatting items (including memory * allocation) outside the CIL context lock. This prevents stalling CIL @@ -701,7 +699,6 @@ xfs_log_commit_cil( */ if (push) xlog_cil_push(log, 0); - return 0; } /* diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 33dbc4e0ad6..76922793f64 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c @@ -1446,6 +1446,14 @@ xfs_log_item_batch_insert( * Bulk operation version of xfs_trans_committed that takes a log vector of * items to insert into the AIL. This uses bulk AIL insertion techniques to * minimise lock traffic. + * + * If we are called with the aborted flag set, it is because a log write during + * a CIL checkpoint commit has failed. In this case, all the items in the + * checkpoint have already gone through IOP_COMMITED and IOP_UNLOCK, which + * means that checkpoint commit abort handling is treated exactly the same + * as an iclog write error even though we haven't started any IO yet. Hence in + * this case all we need to do is IOP_COMMITTED processing, followed by an + * IOP_UNPIN(aborted) call. */ void xfs_trans_committed_bulk( @@ -1472,6 +1480,16 @@ xfs_trans_committed_bulk( if (XFS_LSN_CMP(item_lsn, (xfs_lsn_t)-1) == 0) continue; + /* + * if we are aborting the operation, no point in inserting the + * object into the AIL as we are in a shutdown situation. + */ + if (aborted) { + ASSERT(XFS_FORCED_SHUTDOWN(ailp->xa_mount)); + IOP_UNPIN(lip, 1); + continue; + } + if (item_lsn != commit_lsn) { /* @@ -1503,20 +1521,24 @@ xfs_trans_committed_bulk( } /* - * Called from the trans_commit code when we notice that - * the filesystem is in the middle of a forced shutdown. + * Called from the trans_commit code when we notice that the filesystem is in + * the middle of a forced shutdown. + * + * When we are called here, we have already pinned all the items in the + * transaction. However, neither IOP_COMMITTING or IOP_UNLOCK has been called + * so we can simply walk the items in the transaction, unpin them with an abort + * flag and then free the items. Note that unpinning the items can result in + * them being freed immediately, so we need to use a safe list traversal method + * here. */ STATIC void xfs_trans_uncommit( struct xfs_trans *tp, uint flags) { - struct xfs_log_item_desc *lidp; + struct xfs_log_item_desc *lidp, *n; - list_for_each_entry(lidp, &tp->t_items, lid_trans) { - /* - * Unpin all but those that aren't dirty. - */ + list_for_each_entry_safe(lidp, n, &tp->t_items, lid_trans) { if (lidp->lid_flags & XFS_LID_DIRTY) IOP_UNPIN(lidp->lid_item, 1); } @@ -1733,7 +1755,6 @@ xfs_trans_commit_cil( int flags) { struct xfs_log_vec *log_vector; - int error; /* * Get each log item to allocate a vector structure for @@ -1744,9 +1765,7 @@ xfs_trans_commit_cil( if (!log_vector) return ENOMEM; - error = xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); - if (error) - return error; + xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags); current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); xfs_trans_free(tp); diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e2f4d6af212..2fe6e84894a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -588,7 +588,7 @@ struct sysinfo { /** * BUILD_BUG_ON - break compile if a condition is true. - * @cond: the condition which the compiler should know is false. + * @condition: the condition which the compiler should know is false. * * If you have some code which relies on certain constants being equal, or * other compile-time-evaluated condition, you should use BUILD_BUG_ON to diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index dd6ee49a084..a854fe89484 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -112,6 +112,7 @@ struct usb_hcd { /* Flags that get set only during HCD registration or removal. */ unsigned rh_registered:1;/* is root hub registered? */ unsigned rh_pollable:1; /* may we poll the root hub? */ + unsigned msix_enabled:1; /* driver has MSI-X enabled? */ /* The next flag is a stopgap, to be removed when all the HCDs * support the new root-hub polling mechanism. */ diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 16d682f4f7c..c9049139a7a 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -347,6 +347,9 @@ extern int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, extern int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch); extern int usb_serial_handle_break(struct usb_serial_port *port); +extern void usb_serial_handle_dcd_change(struct usb_serial_port *usb_port, + struct tty_struct *tty, + unsigned int status); extern int usb_serial_bus_register(struct usb_serial_driver *device); diff --git a/kernel/sys.c b/kernel/sys.c index 31b71a276b4..18da702ec81 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1385,7 +1385,8 @@ static int check_prlimit_permission(struct task_struct *task) const struct cred *cred = current_cred(), *tcred; tcred = __task_cred(task); - if ((cred->uid != tcred->euid || + if (current != task && + (cred->uid != tcred->euid || cred->uid != tcred->suid || cred->uid != tcred->uid || cred->gid != tcred->egid || diff --git a/lib/rbtree.c b/lib/rbtree.c index 4693f79195d..a16be19a130 100644 --- a/lib/rbtree.c +++ b/lib/rbtree.c @@ -315,6 +315,7 @@ void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) rb_augment_path(node, func, data); } +EXPORT_SYMBOL(rb_augment_insert); /* * before removing the node, find the deepest node on the rebalance path @@ -340,6 +341,7 @@ struct rb_node *rb_augment_erase_begin(struct rb_node *node) return deepest; } +EXPORT_SYMBOL(rb_augment_erase_begin); /* * after removal, update the tree to account for the removed entry @@ -350,6 +352,7 @@ void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) if (node) rb_augment_path(node, func, data); } +EXPORT_SYMBOL(rb_augment_erase_end); /* * This function returns the first node (in sort order) of the tree. diff --git a/mm/kmemleak-test.c b/mm/kmemleak-test.c index 177a5169bbd..ff0d9779cec 100644 --- a/mm/kmemleak-test.c +++ b/mm/kmemleak-test.c @@ -75,13 +75,11 @@ static int __init kmemleak_test_init(void) * after the module is removed. */ for (i = 0; i < 10; i++) { - elem = kmalloc(sizeof(*elem), GFP_KERNEL); - pr_info("kmemleak: kmalloc(sizeof(*elem)) = %p\n", elem); + elem = kzalloc(sizeof(*elem), GFP_KERNEL); + pr_info("kmemleak: kzalloc(sizeof(*elem)) = %p\n", elem); if (!elem) return -ENOMEM; - memset(elem, 0, sizeof(*elem)); INIT_LIST_HEAD(&elem->list); - list_add_tail(&elem->list, &test_list); } diff --git a/mm/kmemleak.c b/mm/kmemleak.c index bd9bc214091..84225f3b719 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -113,7 +113,9 @@ #define BYTES_PER_POINTER sizeof(void *) /* GFP bitmask for kmemleak internal allocations */ -#define GFP_KMEMLEAK_MASK (GFP_KERNEL | GFP_ATOMIC) +#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC)) | \ + __GFP_NORETRY | __GFP_NOMEMALLOC | \ + __GFP_NOWARN) /* scanning area inside a memory block */ struct kmemleak_scan_area { @@ -511,9 +513,10 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size, struct kmemleak_object *object; struct prio_tree_node *node; - object = kmem_cache_alloc(object_cache, gfp & GFP_KMEMLEAK_MASK); + object = kmem_cache_alloc(object_cache, gfp_kmemleak_mask(gfp)); if (!object) { - kmemleak_stop("Cannot allocate a kmemleak_object structure\n"); + pr_warning("Cannot allocate a kmemleak_object structure\n"); + kmemleak_disable(); return NULL; } @@ -734,9 +737,9 @@ static void add_scan_area(unsigned long ptr, size_t size, gfp_t gfp) return; } - area = kmem_cache_alloc(scan_area_cache, gfp & GFP_KMEMLEAK_MASK); + area = kmem_cache_alloc(scan_area_cache, gfp_kmemleak_mask(gfp)); if (!area) { - kmemleak_warn("Cannot allocate a scan area\n"); + pr_warning("Cannot allocate a scan area\n"); goto out; } diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c index 10c3a871a12..b310702c646 100644 --- a/sound/atmel/ac97c.c +++ b/sound/atmel/ac97c.c @@ -33,9 +33,12 @@ #include <linux/dw_dmac.h> #include <mach/cpu.h> -#include <mach/hardware.h> #include <mach/gpio.h> +#ifdef CONFIG_ARCH_AT91 +#include <mach/hardware.h> +#endif + #include "ac97c.h" enum { diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 6117595fc07..573594bf322 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c @@ -979,31 +979,25 @@ snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec, snd_azf3328_dbgcallenter(); switch (bitrate) { -#define AZF_FMT_XLATE(in_freq, out_bits) \ - do { \ - case AZF_FREQ_ ## in_freq: \ - freq = SOUNDFORMAT_FREQ_ ## out_bits; \ - break; \ - } while (0); - AZF_FMT_XLATE(4000, SUSPECTED_4000) - AZF_FMT_XLATE(4800, SUSPECTED_4800) - /* the AZF3328 names it "5510" for some strange reason: */ - AZF_FMT_XLATE(5512, 5510) - AZF_FMT_XLATE(6620, 6620) - AZF_FMT_XLATE(8000, 8000) - AZF_FMT_XLATE(9600, 9600) - AZF_FMT_XLATE(11025, 11025) - AZF_FMT_XLATE(13240, SUSPECTED_13240) - AZF_FMT_XLATE(16000, 16000) - AZF_FMT_XLATE(22050, 22050) - AZF_FMT_XLATE(32000, 32000) + case AZF_FREQ_4000: freq = SOUNDFORMAT_FREQ_SUSPECTED_4000; break; + case AZF_FREQ_4800: freq = SOUNDFORMAT_FREQ_SUSPECTED_4800; break; + case AZF_FREQ_5512: + /* the AZF3328 names it "5510" for some strange reason */ + freq = SOUNDFORMAT_FREQ_5510; break; + case AZF_FREQ_6620: freq = SOUNDFORMAT_FREQ_6620; break; + case AZF_FREQ_8000: freq = SOUNDFORMAT_FREQ_8000; break; + case AZF_FREQ_9600: freq = SOUNDFORMAT_FREQ_9600; break; + case AZF_FREQ_11025: freq = SOUNDFORMAT_FREQ_11025; break; + case AZF_FREQ_13240: freq = SOUNDFORMAT_FREQ_SUSPECTED_13240; break; + case AZF_FREQ_16000: freq = SOUNDFORMAT_FREQ_16000; break; + case AZF_FREQ_22050: freq = SOUNDFORMAT_FREQ_22050; break; + case AZF_FREQ_32000: freq = SOUNDFORMAT_FREQ_32000; break; default: snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate); /* fall-through */ - AZF_FMT_XLATE(44100, 44100) - AZF_FMT_XLATE(48000, 48000) - AZF_FMT_XLATE(66200, SUSPECTED_66200) -#undef AZF_FMT_XLATE + case AZF_FREQ_44100: freq = SOUNDFORMAT_FREQ_44100; break; + case AZF_FREQ_48000: freq = SOUNDFORMAT_FREQ_48000; break; + case AZF_FREQ_66200: freq = SOUNDFORMAT_FREQ_SUSPECTED_66200; break; } /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */ /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */ diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4a663471dad..74b0560289c 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -381,7 +381,7 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a) snd_print_pcm_rates(a->rates, buf, sizeof(buf)); if (a->format == AUDIO_CODING_TYPE_LPCM) - snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8)); + snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8); else if (a->max_bitrate) snprintf(buf2, sizeof(buf2), ", max bitrate = %d", a->max_bitrate); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index be4df4c6fd5..2fa9ed99c32 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -14954,9 +14954,11 @@ static struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ), SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), - SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), + SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), {} diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c index 9f72d424969..252719101c4 100644 --- a/sound/pci/oxygen/xonar_cs43xx.c +++ b/sound/pci/oxygen/xonar_cs43xx.c @@ -392,7 +392,7 @@ static void dump_d1_registers(struct oxygen *chip, unsigned int i; snd_iprintf(buffer, "\nCS4398: 7?"); - for (i = 2; i <= 8; ++i) + for (i = 2; i < 8; ++i) snd_iprintf(buffer, " %02x", data->cs4398_regs[i]); snd_iprintf(buffer, "\n"); dump_cs4362a_registers(data, buffer); diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c index da2208e06b0..5e4d499d843 100644 --- a/sound/soc/atmel/snd-soc-afeb9260.c +++ b/sound/soc/atmel/snd-soc-afeb9260.c @@ -129,7 +129,7 @@ static struct snd_soc_dai_link afeb9260_dai = { .cpu_dai_name = "atmel-ssc-dai.0", .codec_dai_name = "tlv320aic23-hifi", .platform_name = "atmel_pcm-audio", - .codec_name = "tlv320aic23-codec.0-0x1a", + .codec_name = "tlv320aic23-codec.0-001a", .init = afeb9260_tlv320aic23_init, .ops = &afeb9260_ops, }; diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index e902b24c185..ad28663f5bb 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c @@ -119,7 +119,7 @@ static struct snd_soc_dai_link bf5xx_ssm2602_dai = { .cpu_dai_name = "bf5xx-i2s", .codec_dai_name = "ssm2602-hifi", .platform_name = "bf5xx-pcm-audio", - .codec_name = "ssm2602-codec.0-0x1b", + .codec_name = "ssm2602-codec.0-001b", .ops = &bf5xx_ssm2602_ops, }; diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 247a6a99feb..3351f77607b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2386,7 +2386,7 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) else val = 0; - return snd_soc_update_bits(codec, reg, mask, reg); + return snd_soc_update_bits(codec, reg, mask, val); } #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 6045cbde492..608c84c5aa8 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -1223,7 +1223,7 @@ static int wm8995_set_tristate(struct snd_soc_dai *codec_dai, int tristate) else val = 0; - return snd_soc_update_bits(codec, reg, mask, reg); + return snd_soc_update_bits(codec, reg, mask, val); } /* The size in bits of the FLL divide multiplied by 10 diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index c466982eed2..613df5db0b3 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -91,6 +91,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) static void calibrate_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); + s8 offset; u16 reg, reg_l, reg_r, dcs_cfg; /* If we're using a digital only path and have a previously @@ -149,16 +150,14 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) hubs->dcs_codes); /* HPOUT1L */ - if (reg_l + hubs->dcs_codes > 0 && - reg_l + hubs->dcs_codes < 0xff) - reg_l += hubs->dcs_codes; - dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; + offset = reg_l; + offset += hubs->dcs_codes; + dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1R */ - if (reg_r + hubs->dcs_codes > 0 && - reg_r + hubs->dcs_codes < 0xff) - reg_r += hubs->dcs_codes; - dcs_cfg |= reg_r; + offset = reg_r; + offset += hubs->dcs_codes; + dcs_cfg |= (u8)offset; dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 0c2d6bacc68..b36f0b39b09 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c @@ -223,7 +223,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = { .stream_name = "AIC3X", .cpu_dai_name= "davinci-mcasp.0", .codec_dai_name = "tlv320aic3x-hifi", - .codec_name = "tlv320aic3x-codec.0-001a", + .codec_name = "tlv320aic3x-codec.1-0018", .platform_name = "davinci-pcm-audio", .init = evm_aic3x_init, .ops = &evm_ops, diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index fc592f0d5fc..784cff5f67e 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c @@ -307,10 +307,10 @@ static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link corgi_dai = { .name = "WM8731", .stream_name = "WM8731", - .cpu_dai_name = "pxa-is2-dai", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", - .codec_name = "wm8731-codec-0.001a", + .codec_name = "wm8731-codec-0.001b", .init = corgi_wm8731_init, .ops = &corgi_ops, }; diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 6298ee115e2..a7d4999f9b2 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c @@ -276,7 +276,7 @@ static struct snd_soc_dai_link poodle_dai = { .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8731-hifi", .platform_name = "pxa-pcm-audio", - .codec_name = "wm8731-codec.0-001a", + .codec_name = "wm8731-codec.0-001b", .init = poodle_wm8731_init, .ops = &poodle_ops, }; diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index c2acb69b957..8e157135063 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c @@ -315,10 +315,10 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link spitz_dai = { .name = "wm8750", .stream_name = "WM8750", - .cpu_dai_name = "pxa-is2", + .cpu_dai_name = "pxa2xx-i2s", .codec_dai_name = "wm8750-hifi", .platform_name = "pxa-pcm-audio", - .codec_name = "wm8750-codec.0-001a", + .codec_name = "wm8750-codec.0-001b", .init = spitz_wm8750_init, .ops = &spitz_ops, }; diff --git a/sound/soc/samsung/neo1973_gta02_wm8753.c b/sound/soc/samsung/neo1973_gta02_wm8753.c index 3eec610c10f..0d0ae2b9eef 100644 --- a/sound/soc/samsung/neo1973_gta02_wm8753.c +++ b/sound/soc/samsung/neo1973_gta02_wm8753.c @@ -397,11 +397,11 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { { /* Hifi Playback - for similatious use with voice below */ .name = "WM8753", .stream_name = "WM8753 HiFi", - .cpu_dai_name = "s3c24xx-i2s", + .cpu_dai_name = "s3c24xx-iis", .codec_dai_name = "wm8753-hifi", .init = neo1973_gta02_wm8753_init, .platform_name = "samsung-audio", - .codec_name = "wm8753-codec.0-0x1a", + .codec_name = "wm8753-codec.0-001a", .ops = &neo1973_gta02_hifi_ops, }, { /* Voice via BT */ @@ -410,7 +410,7 @@ static struct snd_soc_dai_link neo1973_gta02_dai[] = { .cpu_dai_name = "bluetooth-dai", .codec_dai_name = "wm8753-voice", .ops = &neo1973_gta02_voice_ops, - .codec_name = "wm8753-codec.0-0x1a", + .codec_name = "wm8753-codec.0-001a", .platform_name = "samsung-audio", }, }; diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c index c7a24514beb..d20815d5ab2 100644 --- a/sound/soc/samsung/neo1973_wm8753.c +++ b/sound/soc/samsung/neo1973_wm8753.c @@ -559,9 +559,9 @@ static struct snd_soc_dai_link neo1973_dai[] = { .name = "WM8753", .stream_name = "WM8753 HiFi", .platform_name = "samsung-audio", - .cpu_dai_name = "s3c24xx-i2s", + .cpu_dai_name = "s3c24xx-iis", .codec_dai_name = "wm8753-hifi", - .codec_name = "wm8753-codec.0-0x1a", + .codec_name = "wm8753-codec.0-001a", .init = neo1973_wm8753_init, .ops = &neo1973_hifi_ops, }, @@ -571,7 +571,7 @@ static struct snd_soc_dai_link neo1973_dai[] = { .platform_name = "samsung-audio", .cpu_dai_name = "bluetooth-dai", .codec_dai_name = "wm8753-voice", - .codec_name = "wm8753-codec.0-0x1a", + .codec_name = "wm8753-codec.0-001a", .ops = &neo1973_voice_ops, }, }; diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c index bb4292e3596..08fcaaa6690 100644 --- a/sound/soc/samsung/s3c24xx_simtec_hermes.c +++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c @@ -94,8 +94,8 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link simtec_dai_aic33 = { .name = "tlv320aic33", .stream_name = "TLV320AIC33", - .codec_name = "tlv320aic3x-codec.0-0x1a", - .cpu_dai_name = "s3c24xx-i2s", + .codec_name = "tlv320aic3x-codec.0-001a", + .cpu_dai_name = "s3c24xx-iis", .codec_dai_name = "tlv320aic3x-hifi", .platform_name = "samsung-audio", .init = simtec_hermes_init, diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c index fbba4e36772..116e3e67016 100644 --- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c +++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c @@ -85,8 +85,8 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd) static struct snd_soc_dai_link simtec_dai_aic23 = { .name = "tlv320aic23", .stream_name = "TLV320AIC23", - .codec_name = "tlv320aic3x-codec.0-0x1a", - .cpu_dai_name = "s3c24xx-i2s", + .codec_name = "tlv320aic3x-codec.0-001a", + .cpu_dai_name = "s3c24xx-iis", .codec_dai_name = "tlv320aic3x-hifi", .platform_name = "samsung-audio", .init = simtec_tlv320aic23_init, diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c index cdc8ecbcb8e..2c09e93dd56 100644 --- a/sound/soc/samsung/s3c24xx_uda134x.c +++ b/sound/soc/samsung/s3c24xx_uda134x.c @@ -228,7 +228,7 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { .stream_name = "UDA134X", .codec_name = "uda134x-hifi", .codec_dai_name = "uda134x-hifi", - .cpu_dai_name = "s3c24xx-i2s", + .cpu_dai_name = "s3c24xx-iis", .ops = &s3c24xx_uda134x_ops, .platform_name = "samsung-audio", }; |