diff --git a/Makefile b/Makefile index 1932984..026a227 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 3 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c index a83cf51..cccf91b 100644 --- a/arch/arm/mach-shmobile/setup-sh7372.c +++ b/arch/arm/mach-shmobile/setup-sh7372.c @@ -1043,6 +1043,8 @@ void __init sh7372_add_standard_devices(void) sh7372_add_device_to_domain(&sh7372_a4r, &veu2_device); sh7372_add_device_to_domain(&sh7372_a4r, &veu3_device); sh7372_add_device_to_domain(&sh7372_a4r, &jpu_device); + sh7372_add_device_to_domain(&sh7372_a4r, &tmu00_device); + sh7372_add_device_to_domain(&sh7372_a4r, &tmu01_device); } void __init sh7372_add_early_devices(void) diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 373652d..46b6839 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -10,6 +10,13 @@ config ARCH_TEGRA_2x_SOC select USB_ARCH_HAS_EHCI if USB_SUPPORT select USB_ULPI if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT + select ARM_ERRATA_720789 + select ARM_ERRATA_742230 + select ARM_ERRATA_751472 + select ARM_ERRATA_754327 + select ARM_ERRATA_764369 + select PL310_ERRATA_727915 if CACHE_L2X0 + select PL310_ERRATA_769419 if CACHE_L2X0 help Support for NVIDIA Tegra AP20 and T20 processors, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller @@ -23,6 +30,11 @@ config ARCH_TEGRA_3x_SOC select USB_ULPI if USB_SUPPORT select USB_ULPI_VIEWPORT if USB_SUPPORT select USE_OF + select ARM_ERRATA_743622 + select ARM_ERRATA_751472 + select ARM_ERRATA_754322 + select ARM_ERRATA_764369 + select PL310_ERRATA_769419 if CACHE_L2X0 help Support for NVIDIA Tegra T30 processor family, based on the ARM CortexA9MP CPU and the ARM PL310 L2 cache controller diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c index 7a95e0b..7cd3456 100644 --- a/arch/arm/mach-tegra/board-dt-tegra20.c +++ b/arch/arm/mach-tegra/board-dt-tegra20.c @@ -68,11 +68,11 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra-i2s.1", NULL), OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra-das", NULL), OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0", - &tegra_ehci1_device.dev.platform_data), + &tegra_ehci1_pdata), OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1", - &tegra_ehci2_device.dev.platform_data), + &tegra_ehci2_pdata), OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2", - &tegra_ehci3_device.dev.platform_data), + &tegra_ehci3_pdata), {} }; diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 7a2a02d..5f6b867 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -446,18 +445,18 @@ static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { .clk = "cdev2", }; -static struct tegra_ehci_platform_data tegra_ehci1_pdata = { +struct tegra_ehci_platform_data tegra_ehci1_pdata = { .operating_mode = TEGRA_USB_OTG, .power_down_on_bus_suspend = 1, }; -static struct tegra_ehci_platform_data tegra_ehci2_pdata = { +struct tegra_ehci_platform_data tegra_ehci2_pdata = { .phy_config = &tegra_ehci2_ulpi_phy_config, .operating_mode = TEGRA_USB_HOST, .power_down_on_bus_suspend = 1, }; -static struct tegra_ehci_platform_data tegra_ehci3_pdata = { +struct tegra_ehci_platform_data tegra_ehci3_pdata = { .operating_mode = TEGRA_USB_HOST, .power_down_on_bus_suspend = 1, }; diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 873ecb2..ec45567 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -20,6 +20,11 @@ #define __MACH_TEGRA_DEVICES_H #include +#include + +extern struct tegra_ehci_platform_data tegra_ehci1_pdata; +extern struct tegra_ehci_platform_data tegra_ehci2_pdata; +extern struct tegra_ehci_platform_data tegra_ehci3_pdata; extern struct platform_device tegra_gpio_device; extern struct platform_device tegra_pinmux_device; diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index fb07275..6d10a66 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -3967,18 +3967,36 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi) static __init int bad_ioapic(unsigned long address) { if (nr_ioapics >= MAX_IO_APICS) { - printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded " - "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics); + pr_warn("WARNING: Max # of I/O APICs (%d) exceeded (found %d), skipping\n", + MAX_IO_APICS, nr_ioapics); return 1; } if (!address) { - printk(KERN_WARNING "WARNING: Bogus (zero) I/O APIC address" - " found in table, skipping!\n"); + pr_warn("WARNING: Bogus (zero) I/O APIC address found in table, skipping!\n"); return 1; } return 0; } +static __init int bad_ioapic_register(int idx) +{ + union IO_APIC_reg_00 reg_00; + union IO_APIC_reg_01 reg_01; + union IO_APIC_reg_02 reg_02; + + reg_00.raw = io_apic_read(idx, 0); + reg_01.raw = io_apic_read(idx, 1); + reg_02.raw = io_apic_read(idx, 2); + + if (reg_00.raw == -1 && reg_01.raw == -1 && reg_02.raw == -1) { + pr_warn("I/O APIC 0x%x registers return all ones, skipping!\n", + mpc_ioapic_addr(idx)); + return 1; + } + + return 0; +} + void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) { int idx = 0; @@ -3995,6 +4013,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) ioapics[idx].mp_config.apicaddr = address; set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address); + + if (bad_ioapic_register(idx)) { + clear_fixmap(FIX_IO_APIC_BASE_0 + idx); + return; + } + ioapics[idx].mp_config.apicid = io_apic_unique_id(id); ioapics[idx].mp_config.apicver = io_apic_get_version(idx); @@ -4015,10 +4039,10 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base) if (gsi_cfg->gsi_end >= gsi_top) gsi_top = gsi_cfg->gsi_end + 1; - printk(KERN_INFO "IOAPIC[%d]: apic_id %d, version %d, address 0x%x, " - "GSI %d-%d\n", idx, mpc_ioapic_id(idx), - mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), - gsi_cfg->gsi_base, gsi_cfg->gsi_end); + pr_info("IOAPIC[%d]: apic_id %d, version %d, address 0x%x, GSI %d-%d\n", + idx, mpc_ioapic_id(idx), + mpc_ioapic_ver(idx), mpc_ioapic_addr(idx), + gsi_cfg->gsi_base, gsi_cfg->gsi_end); nr_ioapics++; } diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 79d97e6..7b784f4 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -98,12 +98,6 @@ #endif .endm -#ifdef CONFIG_VM86 -#define resume_userspace_sig check_userspace -#else -#define resume_userspace_sig resume_userspace -#endif - /* * User gs save/restore * @@ -327,10 +321,19 @@ ret_from_exception: preempt_stop(CLBR_ANY) ret_from_intr: GET_THREAD_INFO(%ebp) -check_userspace: +resume_userspace_sig: +#ifdef CONFIG_VM86 movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS movb PT_CS(%esp), %al andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax +#else + /* + * We can be coming here from a syscall done in the kernel space, + * e.g. a failed kernel_execve(). + */ + movl PT_CS(%esp), %eax + andl $SEGMENT_RPL_MASK, %eax +#endif cmpl $USER_RPL, %eax jb resume_kernel # not returning to v8086 or userspace diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index 6bb7b85..bcfec2d 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -163,7 +163,7 @@ int regset_tls_get(struct task_struct *target, const struct user_regset *regset, { const struct desc_struct *tls; - if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || + if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || (pos % sizeof(struct user_desc)) != 0 || (count % sizeof(struct user_desc)) != 0) return -EINVAL; @@ -198,7 +198,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset, struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES]; const struct user_desc *info; - if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || + if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) || (pos % sizeof(struct user_desc)) != 0 || (count % sizeof(struct user_desc)) != 0) return -EINVAL; diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index a62c201..6fcfcb3 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -932,6 +932,16 @@ static int __init init_tsc_clocksource(void) clocksource_tsc.rating = 0; clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; } + + /* + * Trust the results of the earlier calibration on systems + * exporting a reliable TSC. + */ + if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) { + clocksource_register_khz(&clocksource_tsc, tsc_khz); + return 0; + } + schedule_delayed_work(&tsc_irqwork, 0); return 0; } diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index b466cab..328cb37 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c @@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) spinlock_t *ptl; int i; + down_write(&mm->mmap_sem); pgd = pgd_offset(mm, 0xA0000); if (pgd_none_or_clear_bad(pgd)) goto out; @@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm) } pte_unmap_unlock(pte, ptl); out: + up_write(&mm->mmap_sem); flush_tlb(); } diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 7c1b765..5671752 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -475,8 +475,10 @@ void bpf_jit_compile(struct sk_filter *fp) case BPF_S_LD_W_ABS: func = sk_load_word; common_load: seen |= SEEN_DATAREF; - if ((int)K < 0) + if ((int)K < 0) { + /* Abort the JIT because __load_pointer() is needed. */ goto out; + } t_offset = func - (image + addrs[i]); EMIT1_off32(0xbe, K); /* mov imm32,%esi */ EMIT1_off32(0xe8, t_offset); /* call */ @@ -489,14 +491,8 @@ common_load: seen |= SEEN_DATAREF; goto common_load; case BPF_S_LDX_B_MSH: if ((int)K < 0) { - if (pc_ret0 > 0) { - /* addrs[pc_ret0 - 1] is the start address */ - EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]); - break; - } - CLEAR_A(); - EMIT_JMP(cleanup_addr - addrs[i]); - break; + /* Abort the JIT because __load_pointer() is needed. */ + goto out; } seen |= SEEN_DATAREF | SEEN_XREG; t_offset = sk_load_byte_msh - (image + addrs[i]); diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index ce98e28..e7e67cc 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl @@ -288,7 +288,7 @@ 279 i386 mq_timedsend sys_mq_timedsend compat_sys_mq_timedsend 280 i386 mq_timedreceive sys_mq_timedreceive compat_sys_mq_timedreceive 281 i386 mq_notify sys_mq_notify compat_sys_mq_notify -282 i386 mq_getsetaddr sys_mq_getsetattr compat_sys_mq_getsetattr +282 i386 mq_getsetattr sys_mq_getsetattr compat_sys_mq_getsetattr 283 i386 kexec_load sys_kexec_load compat_sys_kexec_load 284 i386 waitid sys_waitid compat_sys_waitid # 285 sys_setaltroot diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index d07bf03..ddeb845 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -103,8 +103,6 @@ static struct ata_port_operations ahci_p5wdh_ops = { .hardreset = ahci_p5wdh_hardreset, }; -#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) - static const struct ata_port_info ahci_port_info[] = { /* by features */ [board_ahci] = diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index b175000..c2594dd 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -195,6 +195,9 @@ enum { PORT_FBS_EN = (1 << 0), /* Enable FBS */ /* hpriv->flags bits */ + +#define AHCI_HFLAGS(flags) .private_data = (void *)(flags) + AHCI_HFLAG_NO_NCQ = (1 << 0), AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */ AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */ @@ -210,6 +213,9 @@ enum { AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */ AHCI_HFLAG_NO_FPDMA_AA = (1 << 13), /* no FPDMA AA */ AHCI_HFLAG_YES_FBS = (1 << 14), /* force FBS cap on */ + AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on + port start (wait until + error-handling stage) */ /* ap->flags bits */ diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c index 48be4e1..0c86c77 100644 --- a/drivers/ata/ahci_platform.c +++ b/drivers/ata/ahci_platform.c @@ -26,6 +26,7 @@ enum ahci_type { AHCI, /* standard platform ahci */ IMX53_AHCI, /* ahci on i.mx53 */ + STRICT_AHCI, /* delayed DMA engine start */ }; static struct platform_device_id ahci_devtype[] = { @@ -36,6 +37,9 @@ static struct platform_device_id ahci_devtype[] = { .name = "imx53-ahci", .driver_data = IMX53_AHCI, }, { + .name = "strict-ahci", + .driver_data = STRICT_AHCI, + }, { /* sentinel */ } }; @@ -56,6 +60,13 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = ATA_UDMA6, .port_ops = &ahci_pmp_retry_srst_ops, }, + [STRICT_AHCI] = { + AHCI_HFLAGS (AHCI_HFLAG_DELAY_ENGINE), + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &ahci_ops, + }, }; static struct scsi_host_template ahci_platform_sht = { diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index a72bfd0..f9eaa82 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -737,6 +737,7 @@ static void ahci_power_down(struct ata_port *ap) static void ahci_start_port(struct ata_port *ap) { + struct ahci_host_priv *hpriv = ap->host->private_data; struct ahci_port_priv *pp = ap->private_data; struct ata_link *link; struct ahci_em_priv *emp; @@ -746,6 +747,10 @@ static void ahci_start_port(struct ata_port *ap) /* enable FIS reception */ ahci_start_fis_rx(ap); + /* enable DMA */ + if (!(hpriv->flags & AHCI_HFLAG_DELAY_ENGINE)) + ahci_start_engine(ap); + /* turn on LEDs */ if (ap->flags & ATA_FLAG_EM) { ata_for_each_link(link, ap, EDGE) { diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 35aca7d..4fe9d21 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -401,8 +401,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev) ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000); active = clamp_val(t.active, 2, 15); - recover = clamp_val(t.recover, 2, 16); - recover &= 0x15; + recover = clamp_val(t.recover, 2, 16) & 0x0F; inb(0x3E6); inb(0x3E6); diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 978bbf7..58c8b4d 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -366,7 +366,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd) not_suspended = 0; list_for_each_entry(pdd, &genpd->dev_list, list_node) if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev) - || pdd->dev->power.irq_safe)) + || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on)) not_suspended++; if (not_suspended > genpd->in_progress) @@ -503,6 +503,9 @@ static int pm_genpd_runtime_suspend(struct device *dev) might_sleep_if(!genpd->dev_irq_safe); + if (dev_gpd_data(dev)->always_on) + return -EBUSY; + stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; if (stop_ok && !stop_ok(dev)) return -EBUSY; @@ -764,8 +767,10 @@ static int pm_genpd_prepare(struct device *dev) genpd_acquire_lock(genpd); - if (genpd->prepared_count++ == 0) + if (genpd->prepared_count++ == 0) { + genpd->suspended_count = 0; genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF; + } genpd_release_lock(genpd); @@ -845,7 +850,8 @@ static int pm_genpd_suspend_noirq(struct device *dev) if (ret) return ret; - if (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)) + if (dev_gpd_data(dev)->always_on + || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))) return 0; genpd_stop_dev(genpd, dev); @@ -880,7 +886,8 @@ static int pm_genpd_resume_noirq(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; - if (genpd->suspend_power_off) + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on + || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev))) return 0; /* @@ -957,7 +964,7 @@ static int pm_genpd_freeze_noirq(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; - if (genpd->suspend_power_off) + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on) return 0; ret = genpd_freeze_late(genpd, dev); @@ -988,7 +995,7 @@ static int pm_genpd_thaw_noirq(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; - if (genpd->suspend_power_off) + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on) return 0; genpd_start_dev(genpd, dev); @@ -1040,20 +1047,31 @@ static int pm_genpd_restore_noirq(struct device *dev) * Since all of the "noirq" callbacks are executed sequentially, it is * guaranteed that this function will never run twice in parallel for * the same PM domain, so it is not necessary to use locking here. + * + * At this point suspended_count == 0 means we are being run for the + * first time for the given domain in the present cycle. */ - genpd->status = GPD_STATE_POWER_OFF; - if (genpd->suspend_power_off) { + if (genpd->suspended_count++ == 0) { /* - * The boot kernel might put the domain into the power on state, - * so make sure it really is powered off. + * The boot kernel might put the domain into arbitrary state, + * so make it appear as powered off to pm_genpd_poweron(), so + * that it tries to power it on in case it was really off. */ - if (genpd->power_off) - genpd->power_off(genpd); - return 0; + genpd->status = GPD_STATE_POWER_OFF; + if (genpd->suspend_power_off) { + /* + * If the domain was off before the hibernation, make + * sure it will be off going forward. + */ + if (genpd->power_off) + genpd->power_off(genpd); + } } + if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on) + return 0; + pm_genpd_poweron(genpd); - genpd->suspended_count--; genpd_start_dev(genpd, dev); return genpd_resume_early(genpd, dev); @@ -1216,6 +1234,26 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, } /** + * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device. + * @dev: Device to set/unset the flag for. + * @val: The new value of the device's "always on" flag. + */ +void pm_genpd_dev_always_on(struct device *dev, bool val) +{ + struct pm_subsys_data *psd; + unsigned long flags; + + spin_lock_irqsave(&dev->power.lock, flags); + + psd = dev_to_psd(dev); + if (psd && psd->domain_data) + to_gpd_data(psd->domain_data)->always_on = val; + + spin_unlock_irqrestore(&dev->power.lock, flags); +} +EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on); + +/** * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. * @genpd: Master PM domain to add the subdomain to. * @subdomain: Subdomain to be added. @@ -1557,7 +1595,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd, genpd->poweroff_task = NULL; genpd->resume_count = 0; genpd->device_count = 0; - genpd->suspended_count = 0; genpd->max_off_time_ns = -1; genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend; genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume; diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 07f14d1..4eca6e5 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -65,6 +65,7 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x0CF3, 0x3002) }, { USB_DEVICE(0x13d3, 0x3304) }, { USB_DEVICE(0x0930, 0x0215) }, + { USB_DEVICE(0x0489, 0xE03D) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 789c9b5..1f91da3 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -121,6 +121,7 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 7fc75e4..a048199 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -5,7 +5,6 @@ menuconfig TCG_TPM tristate "TPM Hardware Support" depends on HAS_IOMEM - depends on EXPERIMENTAL select SECURITYFS ---help--- If you have a TPM security chip in your system, which diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 32362cf..ad7c732 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1221,12 +1221,13 @@ ssize_t tpm_read(struct file *file, char __user *buf, ret_size = atomic_read(&chip->data_pending); atomic_set(&chip->data_pending, 0); if (ret_size > 0) { /* relay data */ + ssize_t orig_ret_size = ret_size; if (size < ret_size) ret_size = size; mutex_lock(&chip->buffer_mutex); rc = copy_to_user(buf, chip->data_buffer, ret_size); - memset(chip->data_buffer, 0, ret_size); + memset(chip->data_buffer, 0, orig_ret_size); if (rc) ret_size = -EFAULT; diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index ca09bc4..32fe9ef 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -32,6 +32,7 @@ #include #include #include +#include struct sh_cmt_priv { void __iomem *mapbase; @@ -689,6 +690,9 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev) struct sh_cmt_priv *p = platform_get_drvdata(pdev); int ret; + if (!is_early_platform_device(pdev)) + pm_genpd_dev_always_on(&pdev->dev, true); + if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index db8d595..a2172f6 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c @@ -31,6 +31,7 @@ #include #include #include +#include struct sh_mtu2_priv { void __iomem *mapbase; @@ -306,6 +307,9 @@ static int __devinit sh_mtu2_probe(struct platform_device *pdev) struct sh_mtu2_priv *p = platform_get_drvdata(pdev); int ret; + if (!is_early_platform_device(pdev)) + pm_genpd_dev_always_on(&pdev->dev, true); + if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index 079e96a..97f54b6 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c @@ -32,6 +32,7 @@ #include #include #include +#include struct sh_tmu_priv { void __iomem *mapbase; @@ -410,6 +411,9 @@ static int __devinit sh_tmu_probe(struct platform_device *pdev) struct sh_tmu_priv *p = platform_get_drvdata(pdev); int ret; + if (!is_early_platform_device(pdev)) + pm_genpd_dev_always_on(&pdev->dev, true); + if (p) { dev_info(&pdev->dev, "kept as earlytimer\n"); return 0; diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7f5f0da..0a0225a 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2748,7 +2748,7 @@ static int handle_ir_buffer_fill(struct context *context, container_of(context, struct iso_context, context); u32 buffer_dma; - if (!last->transfer_status) + if (last->res_count != 0) /* Descriptor(s) not done yet, stop iteration */ return 0; @@ -2762,8 +2762,7 @@ static int handle_ir_buffer_fill(struct context *context, if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) ctx->base.callback.mc(&ctx->base, le32_to_cpu(last->data_address) + - le16_to_cpu(last->req_count) - - le16_to_cpu(last->res_count), + le16_to_cpu(last->req_count), ctx->base.callback_data); return 1; diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index df0d595..3d00016 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -313,10 +313,16 @@ static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) return -ENODEV; } -static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger) +static int gpio_irq_type_unbanked(struct irq_data *data, unsigned trigger) { - struct davinci_gpio_regs __iomem *g = irq2regs(d->irq); - u32 mask = (u32) irq_data_get_irq_handler_data(d); + struct davinci_gpio_controller *d; + struct davinci_gpio_regs __iomem *g; + struct davinci_soc_info *soc_info = &davinci_soc_info; + u32 mask; + + d = (struct davinci_gpio_controller *)data->handler_data; + g = (struct davinci_gpio_regs __iomem *)d->regs; + mask = __gpio_mask(data->irq - soc_info->gpio_irq); if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) return -EINVAL; @@ -380,7 +386,7 @@ static int __init davinci_gpio_irq_setup(void) * IRQ mux conflicts; gpio_irq_type_unbanked() is only for GPIOs. */ if (soc_info->gpio_unbanked) { - static struct irq_chip gpio_irqchip_unbanked; + static struct irq_chip_type gpio_unbanked; /* pass "bank 0" GPIO IRQs to AINTC */ chips[0].chip.to_irq = gpio_to_irq_unbanked; @@ -388,9 +394,10 @@ static int __init davinci_gpio_irq_setup(void) /* AINTC handles mask/unmask; GPIO handles triggering */ irq = bank_irq; - gpio_irqchip_unbanked = *irq_get_chip(irq); - gpio_irqchip_unbanked.name = "GPIO-AINTC"; - gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked; + gpio_unbanked = *container_of(irq_get_chip(irq), + struct irq_chip_type, chip); + gpio_unbanked.chip.name = "GPIO-AINTC"; + gpio_unbanked.chip.irq_set_type = gpio_irq_type_unbanked; /* default trigger: both edges */ g = gpio2regs(0); @@ -399,9 +406,8 @@ static int __init davinci_gpio_irq_setup(void) /* set the direct IRQs up to use that irqchip */ for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) { - irq_set_chip(irq, &gpio_irqchip_unbanked); - irq_set_handler_data(irq, (void *)__gpio_mask(gpio)); - irq_set_chip_data(irq, (__force void *)g); + irq_set_chip(irq, &gpio_unbanked.chip); + irq_set_handler_data(irq, &chips[gpio / 32]); irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH); } diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 0b05629..a6c10e8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -508,7 +508,10 @@ static void _disable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) static inline void _set_gpio_irqenable(struct gpio_bank *bank, int gpio, int enable) { - _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); + if (enable) + _enable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); + else + _disable_gpio_irqbank(bank, GPIO_BIT(bank, gpio)); } /* diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index be61673..5154493 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -158,7 +158,7 @@ static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - address = (unsigned long)vmf->virtual_address; + address = (unsigned long)vmf->virtual_address - (vmf->pgoff << PAGE_SHIFT); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 308f819..c1043e5 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -442,6 +442,10 @@ static int i915_drm_freeze(struct drm_device *dev) /* Modeset on resume, not lid events */ dev_priv->modeset_on_lid = 0; + console_lock(); + intel_fbdev_set_suspend(dev, 1); + console_unlock(); + return 0; } @@ -514,6 +518,9 @@ static int i915_drm_thaw(struct drm_device *dev) dev_priv->modeset_on_lid = 0; + console_lock(); + intel_fbdev_set_suspend(dev, 0); + console_unlock(); return error; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e55badb..60a84aa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3084,10 +3084,13 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj) return ret; } + ret = i915_gem_object_wait_rendering(obj); + if (ret) + return ret; + /* Ensure that we invalidate the GPU's caches and TLBs. */ obj->base.read_domains &= ~I915_GEM_GPU_DOMAINS; - - return i915_gem_object_wait_rendering(obj); + return 0; } /** diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 1348705..e85f976 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -381,7 +381,7 @@ extern int intel_framebuffer_init(struct drm_device *dev, struct drm_i915_gem_object *obj); extern int intel_fbdev_init(struct drm_device *dev); extern void intel_fbdev_fini(struct drm_device *dev); - +extern void intel_fbdev_set_suspend(struct drm_device *dev, int state); extern void intel_prepare_page_flip(struct drm_device *dev, int plane); extern void intel_finish_page_flip(struct drm_device *dev, int pipe); extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 571375a..12a04b9 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -258,6 +258,16 @@ void intel_fbdev_fini(struct drm_device *dev) kfree(dev_priv->fbdev); dev_priv->fbdev = NULL; } + +void intel_fbdev_set_suspend(struct drm_device *dev, int state) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + if (!dev_priv->fbdev) + return; + + fb_set_suspend(dev_priv->fbdev->helper.fbdev, state); +} + MODULE_LICENSE("GPL and additional rights"); void intel_fb_output_poll_changed(struct drm_device *dev) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 742f17f..24ed306 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -550,8 +550,8 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, if (encoder->crtc == crtc) { radeon_encoder = to_radeon_encoder(encoder); connector = radeon_get_connector_for_encoder(encoder); - if (connector && connector->display_info.bpc) - bpc = connector->display_info.bpc; + /* if (connector && connector->display_info.bpc) + bpc = connector->display_info.bpc; */ encoder_mode = atombios_get_encoder_mode(encoder); is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); if ((radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT | ATOM_DEVICE_DFP_SUPPORT)) || @@ -922,7 +922,9 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; int dp_clock; - bpc = connector->display_info.bpc; + + /* if (connector->display_info.bpc) + bpc = connector->display_info.bpc; */ switch (encoder_mode) { case ATOM_ENCODER_MODE_DP_MST: diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 552b436..0d9abca 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -405,10 +405,13 @@ static void dp_get_adjust_train(u8 link_status[DP_LINK_STATUS_SIZE], /* get bpc from the EDID */ static int convert_bpc_to_bpp(int bpc) { +#if 0 if (bpc == 0) return 24; else return bpc * 3; +#endif + return 24; } /* get the max pix clock supported by the link rate and lane num */ diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index b88c460..8ed806a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -537,7 +537,7 @@ atombios_dig_encoder_setup(struct drm_encoder *encoder, int action, int panel_mo dp_clock = dig_connector->dp_clock; dp_lane_count = dig_connector->dp_lane_count; hpd_id = radeon_connector->hpd.hpd; - bpc = connector->display_info.bpc; + /* bpc = connector->display_info.bpc; */ } /* no dig encoder assigned */ @@ -1098,7 +1098,7 @@ atombios_external_encoder_setup(struct drm_encoder *encoder, dp_lane_count = dig_connector->dp_lane_count; connector_object_id = (radeon_connector->connector_object_id & OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; - bpc = connector->display_info.bpc; + /* bpc = connector->display_info.bpc; */ } memset(&args, 0, sizeof(args)); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 1f53ae7..7354137 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -442,6 +442,20 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, struct radeon_device *rdev = dev->dev_private; *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); } + + /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ + if ((dev->pdev->device == 0x9802) && + (dev->pdev->subsystem_vendor == 0x1734) && + (dev->pdev->subsystem_device == 0x11bd)) { + if (*connector_type == DRM_MODE_CONNECTOR_VGA) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + *line_mux = 0x3103; + } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) { + *connector_type = DRM_MODE_CONNECTOR_DVII; + } + } + + return true; } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 8c9a811..d2e6144 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -946,6 +946,10 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) encoder = obj_to_encoder(obj); + if (encoder->encoder_type != DRM_MODE_ENCODER_DAC || + encoder->encoder_type != DRM_MODE_ENCODER_TVDAC) + continue; + encoder_funcs = encoder->helper_private; if (encoder_funcs->detect) { if (ret != connector_status_connected) { diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index fde25c0..986d608 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, uint32_t height) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct radeon_device *rdev = crtc->dev->dev_private; struct drm_gem_object *obj; + struct radeon_bo *robj; uint64_t gpu_addr; int ret; @@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, return -ENOENT; } - ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); + robj = gem_to_radeon_bo(obj); + ret = radeon_bo_reserve(robj, false); + if (unlikely(ret != 0)) + goto fail; + /* Only 27 bit offset for legacy cursor */ + ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM, + ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, + &gpu_addr); + radeon_bo_unreserve(robj); if (ret) goto fail; @@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc, radeon_crtc->cursor_height = height; radeon_lock_cursor(crtc, true); - /* XXX only 27 bit offset for legacy cursor */ radeon_set_cursor(crtc, obj, gpu_addr); radeon_show_cursor(crtc); radeon_lock_cursor(crtc, false); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index d45df17..fd2dc0e 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -224,7 +224,8 @@ void radeon_bo_unref(struct radeon_bo **bo) *bo = NULL; } -int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) +int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset, + u64 *gpu_addr) { int r, i; @@ -232,6 +233,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) bo->pin_count++; if (gpu_addr) *gpu_addr = radeon_bo_gpu_offset(bo); + WARN_ON_ONCE(max_offset != 0); return 0; } radeon_ttm_placement_from_domain(bo, domain); @@ -239,6 +241,15 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) /* force to pin into visible video ram */ bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT; } + if (max_offset) { + u64 lpfn = max_offset >> PAGE_SHIFT; + + if (!bo->placement.lpfn) + bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT; + + if (lpfn < bo->placement.lpfn) + bo->placement.lpfn = lpfn; + } for (i = 0; i < bo->placement.num_placement; i++) bo->placements[i] |= TTM_PL_FLAG_NO_EVICT; r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false); @@ -252,6 +263,11 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) return r; } +int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr) +{ + return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr); +} + int radeon_bo_unpin(struct radeon_bo *bo) { int r, i; diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index cde4303..f9104be 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -118,6 +118,8 @@ extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); extern void radeon_bo_kunmap(struct radeon_bo *bo); extern void radeon_bo_unref(struct radeon_bo **bo); extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr); +extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, + u64 max_offset, u64 *gpu_addr); extern int radeon_bo_unpin(struct radeon_bo *bo); extern int radeon_bo_evict_vram(struct radeon_device *rdev); extern void radeon_bo_force_delete(struct radeon_device *rdev); diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index 8965ad9..b99af34 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c @@ -45,6 +45,12 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, case 0xff09: ch_map_key_clear(BTN_9); break; case 0xff0a: ch_map_key_clear(BTN_A); break; case 0xff0b: ch_map_key_clear(BTN_B); break; + case 0x00f1: ch_map_key_clear(KEY_WLAN); break; + case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN); break; + case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP); break; + case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break; + case 0x00f7: ch_map_key_clear(KEY_CAMERA); break; + case 0x00f8: ch_map_key_clear(KEY_PROG1); break; default: return 0; } @@ -53,6 +59,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ch_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, { } }; MODULE_DEVICE_TABLE(hid, ch_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index af08ce7..75dbe34 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1396,6 +1396,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 63552e3..c7d0aa6 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -193,6 +193,7 @@ #define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 +#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 #define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 523f8fb..930370d 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -60,7 +60,7 @@ static ssize_t show_power(struct device *dev, pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), REG_TDP_RUNNING_AVERAGE, &val); running_avg_capture = (val >> 4) & 0x3fffff; - running_avg_capture = sign_extend32(running_avg_capture, 22); + running_avg_capture = sign_extend32(running_avg_capture, 21); running_avg_range = val & 0xf; pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 9a43cb0..db43b31 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -364,6 +364,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, } ib_conn = ep->dd_data; + if (iser_alloc_rx_descriptors(ib_conn)) + return -ENOMEM; + /* binds the iSER connection retrieved from the previously * connected ep_handle to the iSCSI layer connection. exchanges * connection pointers */ @@ -398,19 +401,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) iser_conn->ib_conn = NULL; } -static int -iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - int err; - - err = iser_conn_set_full_featured_mode(conn); - if (err) - return err; - - return iscsi_conn_start(cls_conn); -} - static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) { struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); @@ -724,7 +714,7 @@ static struct iscsi_transport iscsi_iser_transport = { .get_conn_param = iscsi_conn_get_param, .get_ep_param = iscsi_iser_get_ep_param, .get_session_param = iscsi_session_get_param, - .start_conn = iscsi_iser_conn_start, + .start_conn = iscsi_conn_start, .stop_conn = iscsi_iser_conn_stop, /* iscsi host params */ .get_host_param = iscsi_host_get_param, diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index db7ea37..296be43 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -366,4 +366,5 @@ int iser_dma_map_task_data(struct iscsi_iser_task *iser_task, void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task); int iser_initialize_task_headers(struct iscsi_task *task, struct iser_tx_desc *tx_desc); +int iser_alloc_rx_descriptors(struct iser_conn *ib_conn); #endif diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c index a607542..738a149 100644 --- a/drivers/infiniband/ulp/iser/iser_initiator.c +++ b/drivers/infiniband/ulp/iser/iser_initiator.c @@ -170,7 +170,7 @@ static void iser_create_send_desc(struct iser_conn *ib_conn, } -static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn) +int iser_alloc_rx_descriptors(struct iser_conn *ib_conn) { int i, j; u64 dma_addr; @@ -242,23 +242,24 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn) kfree(ib_conn->rx_descs); } -/** - * iser_conn_set_full_featured_mode - (iSER API) - */ -int iser_conn_set_full_featured_mode(struct iscsi_conn *conn) +static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req) { struct iscsi_iser_conn *iser_conn = conn->dd_data; - iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX); - - /* Check that there is no posted recv or send buffers left - */ - /* they must be consumed during the login phase */ - BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0); - BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); + iser_dbg("req op %x flags %x\n", req->opcode, req->flags); + /* check if this is the last login - going to full feature phase */ + if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE) + return 0; - if (iser_alloc_rx_descriptors(iser_conn->ib_conn)) - return -ENOMEM; + /* + * Check that there is one posted recv buffer (for the last login + * response) and no posted send buffers left - they must have been + * consumed during previous login phases. + */ + WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1); + WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0); + iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX); /* Initial post receive buffers */ if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX)) return -ENOMEM; @@ -438,6 +439,9 @@ int iser_send_control(struct iscsi_conn *conn, err = iser_post_recvl(iser_conn->ib_conn); if (err) goto send_control_error; + err = iser_post_rx_bufs(conn, task->hdr); + if (err) + goto send_control_error; } err = iser_post_send(iser_conn->ib_conn, mdesc); diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 2b73d43..3c5c550 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1750,6 +1750,7 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, srp_cmd->tag); cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION; cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; } @@ -1757,15 +1758,19 @@ static int srpt_handle_cmd(struct srpt_rdma_ch *ch, cmd->data_direction = dir; unpacked_lun = srpt_unpack_lun((uint8_t *)&srp_cmd->lun, sizeof(srp_cmd->lun)); - if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) + if (transport_lookup_cmd_lun(cmd, unpacked_lun) < 0) { + kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); goto send_sense; + } ret = transport_generic_allocate_tasks(cmd, srp_cmd->cdb); - if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) - srpt_queue_status(cmd); - else if (cmd->se_cmd_flags & SCF_SCSI_CDB_EXCEPTION) - goto send_sense; - else - WARN_ON_ONCE(ret); + if (ret < 0) { + kref_put(&send_ioctx->kref, srpt_put_send_ioctx_kref); + if (cmd->se_cmd_flags & SCF_SCSI_RESERVATION_CONFLICT) { + srpt_queue_status(cmd); + return 0; + } else + goto send_sense; + } transport_handle_cdb_direct(cmd); return 0; diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index f75e060..ae2ec92 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2804,7 +2804,7 @@ static int amd_iommu_dma_supported(struct device *dev, u64 mask) * we don't need to preallocate the protection domains anymore. * For now we have to. */ -static void prealloc_protection_domains(void) +static void __init prealloc_protection_domains(void) { struct iommu_dev_data *dev_data; struct dma_ops_domain *dma_dom; diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index a35e98a..c94a165 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1131,8 +1131,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu) { int r; - if (pci_enable_msi(iommu->dev)) - return 1; + r = pci_enable_msi(iommu->dev); + if (r) + return r; r = request_threaded_irq(iommu->dev->irq, amd_iommu_int_handler, @@ -1142,27 +1143,36 @@ static int iommu_setup_msi(struct amd_iommu *iommu) if (r) { pci_disable_msi(iommu->dev); - return 1; + return r; } iommu->int_enabled = true; - iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); - - if (iommu->ppr_log != NULL) - iommu_feature_enable(iommu, CONTROL_PPFINT_EN); return 0; } static int iommu_init_msi(struct amd_iommu *iommu) { + int ret; + if (iommu->int_enabled) - return 0; + goto enable_faults; if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI)) - return iommu_setup_msi(iommu); + ret = iommu_setup_msi(iommu); + else + ret = -ENODEV; - return 1; + if (ret) + return ret; + +enable_faults: + iommu_feature_enable(iommu, CONTROL_EVT_INT_EN); + + if (iommu->ppr_log != NULL) + iommu_feature_enable(iommu, CONTROL_PPFINT_EN); + + return 0; } /**************************************************************************** diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index cdf36b1..239af9a 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -1904,6 +1904,8 @@ location_store(struct mddev *mddev, const char *buf, size_t len) if (mddev->pers) { mddev->pers->quiesce(mddev, 1); rv = bitmap_create(mddev); + if (!rv) + rv = bitmap_load(mddev); if (rv) { bitmap_destroy(mddev); mddev->bitmap_info.offset = 0; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 8c2a000..58d8c6d 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -176,7 +176,6 @@ struct crypt_config { #define MIN_IOS 16 #define MIN_POOL_PAGES 32 -#define MIN_BIO_PAGES 8 static struct kmem_cache *_crypt_io_pool; @@ -848,12 +847,11 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size, } /* - * if additional pages cannot be allocated without waiting, - * return a partially allocated bio, the caller will then try - * to allocate additional bios while submitting this partial bio + * If additional pages cannot be allocated without waiting, + * return a partially-allocated bio. The caller will then try + * to allocate more bios while submitting this partial bio. */ - if (i == (MIN_BIO_PAGES - 1)) - gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; + gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT; len = (size > PAGE_SIZE) ? PAGE_SIZE : size; @@ -1046,16 +1044,14 @@ static void kcryptd_queue_io(struct dm_crypt_io *io) queue_work(cc->io_queue, &io->work); } -static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, - int error, int async) +static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async) { struct bio *clone = io->ctx.bio_out; struct crypt_config *cc = io->target->private; - if (unlikely(error < 0)) { + if (unlikely(io->error < 0)) { crypt_free_buffer_pages(cc, clone); bio_put(clone); - io->error = -EIO; crypt_dec_pending(io); return; } @@ -1106,12 +1102,16 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) sector += bio_sectors(clone); crypt_inc_pending(io); + r = crypt_convert(cc, &io->ctx); + if (r < 0) + io->error = -EIO; + crypt_finished = atomic_dec_and_test(&io->ctx.pending); /* Encryption was already finished, submit io now */ if (crypt_finished) { - kcryptd_crypt_write_io_submit(io, r, 0); + kcryptd_crypt_write_io_submit(io, 0); /* * If there was an error, do not try next fragments. @@ -1162,11 +1162,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io) crypt_dec_pending(io); } -static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error) +static void kcryptd_crypt_read_done(struct dm_crypt_io *io) { - if (unlikely(error < 0)) - io->error = -EIO; - crypt_dec_pending(io); } @@ -1181,9 +1178,11 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) io->sector); r = crypt_convert(cc, &io->ctx); + if (r < 0) + io->error = -EIO; if (atomic_dec_and_test(&io->ctx.pending)) - kcryptd_crypt_read_done(io, r); + kcryptd_crypt_read_done(io); crypt_dec_pending(io); } @@ -1204,15 +1203,18 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post) error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq); + if (error < 0) + io->error = -EIO; + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); if (!atomic_dec_and_test(&ctx->pending)) return; if (bio_data_dir(io->base_bio) == READ) - kcryptd_crypt_read_done(io, error); + kcryptd_crypt_read_done(io); else - kcryptd_crypt_write_io_submit(io, error, 1); + kcryptd_crypt_write_io_submit(io, 1); } static void kcryptd_crypt(struct work_struct *work) diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index 042e719..aa70f7d 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c @@ -283,7 +283,7 @@ int dm_exception_store_init(void) return 0; persistent_fail: - dm_persistent_snapshot_exit(); + dm_transient_snapshot_exit(); transient_fail: return r; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index c308757..da2f021 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -124,7 +124,7 @@ struct cell { struct hlist_node list; struct bio_prison *prison; struct cell_key key; - unsigned count; + struct bio *holder; struct bio_list bios; }; @@ -220,55 +220,60 @@ static struct cell *__search_bucket(struct hlist_head *bucket, * This may block if a new cell needs allocating. You must ensure that * cells will be unlocked even if the calling thread is blocked. * - * Returns the number of entries in the cell prior to the new addition - * or < 0 on failure. + * Returns 1 if the cell was already held, 0 if @inmate is the new holder. */ static int bio_detain(struct bio_prison *prison, struct cell_key *key, struct bio *inmate, struct cell **ref) { - int r; + int r = 1; unsigned long flags; uint32_t hash = hash_key(prison, key); - struct cell *uninitialized_var(cell), *cell2 = NULL; + struct cell *cell, *cell2; BUG_ON(hash > prison->nr_buckets); spin_lock_irqsave(&prison->lock, flags); + cell = __search_bucket(prison->cells + hash, key); + if (cell) { + bio_list_add(&cell->bios, inmate); + goto out; + } - if (!cell) { - /* - * Allocate a new cell - */ - spin_unlock_irqrestore(&prison->lock, flags); - cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO); - spin_lock_irqsave(&prison->lock, flags); + /* + * Allocate a new cell + */ + spin_unlock_irqrestore(&prison->lock, flags); + cell2 = mempool_alloc(prison->cell_pool, GFP_NOIO); + spin_lock_irqsave(&prison->lock, flags); - /* - * We've been unlocked, so we have to double check that - * nobody else has inserted this cell in the meantime. - */ - cell = __search_bucket(prison->cells + hash, key); + /* + * We've been unlocked, so we have to double check that + * nobody else has inserted this cell in the meantime. + */ + cell = __search_bucket(prison->cells + hash, key); + if (cell) { + mempool_free(cell2, prison->cell_pool); + bio_list_add(&cell->bios, inmate); + goto out; + } + + /* + * Use new cell. + */ + cell = cell2; - if (!cell) { - cell = cell2; - cell2 = NULL; + cell->prison = prison; + memcpy(&cell->key, key, sizeof(cell->key)); + cell->holder = inmate; + bio_list_init(&cell->bios); + hlist_add_head(&cell->list, prison->cells + hash); - cell->prison = prison; - memcpy(&cell->key, key, sizeof(cell->key)); - cell->count = 0; - bio_list_init(&cell->bios); - hlist_add_head(&cell->list, prison->cells + hash); - } - } + r = 0; - r = cell->count++; - bio_list_add(&cell->bios, inmate); +out: spin_unlock_irqrestore(&prison->lock, flags); - if (cell2) - mempool_free(cell2, prison->cell_pool); - *ref = cell; return r; @@ -283,8 +288,8 @@ static void __cell_release(struct cell *cell, struct bio_list *inmates) hlist_del(&cell->list); - if (inmates) - bio_list_merge(inmates, &cell->bios); + bio_list_add(inmates, cell->holder); + bio_list_merge(inmates, &cell->bios); mempool_free(cell, prison->cell_pool); } @@ -305,22 +310,44 @@ static void cell_release(struct cell *cell, struct bio_list *bios) * bio may be in the cell. This function releases the cell, and also does * a sanity check. */ +static void __cell_release_singleton(struct cell *cell, struct bio *bio) +{ + hlist_del(&cell->list); + BUG_ON(cell->holder != bio); + BUG_ON(!bio_list_empty(&cell->bios)); +} + static void cell_release_singleton(struct cell *cell, struct bio *bio) { - struct bio_prison *prison = cell->prison; - struct bio_list bios; - struct bio *b; unsigned long flags; - - bio_list_init(&bios); + struct bio_prison *prison = cell->prison; spin_lock_irqsave(&prison->lock, flags); - __cell_release(cell, &bios); + __cell_release_singleton(cell, bio); spin_unlock_irqrestore(&prison->lock, flags); +} + +/* + * Sometimes we don't want the holder, just the additional bios. + */ +static void __cell_release_no_holder(struct cell *cell, struct bio_list *inmates) +{ + struct bio_prison *prison = cell->prison; - b = bio_list_pop(&bios); - BUG_ON(b != bio); - BUG_ON(!bio_list_empty(&bios)); + hlist_del(&cell->list); + bio_list_merge(inmates, &cell->bios); + + mempool_free(cell, prison->cell_pool); +} + +static void cell_release_no_holder(struct cell *cell, struct bio_list *inmates) +{ + unsigned long flags; + struct bio_prison *prison = cell->prison; + + spin_lock_irqsave(&prison->lock, flags); + __cell_release_no_holder(cell, inmates); + spin_unlock_irqrestore(&prison->lock, flags); } static void cell_error(struct cell *cell) @@ -800,21 +827,16 @@ static void cell_defer(struct thin_c *tc, struct cell *cell, * Same as cell_defer above, except it omits one particular detainee, * a write bio that covers the block and has already been processed. */ -static void cell_defer_except(struct thin_c *tc, struct cell *cell, - struct bio *exception) +static void cell_defer_except(struct thin_c *tc, struct cell *cell) { struct bio_list bios; - struct bio *bio; struct pool *pool = tc->pool; unsigned long flags; bio_list_init(&bios); - cell_release(cell, &bios); spin_lock_irqsave(&pool->lock, flags); - while ((bio = bio_list_pop(&bios))) - if (bio != exception) - bio_list_add(&pool->deferred_bios, bio); + cell_release_no_holder(cell, &pool->deferred_bios); spin_unlock_irqrestore(&pool->lock, flags); wake_worker(pool); @@ -854,7 +876,7 @@ static void process_prepared_mapping(struct new_mapping *m) * the bios in the cell. */ if (bio) { - cell_defer_except(tc, m->cell, bio); + cell_defer_except(tc, m->cell); bio_endio(bio, 0); } else cell_defer(tc, m->cell, m->data_block); diff --git a/drivers/md/md.c b/drivers/md/md.c index ce88755..6acc846 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1805,13 +1805,13 @@ retry: | BB_LEN(internal_bb)); *bbp++ = cpu_to_le64(store_bb); } + bb->changed = 0; if (read_seqretry(&bb->lock, seq)) goto retry; bb->sector = (rdev->sb_start + (int)le32_to_cpu(sb->bblog_offset)); bb->size = le16_to_cpu(sb->bblog_size); - bb->changed = 0; } } @@ -2366,6 +2366,7 @@ repeat: clear_bit(MD_CHANGE_PENDING, &mddev->flags); list_for_each_entry(rdev, &mddev->disks, same_set) { if (rdev->badblocks.changed) { + rdev->badblocks.changed = 0; md_ack_all_badblocks(&rdev->badblocks); md_error(mddev, rdev); } @@ -8157,30 +8158,23 @@ static int md_notify_reboot(struct notifier_block *this, struct mddev *mddev; int need_delay = 0; - if ((code == SYS_DOWN) || (code == SYS_HALT) || (code == SYS_POWER_OFF)) { - - printk(KERN_INFO "md: stopping all md devices.\n"); - - for_each_mddev(mddev, tmp) { - if (mddev_trylock(mddev)) { - /* Force a switch to readonly even array - * appears to still be in use. Hence - * the '100'. - */ - md_set_readonly(mddev, 100); - mddev_unlock(mddev); - } - need_delay = 1; + for_each_mddev(mddev, tmp) { + if (mddev_trylock(mddev)) { + __md_stop_writes(mddev); + mddev->safemode = 2; + mddev_unlock(mddev); } - /* - * certain more exotic SCSI devices are known to be - * volatile wrt too early system reboots. While the - * right place to handle this issue is the given - * driver, we do want to have a safe RAID driver ... - */ - if (need_delay) - mdelay(1000*1); + need_delay = 1; } + /* + * certain more exotic SCSI devices are known to be + * volatile wrt too early system reboots. While the + * right place to handle this issue is the given + * driver, we do want to have a safe RAID driver ... + */ + if (need_delay) + mdelay(1000*1); + return NOTIFY_DONE; } diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index 023fbc2..1a35caf 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -128,18 +128,9 @@ static void delete_at(struct node *n, unsigned index) n->header.nr_entries = cpu_to_le32(nr_entries - 1); } -static unsigned del_threshold(struct node *n) -{ - return le32_to_cpu(n->header.max_entries) / 3; -} - static unsigned merge_threshold(struct node *n) { - /* - * The extra one is because we know we're potentially going to - * delete an entry. - */ - return 2 * (le32_to_cpu(n->header.max_entries) / 3) + 1; + return le32_to_cpu(n->header.max_entries) / 3; } struct child { @@ -188,6 +179,15 @@ static int exit_child(struct dm_btree_info *info, struct child *c) static void shift(struct node *left, struct node *right, int count) { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); + uint32_t max_entries = le32_to_cpu(left->header.max_entries); + uint32_t r_max_entries = le32_to_cpu(right->header.max_entries); + + BUG_ON(max_entries != r_max_entries); + BUG_ON(nr_left - count > max_entries); + BUG_ON(nr_right + count > max_entries); + if (!count) return; @@ -199,13 +199,8 @@ static void shift(struct node *left, struct node *right, int count) node_shift(right, count); } - left->header.nr_entries = - cpu_to_le32(le32_to_cpu(left->header.nr_entries) - count); - BUG_ON(le32_to_cpu(left->header.nr_entries) > le32_to_cpu(left->header.max_entries)); - - right->header.nr_entries = - cpu_to_le32(le32_to_cpu(right->header.nr_entries) + count); - BUG_ON(le32_to_cpu(right->header.nr_entries) > le32_to_cpu(right->header.max_entries)); + left->header.nr_entries = cpu_to_le32(nr_left - count); + right->header.nr_entries = cpu_to_le32(nr_right + count); } static void __rebalance2(struct dm_btree_info *info, struct node *parent, @@ -215,8 +210,9 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent, struct node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); + unsigned threshold = 2 * merge_threshold(left) + 1; - if (nr_left + nr_right <= merge_threshold(left)) { + if (nr_left + nr_right < threshold) { /* * Merge */ @@ -234,9 +230,6 @@ static void __rebalance2(struct dm_btree_info *info, struct node *parent, * Rebalance. */ unsigned target_left = (nr_left + nr_right) / 2; - unsigned shift_ = nr_left - target_left; - BUG_ON(le32_to_cpu(left->header.max_entries) <= nr_left - shift_); - BUG_ON(le32_to_cpu(right->header.max_entries) <= nr_right + shift_); shift(left, right, nr_left - target_left); *key_ptr(parent, r->index) = right->keys[0]; } @@ -272,6 +265,84 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, return exit_child(info, &right); } +/* + * We dump as many entries from center as possible into left, then the rest + * in right, then rebalance2. This wastes some cpu, but I want something + * simple atm. + */ +static void delete_center_node(struct dm_btree_info *info, struct node *parent, + struct child *l, struct child *c, struct child *r, + struct node *left, struct node *center, struct node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) +{ + uint32_t max_entries = le32_to_cpu(left->header.max_entries); + unsigned shift = min(max_entries - nr_left, nr_center); + + BUG_ON(nr_left + shift > max_entries); + node_copy(left, center, -shift); + left->header.nr_entries = cpu_to_le32(nr_left + shift); + + if (shift != nr_center) { + shift = nr_center - shift; + BUG_ON((nr_right + shift) > max_entries); + node_shift(right, shift); + node_copy(center, right, shift); + right->header.nr_entries = cpu_to_le32(nr_right + shift); + } + *key_ptr(parent, r->index) = right->keys[0]; + + delete_at(parent, c->index); + r->index--; + + dm_tm_dec(info->tm, dm_block_location(c->block)); + __rebalance2(info, parent, l, r); +} + +/* + * Redistributes entries among 3 sibling nodes. + */ +static void redistribute3(struct dm_btree_info *info, struct node *parent, + struct child *l, struct child *c, struct child *r, + struct node *left, struct node *center, struct node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) +{ + int s; + uint32_t max_entries = le32_to_cpu(left->header.max_entries); + unsigned target = (nr_left + nr_center + nr_right) / 3; + BUG_ON(target > max_entries); + + if (nr_left < nr_right) { + s = nr_left - target; + + if (s < 0 && nr_center < -s) { + /* not enough in central node */ + shift(left, center, nr_center); + s = nr_center - target; + shift(left, right, s); + nr_right += s; + } else + shift(left, center, s); + + shift(center, right, target - nr_right); + + } else { + s = target - nr_right; + if (s > 0 && nr_center < s) { + /* not enough in central node */ + shift(center, right, nr_center); + s = target - nr_center; + shift(left, right, s); + nr_left -= s; + } else + shift(center, right, s); + + shift(left, center, nr_left - target); + } + + *key_ptr(parent, c->index) = center->keys[0]; + *key_ptr(parent, r->index) = right->keys[0]; +} + static void __rebalance3(struct dm_btree_info *info, struct node *parent, struct child *l, struct child *c, struct child *r) { @@ -282,62 +353,18 @@ static void __rebalance3(struct dm_btree_info *info, struct node *parent, uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_center = le32_to_cpu(center->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); - uint32_t max_entries = le32_to_cpu(left->header.max_entries); - unsigned target; + unsigned threshold = merge_threshold(left) * 4 + 1; BUG_ON(left->header.max_entries != center->header.max_entries); BUG_ON(center->header.max_entries != right->header.max_entries); - if (((nr_left + nr_center + nr_right) / 2) < merge_threshold(center)) { - /* - * Delete center node: - * - * We dump as many entries from center as possible into - * left, then the rest in right, then rebalance2. This - * wastes some cpu, but I want something simple atm. - */ - unsigned shift = min(max_entries - nr_left, nr_center); - - BUG_ON(nr_left + shift > max_entries); - node_copy(left, center, -shift); - left->header.nr_entries = cpu_to_le32(nr_left + shift); - - if (shift != nr_center) { - shift = nr_center - shift; - BUG_ON((nr_right + shift) >= max_entries); - node_shift(right, shift); - node_copy(center, right, shift); - right->header.nr_entries = cpu_to_le32(nr_right + shift); - } - *key_ptr(parent, r->index) = right->keys[0]; - - delete_at(parent, c->index); - r->index--; - - dm_tm_dec(info->tm, dm_block_location(c->block)); - __rebalance2(info, parent, l, r); - - return; - } - - /* - * Rebalance - */ - target = (nr_left + nr_center + nr_right) / 3; - BUG_ON(target > max_entries); - - /* - * Adjust the left node - */ - shift(left, center, nr_left - target); - - /* - * Adjust the right node - */ - shift(center, right, target - nr_right); - *key_ptr(parent, c->index) = center->keys[0]; - *key_ptr(parent, r->index) = right->keys[0]; + if ((nr_left + nr_center + nr_right) < threshold) + delete_center_node(info, parent, l, c, r, left, center, right, + nr_left, nr_center, nr_right); + else + redistribute3(info, parent, l, c, r, left, center, right, + nr_left, nr_center, nr_right); } static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, @@ -441,9 +468,6 @@ static int rebalance_children(struct shadow_spine *s, if (r) return r; - if (child_entries > del_threshold(n)) - return 0; - has_left_sibling = i > 0; has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a0b225e..118e0f6 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -737,9 +737,22 @@ static void wait_barrier(struct r1conf *conf) spin_lock_irq(&conf->resync_lock); if (conf->barrier) { conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, !conf->barrier, + /* Wait for the barrier to drop. + * However if there are already pending + * requests (preventing the barrier from + * rising completely), and the + * pre-process bio queue isn't empty, + * then don't wait, as we need to empty + * that queue to get the nr_pending + * count down. + */ + wait_event_lock_irq(conf->wait_barrier, + !conf->barrier || + (conf->nr_pending && + current->bio_list && + !bio_list_empty(current->bio_list)), conf->resync_lock, - ); + ); conf->nr_waiting--; } conf->nr_pending++; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 58c44d6..be7101d 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -863,9 +863,22 @@ static void wait_barrier(struct r10conf *conf) spin_lock_irq(&conf->resync_lock); if (conf->barrier) { conf->nr_waiting++; - wait_event_lock_irq(conf->wait_barrier, !conf->barrier, + /* Wait for the barrier to drop. + * However if there are already pending + * requests (preventing the barrier from + * rising completely), and the + * pre-process bio queue isn't empty, + * then don't wait, as we need to empty + * that queue to get the nr_pending + * count down. + */ + wait_event_lock_irq(conf->wait_barrier, + !conf->barrier || + (conf->nr_pending && + current->bio_list && + !bio_list_empty(current->bio_list)), conf->resync_lock, - ); + ); conf->nr_waiting--; } conf->nr_pending++; diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c index 38ef025..81305de 100644 --- a/drivers/media/dvb/dvb-usb/mxl111sf.c +++ b/drivers/media/dvb/dvb-usb/mxl111sf.c @@ -351,15 +351,13 @@ static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff) adap_state->ep6_clockphase, 0, 0); mxl_fail(ret); +#if 0 } else { ret = mxl111sf_disable_656_port(state); mxl_fail(ret); +#endif } - mxl111sf_read_reg(state, 0x12, &tmp); - tmp &= ~0x04; - mxl111sf_write_reg(state, 0x12, tmp); - return ret; } diff --git a/drivers/media/dvb/frontends/au8522_dig.c b/drivers/media/dvb/frontends/au8522_dig.c index c688b95..25f6509 100644 --- a/drivers/media/dvb/frontends/au8522_dig.c +++ b/drivers/media/dvb/frontends/au8522_dig.c @@ -588,11 +588,6 @@ static int au8522_set_frontend(struct dvb_frontend *fe) (state->current_modulation == c->modulation)) return 0; - au8522_enable_modulation(fe, c->modulation); - - /* Allow the demod to settle */ - msleep(100); - if (fe->ops.tuner_ops.set_params) { if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); @@ -604,6 +599,11 @@ static int au8522_set_frontend(struct dvb_frontend *fe) if (ret < 0) return ret; + /* Allow the tuner to settle */ + msleep(100); + + au8522_enable_modulation(fe, c->modulation); + state->current_frequency = c->frequency; return 0; diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c index c990d35..e046622 100644 --- a/drivers/media/dvb/frontends/lgdt330x.c +++ b/drivers/media/dvb/frontends/lgdt330x.c @@ -104,8 +104,8 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state, * then reads the data returned for (len) bytes. */ -static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, - enum I2C_REG reg, u8* buf, int len) +static int i2c_read_demod_bytes(struct lgdt330x_state *state, + enum I2C_REG reg, u8 *buf, int len) { u8 wr [] = { reg }; struct i2c_msg msg [] = { @@ -118,6 +118,8 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state, ret = i2c_transfer(state->i2c, msg, 2); if (ret != 2) { printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret); + if (ret >= 0) + ret = -EIO; } else { ret = 0; } diff --git a/drivers/media/dvb/frontends/tda10071.c b/drivers/media/dvb/frontends/tda10071.c index a992050..c21bc92 100644 --- a/drivers/media/dvb/frontends/tda10071.c +++ b/drivers/media/dvb/frontends/tda10071.c @@ -1215,7 +1215,7 @@ error: EXPORT_SYMBOL(tda10071_attach); static struct dvb_frontend_ops tda10071_ops = { - .delsys = { SYS_DVBT, SYS_DVBT2 }, + .delsys = { SYS_DVBS, SYS_DVBS2 }, .info = { .name = "NXP TDA10071", .frequency_min = 950000, diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c index c6da8f7..d8c8982 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c +++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c @@ -320,7 +320,17 @@ static struct tda829x_config tda829x_no_probe = { .probe_tuner = TDA829X_DONT_PROBE, }; +static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = { + .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5, + .if_lvl = 1, .rfagc_top = 0x37, }, + .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6, + .if_lvl = 1, .rfagc_top = 0x37, }, +}; + static struct tda18271_config hauppauge_tda18271_dvb_config = { + .std_map = &hauppauge_tda18271_dvbt_std_map, .gate = TDA18271_GATE_ANALOG, .output_opt = TDA18271_OUTPUT_LT_OFF, }; diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index a04b3c1..f04920b 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -270,6 +270,20 @@ static int wm8994_suspend(struct device *dev) break; } + switch (wm8994->type) { + case WM1811: + ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2); + if (ret < 0) { + dev_err(dev, "Failed to read jackdet: %d\n", ret); + } else if (ret & WM1811_JACKDET_MODE_MASK) { + dev_dbg(dev, "CODEC still active, ignoring suspend\n"); + return 0; + } + break; + default: + break; + } + /* Disable LDO pulldowns while the device is suspended if we * don't know that something will be driving them. */ if (!wm8994->ldo_ena_always_driven) diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 0cb17d9..b99318e 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -1174,7 +1174,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ech) - goto out_slab; + goto out_si; vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); if (!vidh) @@ -1235,8 +1235,6 @@ out_vidh: ubi_free_vid_hdr(ubi, vidh); out_ech: kfree(ech); -out_slab: - kmem_cache_destroy(si->scan_leb_slab); out_si: ubi_scan_destroy_si(si); return ERR_PTR(err); @@ -1325,7 +1323,9 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) } } - kmem_cache_destroy(si->scan_leb_slab); + if (si->scan_leb_slab) + kmem_cache_destroy(si->scan_leb_slab); + kfree(si); } diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 0696e36..cf42971 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -389,7 +389,7 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max) */ int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) { - int err, medium_ec; + int err; struct ubi_wl_entry *e, *first, *last; ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM || @@ -427,7 +427,7 @@ retry: * For unknown data we pick a physical eraseblock with medium * erase counter. But we by no means can pick a physical * eraseblock with erase counter greater or equivalent than the - * lowest erase counter plus %WL_FREE_MAX_DIFF. + * lowest erase counter plus %WL_FREE_MAX_DIFF/2. */ first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb); @@ -436,10 +436,8 @@ retry: if (last->ec - first->ec < WL_FREE_MAX_DIFF) e = rb_entry(ubi->free.rb_node, struct ubi_wl_entry, u.rb); - else { - medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2; - e = find_wl_entry(&ubi->free, medium_ec); - } + else + e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2); break; case UBI_SHORTTERM: /* diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 760c2b1..b4a208e 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -95,6 +95,10 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); +static int legacy_pme = 0; +module_param(legacy_pme, int, 0); +MODULE_PARM_DESC(legacy_pme, "Legacy power management"); + static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */ { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */ @@ -867,6 +871,13 @@ static void sky2_wol_init(struct sky2_port *sky2) /* Disable PiG firmware */ sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF); + /* Needed by some broken BIOSes, use PCI rather than PCI-e for WOL */ + if (legacy_pme) { + u32 reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); + reg1 |= PCI_Y2_PME_LEGACY; + sky2_pci_write32(hw, PCI_DEV_REG1, reg1); + } + /* block receiver */ sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); sky2_read32(hw, B0_CTST); diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index d498f04..8bf22b6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -394,7 +394,7 @@ static int mlx4_how_many_lives_vf(struct mlx4_dev *dev) return ret; } -static int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) +int mlx4_is_slave_active(struct mlx4_dev *dev, int slave) { struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_slave_state *s_slave; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 59681f0..9611049 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -589,6 +589,14 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) entry = (struct skb_data *) skb->cb; urb = entry->urb; + /* + * Get reference count of the URB to avoid it to be + * freed during usb_unlink_urb, which may trigger + * use-after-free problem inside usb_unlink_urb since + * usb_unlink_urb is always racing with .complete + * handler(include defer_bh). + */ + usb_get_urb(urb); spin_unlock_irqrestore(&q->lock, flags); // during some PM-driven resume scenarios, // these (async) unlinks complete immediately @@ -597,6 +605,7 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q) netdev_dbg(dev->net, "unlink urb err, %d\n", retval); else count++; + usb_put_urb(urb); spin_lock_irqsave(&q->lock, flags); } spin_unlock_irqrestore (&q->lock, flags); @@ -1028,7 +1037,6 @@ static void tx_complete (struct urb *urb) } usb_autopm_put_interface_async(dev->intf); - urb->dev = NULL; entry->state = tx_done; defer_bh(dev, skb, &dev->txq); } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 4a00806..a09abc2 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -118,13 +118,15 @@ void ath9k_ps_restore(struct ath_softc *sc) if (--sc->ps_usecount != 0) goto unlock; - if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) + if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) + goto unlock; + + if (sc->ps_idle) mode = ATH9K_PM_FULL_SLEEP; else if (sc->ps_enabled && !(sc->ps_flags & (PS_WAIT_FOR_BEACON | PS_WAIT_FOR_CAB | - PS_WAIT_FOR_PSPOLL_DATA | - PS_WAIT_FOR_TX_ACK))) + PS_WAIT_FOR_PSPOLL_DATA))) mode = ATH9K_PM_NETWORK_SLEEP; else goto unlock; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7bcfa78..3abe9ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1465,20 +1465,10 @@ void iwl_bg_watchdog(unsigned long data) if (timeout == 0) return; - /* monitor and check for stuck cmd queue */ - if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) - return; - - /* monitor and check for other stuck queues */ - if (iwl_is_any_associated(priv)) { - for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) { - /* skip as we already checked the command queue */ - if (cnt == priv->shrd->cmd_queue) - continue; - if (iwl_check_stuck_queue(priv, cnt)) - return; - } - } + /* monitor and check for stuck queues */ + for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) + if (iwl_check_stuck_queue(priv, cnt)) + return; mod_timer(&priv->watchdog, jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout))); diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c index 7faed62..f792990 100644 --- a/drivers/net/wireless/p54/p54spi.c +++ b/drivers/net/wireless/p54/p54spi.c @@ -618,19 +618,19 @@ static int __devinit p54spi_probe(struct spi_device *spi) ret = spi_setup(spi); if (ret < 0) { dev_err(&priv->spi->dev, "spi_setup failed"); - goto err_free_common; + goto err_free; } ret = gpio_request(p54spi_gpio_power, "p54spi power"); if (ret < 0) { dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); - goto err_free_common; + goto err_free; } ret = gpio_request(p54spi_gpio_irq, "p54spi irq"); if (ret < 0) { dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); - goto err_free_common; + goto err_free_gpio_power; } gpio_direction_output(p54spi_gpio_power, 0); @@ -641,7 +641,7 @@ static int __devinit p54spi_probe(struct spi_device *spi) priv->spi); if (ret < 0) { dev_err(&priv->spi->dev, "request_irq() failed"); - goto err_free_common; + goto err_free_gpio_irq; } irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING); @@ -673,6 +673,12 @@ static int __devinit p54spi_probe(struct spi_device *spi) return 0; err_free_common: + free_irq(gpio_to_irq(p54spi_gpio_irq), spi); +err_free_gpio_irq: + gpio_free(p54spi_gpio_irq); +err_free_gpio_power: + gpio_free(p54spi_gpio_power); +err_free: p54_free_common(priv->hw); return ret; } diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 262ee9e..7ef0b74 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c13) }, { USB_DEVICE(0x07d1, 0x3c15) }, { USB_DEVICE(0x07d1, 0x3c16) }, + { USB_DEVICE(0x2001, 0x3c1b) }, /* Draytek */ { USB_DEVICE(0x07fa, 0x7712) }, /* DVICO */ diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 8d6eb0f..30fc641 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -413,6 +413,7 @@ void rtl_init_rfkill(struct ieee80211_hw *hw) wiphy_rfkill_start_polling(hw->wiphy); } +EXPORT_SYMBOL(rtl_init_rfkill); void rtl_deinit_rfkill(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index 3f0f056..79b7b16 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c @@ -31,8 +31,50 @@ #include "core.h" #include "cam.h" #include "base.h" +#include "pci.h" #include "ps.h" +#include + +void rtl_fw_cb(const struct firmware *firmware, void *context) +{ + struct ieee80211_hw *hw = context; + struct rtl_priv *rtlpriv = rtl_priv(hw); + int err; + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + ("Firmware callback routine entered!\n")); + complete(&rtlpriv->firmware_loading_complete); + if (!firmware) { + pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0; + return; + } + if (firmware->size > rtlpriv->max_fw_size) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return; + } + memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); + rtlpriv->rtlhal.fwsize = firmware->size; + release_firmware(firmware); + + err = ieee80211_register_hw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't register mac80211 hw\n")); + return; + } else { + rtlpriv->mac80211.mac80211_registered = 1; + } + set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + + /*init rfkill */ + rtl_init_rfkill(hw); +} +EXPORT_SYMBOL(rtl_fw_cb); + /*mutex for start & stop is must here. */ static int rtl_op_start(struct ieee80211_hw *hw) { diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index f02824a..5e8482b 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h @@ -30,8 +30,6 @@ #ifndef __RTL_CORE_H__ #define __RTL_CORE_H__ -#include - #define RTL_SUPPORTED_FILTERS \ (FIF_PROMISC_IN_BSS | \ FIF_ALLMULTI | FIF_CONTROL | \ @@ -42,4 +40,6 @@ #define RTL_SUPPORTED_CTRL_FILTER 0xFF extern const struct ieee80211_ops rtl_ops; +void rtl_fw_cb(const struct firmware *firmware, void *context); + #endif diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 9245d88..34a7c45 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -28,8 +28,8 @@ *****************************************************************************/ #include -#include "core.h" #include "wifi.h" +#include "core.h" #include "pci.h" #include "base.h" #include "ps.h" @@ -657,6 +657,8 @@ static void _rtl_receive_one(struct ieee80211_hw *hw, struct sk_buff *skb, return; uskb = dev_alloc_skb(skb->len + 128); + if (!uskb) + return; /* exit if allocation failed */ memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, sizeof(rx_status)); pdata = (u8 *)skb_put(uskb, skb->len); memcpy(pdata, skb->data, skb->len); @@ -1155,10 +1157,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, ring->idx = (ring->idx + 1) % ring->entries; } - pci_free_consistent(rtlpci->pdev, - sizeof(*ring->desc) * ring->entries, - ring->desc, ring->dma); - ring->desc = NULL; + if (ring->desc) { + pci_free_consistent(rtlpci->pdev, + sizeof(*ring->desc) * ring->entries, + ring->desc, ring->dma); + ring->desc = NULL; + } } static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) @@ -1182,12 +1186,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci) kfree_skb(skb); } - pci_free_consistent(rtlpci->pdev, + if (rtlpci->rx_ring[rx_queue_idx].desc) { + pci_free_consistent(rtlpci->pdev, sizeof(*rtlpci->rx_ring[rx_queue_idx]. desc) * rtlpci->rxringcount, rtlpci->rx_ring[rx_queue_idx].desc, rtlpci->rx_ring[rx_queue_idx].dma); - rtlpci->rx_ring[rx_queue_idx].desc = NULL; + rtlpci->rx_ring[rx_queue_idx].desc = NULL; + } } } @@ -1573,6 +1579,9 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->hw_disable(hw); + /* some things are not needed if firmware not available */ + if (!rtlpriv->max_fw_size) + return; rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flags); @@ -1791,6 +1800,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, rtlpriv = hw->priv; pcipriv = (void *)rtlpriv->priv; pcipriv->dev.pdev = pdev; + init_completion(&rtlpriv->firmware_loading_complete); /* init cfg & intf_ops */ rtlpriv->rtlhal.interface = INTF_PCI; @@ -1811,7 +1821,7 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, err = pci_request_regions(pdev, KBUILD_MODNAME); if (err) { RT_ASSERT(false, ("Can't obtain PCI resources\n")); - return err; + goto fail2; } pmem_start = pci_resource_start(pdev, rtlpriv->cfg->bar_id); @@ -1877,15 +1887,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, goto fail3; } - err = ieee80211_register_hw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Can't register mac80211 hw.\n")); - goto fail3; - } else { - rtlpriv->mac80211.mac80211_registered = 1; - } - err = sysfs_create_group(&pdev->dev.kobj, &rtl_attribute_group); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, @@ -1893,9 +1894,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, goto fail3; } - /*init rfkill */ - rtl_init_rfkill(hw); - rtlpci = rtl_pcidev(pcipriv); err = request_irq(rtlpci->pdev->irq, &_rtl_pci_interrupt, IRQF_SHARED, KBUILD_MODNAME, hw); @@ -1904,24 +1902,22 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, ("%s: failed to register IRQ handler\n", wiphy_name(hw->wiphy))); goto fail3; - } else { - rtlpci->irq_alloc = 1; } + rtlpci->irq_alloc = 1; - set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); return 0; fail3: pci_set_drvdata(pdev, NULL); rtl_deinit_core(hw); _rtl_pci_io_handler_release(hw); - ieee80211_free_hw(hw); if (rtlpriv->io.pci_mem_start != 0) pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); fail2: pci_release_regions(pdev); + complete(&rtlpriv->firmware_loading_complete); fail1: @@ -1940,6 +1936,8 @@ void rtl_pci_disconnect(struct pci_dev *pdev) struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); struct rtl_mac *rtlmac = rtl_mac(rtlpriv); + /* just in case driver is removed before firmware callback */ + wait_for_completion(&rtlpriv->firmware_loading_complete); clear_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); sysfs_remove_group(&pdev->dev.kobj, &rtl_attribute_group); diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h index ebe0b42..0860896 100644 --- a/drivers/net/wireless/rtlwifi/pci.h +++ b/drivers/net/wireless/rtlwifi/pci.h @@ -239,7 +239,6 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev, void rtl_pci_disconnect(struct pci_dev *pdev); int rtl_pci_suspend(struct device *dev); int rtl_pci_resume(struct device *dev); - static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr) { return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr); diff --git a/drivers/net/wireless/rtlwifi/ps.c b/drivers/net/wireless/rtlwifi/ps.c index 130fdd9..bc33a61 100644 --- a/drivers/net/wireless/rtlwifi/ps.c +++ b/drivers/net/wireless/rtlwifi/ps.c @@ -47,7 +47,8 @@ bool rtl_ps_enable_nic(struct ieee80211_hw *hw) ("Driver is already down!\n")); /*<2> Enable Adapter */ - rtlpriv->cfg->ops->hw_init(hw); + if (rtlpriv->cfg->ops->hw_init(hw)) + return 1; RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); /*<3> Enable Interrupt */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index 72a98ca..a004ad7 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -524,6 +524,10 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) dm_digtable.cur_igvalue, dm_digtable.pre_igvalue, dm_digtable.backoff_val)); + dm_digtable.cur_igvalue += 2; + if (dm_digtable.cur_igvalue > 0x3f) + dm_digtable.cur_igvalue = 0x3f; + if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) { rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, dm_digtable.cur_igvalue); @@ -1219,13 +1223,18 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) ("PreState = %d, CurState = %d\n", p_ra->pre_ratr_state, p_ra->ratr_state)); - rcu_read_lock(); - sta = ieee80211_find_sta(mac->vif, mac->bssid); + /* Only the PCI card uses sta in the update rate table + * callback routine */ + if (rtlhal->interface == INTF_PCI) { + rcu_read_lock(); + sta = ieee80211_find_sta(mac->vif, mac->bssid); + } rtlpriv->cfg->ops->update_rate_tbl(hw, sta, p_ra->ratr_state); p_ra->pre_ratr_state = p_ra->ratr_state; - rcu_read_unlock(); + if (rtlhal->interface == INTF_PCI) + rcu_read_unlock(); } } } diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index 931d979..a0af233 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c @@ -262,10 +262,9 @@ int rtl92c_download_fw(struct ieee80211_hw *hw) u32 fwsize; enum version_8192c version = rtlhal->version; - if (!rtlhal->pfirmware) + if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) return 1; - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware; pfwdata = (u8 *) rtlhal->pfirmware; fwsize = rtlhal->fwsize; @@ -518,15 +517,8 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw, void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len, u8 *p_cmdbuffer) { - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u32 tmp_cmdbuf[2]; - if (rtlhal->fw_ready == false) { - RT_ASSERT(false, ("return H2C cmd because of Fw " - "download fail!!!\n")); - return; - } - memset(tmp_cmdbuf, 0, 8); memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len); _rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); @@ -788,6 +780,8 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) skb = dev_alloc_skb(totalpacketlen); + if (!skb) + return; memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, totalpacketlen); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index a3deaef..b603289 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -921,10 +921,7 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) ("Failed to download FW. Init HW " "without FW now..\n")); err = 1; - rtlhal->fw_ready = false; return err; - } else { - rtlhal->fw_ready = true; } rtlhal->last_hmeboxnum = 0; @@ -1199,7 +1196,6 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u8 u1b_tmp; u32 u4b_tmp; @@ -1210,7 +1206,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0); - if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready) + if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) rtl92c_firmware_selfreset(hw); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51); rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 89ef698..3d3b52c 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -92,9 +92,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) int err; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - const struct firmware *firmware; struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - char *fw_name = NULL; rtl8192ce_bt_reg_init(hw); @@ -166,26 +164,20 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) /* request fw */ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && !IS_92C_SERIAL(rtlhal->version)) - fw_name = "rtlwifi/rtl8192cfwU.bin"; + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) - fw_name = "rtlwifi/rtl8192cfwU_B.bin"; - else - fw_name = rtlpriv->cfg->fw_name; - err = request_firmware(&firmware, fw_name, rtlpriv->io.dev); + rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; + + rtlpriv->max_fw_size = 0x4000; + pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Failed to request firmware!\n")); return 1; } - if (firmware->size > 0x4000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); return 0; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 124cf63..d3a9341 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -1171,10 +1171,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Failed to download FW. Init HW without FW now..\n")); err = 1; - rtlhal->fw_ready = false; return err; - } else { - rtlhal->fw_ready = true; } rtlhal->last_hmeboxnum = 0; /* h2c */ _rtl92cu_phy_param_tab_init(hw); @@ -1270,24 +1267,22 @@ static void _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM) if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) { /* reset MCU ready status */ rtl_write_byte(rtlpriv, REG_MCUFWDL, 0); - if (rtlhal->fw_ready) { - /* 8051 reset by self */ - rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); - while ((retry_cnts++ < 100) && - (FEN_CPUEN & rtl_read_word(rtlpriv, - REG_SYS_FUNC_EN))) { - udelay(50); - } - if (retry_cnts >= 100) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + /* 8051 reset by self */ + rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20); + while ((retry_cnts++ < 100) && + (FEN_CPUEN & rtl_read_word(rtlpriv, + REG_SYS_FUNC_EN))) { + udelay(50); + } + if (retry_cnts >= 100) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("#####=> 8051 reset failed!.." ".......................\n");); - /* if 8051 reset fail, reset MAC. */ - rtl_write_byte(rtlpriv, - REG_SYS_FUNC_EN + 1, - 0x50); - udelay(100); - } + /* if 8051 reset fail, reset MAC. */ + rtl_write_byte(rtlpriv, + REG_SYS_FUNC_EN + 1, + 0x50); + udelay(100); } } /* Reset MAC and Enable 8051 */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 6d2ca77..adf320d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -54,7 +54,6 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin"); static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); - const struct firmware *firmware; int err; rtlpriv->dm.dm_initialgain_enable = true; @@ -62,29 +61,21 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) rtlpriv->dm.disable_framebursting = false; rtlpriv->dm.thermalvalue = 0; rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug; - rtlpriv->rtlhal.pfirmware = vmalloc(0x4000); + + /* for firmware buf */ + rtlpriv->rtlhal.pfirmware = vzalloc(0x4000); if (!rtlpriv->rtlhal.pfirmware) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Can't alloc buffer for fw.\n")); return 1; } - /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); - if (err) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Failed to request firmware!\n")); - return 1; - } - if (firmware->size > 0x4000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); + + pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0x4000; + err = request_firmware_nowait(THIS_MODULE, 1, + rtlpriv->cfg->fw_name, rtlpriv->io.dev, + GFP_KERNEL, hw, rtl_fw_cb); + return 0; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c index 82f060b..335f582 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/fw.c @@ -257,7 +257,7 @@ int rtl92d_download_fw(struct ieee80211_hw *hw) bool fw_downloaded = false, fwdl_in_process = false; unsigned long flags; - if (!rtlhal->pfirmware) + if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) return 1; fwsize = rtlhal->fwsize; pfwheader = (u8 *) rtlhal->pfirmware; @@ -539,14 +539,8 @@ static void _rtl92d_fill_h2c_command(struct ieee80211_hw *hw, void rtl92d_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, u32 cmd_len, u8 *cmdbuffer) { - struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); u32 tmp_cmdbuf[2]; - if (rtlhal->fw_ready == false) { - RT_ASSERT(false, ("return H2C cmd because of Fw " - "download fail!!!\n")); - return; - } memset(tmp_cmdbuf, 0, 8); memcpy(tmp_cmdbuf, cmdbuffer, cmd_len); _rtl92d_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf); @@ -763,12 +757,16 @@ void rtl92d_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished) "rtl92d_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n", u1RsvdPageLoc, 3); skb = dev_alloc_skb(totalpacketlen); - memcpy((u8 *) skb_put(skb, totalpacketlen), &reserved_page_packet, - totalpacketlen); - rtstatus = _rtl92d_cmd_send_packet(hw, skb); + if (!skb) { + dlok = false; + } else { + memcpy((u8 *) skb_put(skb, totalpacketlen), + &reserved_page_packet, totalpacketlen); + rtstatus = _rtl92d_cmd_send_packet(hw, skb); - if (rtstatus) - dlok = true; + if (rtstatus) + dlok = true; + } if (dlok) { RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("Set RSVD page location to Fw.\n")); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c index 9d89d7c..e6dabf6 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c @@ -932,10 +932,7 @@ int rtl92de_hw_init(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Failed to download FW. Init HW " "without FW..\n")); - rtlhal->fw_ready = false; return 1; - } else { - rtlhal->fw_ready = true; } rtlhal->last_hmeboxnum = 0; rtlpriv->psc.fw_current_inpsmode = false; diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 7911c9c..2afcfe3 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -94,7 +94,6 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) u8 tid; struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - const struct firmware *firmware; static int header_print; rtlpriv->dm.dm_initialgain_enable = true; @@ -170,6 +169,15 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) else if (rtlpriv->psc.reg_fwctrl_lps == 3) rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; + /* for early mode */ + rtlpriv->rtlhal.earlymode_enable = true; + for (tid = 0; tid < 8; tid++) + skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); + + /* Only load firmware for first MAC */ + if (header_print) + return 0; + /* for firmware buf */ rtlpriv->rtlhal.pfirmware = vzalloc(0x8000); if (!rtlpriv->rtlhal.pfirmware) { @@ -178,33 +186,21 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw) return 1; } - if (!header_print) { - pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); - pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); - header_print++; - } + rtlpriv->max_fw_size = 0x8000; + pr_info("Driver for Realtek RTL8192DE WLAN interface\n"); + pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name); + header_print++; + /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl_fw_cb); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Failed to request firmware!\n")); return 1; } - if (firmware->size > 0x8000) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size); - rtlpriv->rtlhal.fwsize = firmware->size; - release_firmware(firmware); - /* for early mode */ - rtlpriv->rtlhal.earlymode_enable = true; - for (tid = 0; tid < 8; tid++) - skb_queue_head_init(&rtlpriv->mac80211.skb_waitq[tid]); return 0; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c index 3fda6b1..4bb113f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c @@ -364,7 +364,7 @@ int rtl92s_download_fw(struct ieee80211_hw *hw) u8 fwstatus = FW_STATUS_INIT; bool rtstatus = true; - if (!rtlhal->pfirmware) + if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) return 1; firmware = (struct rt_firmware *)rtlhal->pfirmware; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index c474486..58b1a6a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c @@ -952,11 +952,10 @@ int rtl92se_hw_init(struct ieee80211_hw *hw) if (!rtstatus) { RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Failed to download FW. " - "Init HW without FW now.., Please copy FW into" + "Init HW without FW now.., " + "Please copy FW into" "/lib/firmware/rtlwifi\n")); - rtlhal->fw_ready = false; - } else { - rtlhal->fw_ready = true; + return 1; } /* After FW download, we have to reset MAC register */ @@ -1219,9 +1218,14 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw) void rtl92se_disable_interrupt(struct ieee80211_hw *hw) { - struct rtl_priv *rtlpriv = rtl_priv(hw); - struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); + struct rtl_priv *rtlpriv; + struct rtl_pci *rtlpci; + rtlpriv = rtl_priv(hw); + /* if firmware not available, no interrupts */ + if (!rtlpriv || !rtlpriv->max_fw_size) + return; + rtlpci = rtl_pcidev(rtl_pcipriv(hw)); rtl_write_dword(rtlpriv, INTA_MASK, 0); rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c index e3fe7c9..8b4d56a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/led.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c @@ -76,10 +76,13 @@ void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) { - struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_priv *rtlpriv; struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); u8 ledcfg; + rtlpriv = rtl_priv(hw); + if (!rtlpriv || rtlpriv->max_fw_size) + return; RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 78723cf..2b72c61 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -35,6 +35,8 @@ #include "../wifi.h" #include "../core.h" #include "../pci.h" +#include "../base.h" +#include "../pci.h" #include "reg.h" #include "def.h" #include "phy.h" @@ -89,12 +91,53 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) rtlpci->const_support_pciaspm = 2; } +static void rtl92se_fw_cb(const struct firmware *firmware, void *context) +{ + struct ieee80211_hw *hw = context; + struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); + struct rtl_priv *rtlpriv = rtl_priv(hw); + struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); + struct rt_firmware *pfirmware = NULL; + int err; + + RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, + ("Firmware callback routine entered!\n")); + complete(&rtlpriv->firmware_loading_complete); + if (!firmware) { + pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name); + rtlpriv->max_fw_size = 0; + return; + } + if (firmware->size > rtlpriv->max_fw_size) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Firmware is too big!\n")); + release_firmware(firmware); + return; + } + pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; + memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); + pfirmware->sz_fw_tmpbufferlen = firmware->size; + release_firmware(firmware); + + err = ieee80211_register_hw(hw); + if (err) { + RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, + ("Can't register mac80211 hw\n")); + return; + } else { + rtlpriv->mac80211.mac80211_registered = 1; + } + rtlpci->irq_alloc = 1; + set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); + + /*init rfkill */ + rtl_init_rfkill(hw); +} + static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); - const struct firmware *firmware; - struct rt_firmware *pfirmware = NULL; int err = 0; u16 earlyrxthreshold = 7; @@ -192,27 +235,19 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) return 1; } + rtlpriv->max_fw_size = sizeof(struct rt_firmware); + pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" "Loading firmware %s\n", rtlpriv->cfg->fw_name); /* request fw */ - err = request_firmware(&firmware, rtlpriv->cfg->fw_name, - rtlpriv->io.dev); + err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name, + rtlpriv->io.dev, GFP_KERNEL, hw, + rtl92se_fw_cb); if (err) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Failed to request firmware!\n")); return 1; } - if (firmware->size > sizeof(struct rt_firmware)) { - RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, - ("Firmware is too big!\n")); - release_firmware(firmware); - return 1; - } - - pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; - memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); - pfirmware->sz_fw_tmpbufferlen = firmware->size; - release_firmware(firmware); return err; } diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index e956fa7..fbbfaba 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -29,8 +29,8 @@ #include #include -#include "core.h" #include "wifi.h" +#include "core.h" #include "usb.h" #include "base.h" #include "ps.h" @@ -520,12 +520,14 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, u8 *pdata; uskb = dev_alloc_skb(skb->len + 128); - memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, - sizeof(rx_status)); - pdata = (u8 *)skb_put(uskb, skb->len); - memcpy(pdata, skb->data, skb->len); + if (uskb) { /* drop packet on allocation failure */ + memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status, + sizeof(rx_status)); + pdata = (u8 *)skb_put(uskb, skb->len); + memcpy(pdata, skb->data, skb->len); + ieee80211_rx_irqsafe(hw, uskb); + } dev_kfree_skb_any(skb); - ieee80211_rx_irqsafe(hw, uskb); } else { dev_kfree_skb_any(skb); } @@ -665,15 +667,17 @@ static int rtl_usb_start(struct ieee80211_hw *hw) struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); err = rtlpriv->cfg->ops->hw_init(hw); - rtl_init_rx_config(hw); + if (!err) { + rtl_init_rx_config(hw); - /* Enable software */ - SET_USB_START(rtlusb); - /* should after adapter start and interrupt enable. */ - set_hal_start(rtlhal); + /* Enable software */ + SET_USB_START(rtlusb); + /* should after adapter start and interrupt enable. */ + set_hal_start(rtlhal); - /* Start bulk IN */ - _rtl_usb_receive(hw); + /* Start bulk IN */ + _rtl_usb_receive(hw); + } return err; } @@ -950,6 +954,7 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, return -ENOMEM; } rtlpriv = hw->priv; + init_completion(&rtlpriv->firmware_loading_complete); SET_IEEE80211_DEV(hw, &intf->dev); udev = interface_to_usbdev(intf); usb_get_dev(udev); @@ -984,24 +989,12 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, goto error_out; } - /*init rfkill */ - /* rtl_init_rfkill(hw); */ - - err = ieee80211_register_hw(hw); - if (err) { - RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, - ("Can't register mac80211 hw.\n")); - goto error_out; - } else { - rtlpriv->mac80211.mac80211_registered = 1; - } - set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); return 0; error_out: rtl_deinit_core(hw); _rtl_usb_io_handler_release(hw); - ieee80211_free_hw(hw); usb_put_dev(udev); + complete(&rtlpriv->firmware_loading_complete); return -ENODEV; } EXPORT_SYMBOL(rtl_usb_probe); @@ -1015,6 +1008,9 @@ void rtl_usb_disconnect(struct usb_interface *intf) if (unlikely(!rtlpriv)) return; + + /* just in case driver is removed before firmware callback */ + wait_for_completion(&rtlpriv->firmware_loading_complete); /*ieee80211_unregister_hw will call ops_stop */ if (rtlmac->mac80211_registered == 1) { ieee80211_unregister_hw(hw); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index cdaf142..cfd8d1c 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "debug.h" #define RF_CHANGE_BY_INIT 0 @@ -1045,7 +1046,6 @@ struct rtl_hal { u16 fw_subversion; bool h2c_setinprogress; u8 last_hmeboxnum; - bool fw_ready; /*Reserve page start offset except beacon in TxQ. */ u8 fw_rsvdpage_startoffset; u8 h2c_txcmd_seq; @@ -1591,6 +1591,7 @@ struct rtl_debug { }; struct rtl_priv { + struct completion firmware_loading_complete; struct rtl_locks locks; struct rtl_works works; struct rtl_mac mac80211; @@ -1612,6 +1613,7 @@ struct rtl_priv { struct rtl_rate_priv *rate_priv; struct rtl_debug dbg; + int max_fw_size; /* *hal_cfg : for diff cards diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 24f049e..2275162 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) int pos; u32 reg32; - if (aspm_disabled) - return 0; - /* * Some functions in a slot might not all be PCIe functions, * very strange. Disable ASPM for the whole slot @@ -511,6 +508,16 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) pos = pci_pcie_cap(child); if (!pos) return -EINVAL; + + /* + * If ASPM is disabled then we're not going to change + * the BIOS state. It's safe to continue even if it's a + * pre-1.1 device + */ + + if (aspm_disabled) + continue; + /* * Disable ASPM for pre-1.1 PCIe device, we follow MS to use * RBER bit to determine if a function is 1.1 version device diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8a1c031..565742b 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -445,6 +445,11 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) if (rtc->uie_rtctimer.enabled == enabled) goto out; + if (rtc->uie_unsupported) { + err = -EINVAL; + goto out; + } + if (enabled) { struct rtc_time tm; ktime_t now, onesec; @@ -763,6 +768,14 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) return 0; } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ + if (!rtc->ops || !rtc->ops->alarm_irq_enable) + return; + + rtc->ops->alarm_irq_enable(rtc->dev.parent, false); +} + /** * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue * @rtc rtc device @@ -784,8 +797,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) struct rtc_wkalrm alarm; int err; next = timerqueue_getnext(&rtc->timerqueue); - if (!next) + if (!next) { + rtc_alarm_disable(rtc); return; + } alarm.time = rtc_ktime_to_tm(next->expires); alarm.enabled = 1; err = __rtc_set_alarm(rtc, &alarm); @@ -847,7 +862,8 @@ again: err = __rtc_set_alarm(rtc, &alarm); if (err == -ETIME) goto again; - } + } else + rtc_alarm_disable(rtc); mutex_unlock(&rtc->ops_lock); } diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 9d3cacc..613447a 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -360,6 +360,8 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op) &mpc5200_rtc_ops, THIS_MODULE); } + rtc->rtc->uie_unsupported = 1; + if (IS_ERR(rtc->rtc)) { err = PTR_ERR(rtc->rtc); goto out_free_irq; diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index cfd4914..e3e3c7d 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1941,7 +1941,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) switch (nlh->nlmsg_type) { case ISCSI_UEVENT_CREATE_SESSION: err = iscsi_if_create_session(priv, ep, ev, - NETLINK_CREDS(skb)->pid, + NETLINK_CB(skb).pid, ev->u.c_session.initial_cmdsn, ev->u.c_session.cmds_max, ev->u.c_session.queue_depth); @@ -1954,7 +1954,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) } err = iscsi_if_create_session(priv, ep, ev, - NETLINK_CREDS(skb)->pid, + NETLINK_CB(skb).pid, ev->u.c_bound_session.initial_cmdsn, ev->u.c_bound_session.cmds_max, ev->u.c_bound_session.queue_depth); diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c index efc7dc1..5cd2309 100644 --- a/drivers/staging/android/lowmemorykiller.c +++ b/drivers/staging/android/lowmemorykiller.c @@ -73,10 +73,10 @@ static int task_notify_func(struct notifier_block *self, unsigned long val, void *data) { struct task_struct *task = data; - if (task == lowmem_deathpending) { + + if (task == lowmem_deathpending) lowmem_deathpending = NULL; - task_handoff_unregister(&task_nb); - } + return NOTIFY_OK; } @@ -174,14 +174,12 @@ static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc) selected->pid, selected->comm, selected_oom_adj, selected_tasksize); /* - * If CONFIG_PROFILING is off, then task_handoff_register() - * is a nop. In that case we don't want to stall the killer - * by setting lowmem_deathpending. + * If CONFIG_PROFILING is off, then we don't want to stall + * the killer by setting lowmem_deathpending. */ #ifdef CONFIG_PROFILING lowmem_deathpending = selected; lowmem_deathpending_timeout = jiffies + HZ; - task_handoff_register(&task_nb); #endif force_sig(SIGKILL, selected); rem -= selected_tasksize; @@ -199,6 +197,7 @@ static struct shrinker lowmem_shrinker = { static int __init lowmem_init(void) { + task_handoff_register(&task_nb); register_shrinker(&lowmem_shrinker); return 0; } @@ -206,6 +205,7 @@ static int __init lowmem_init(void) static void __exit lowmem_exit(void) { unregister_shrinker(&lowmem_shrinker); + task_handoff_unregister(&task_nb); } module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR); diff --git a/drivers/staging/media/as102/as102_fw.h b/drivers/staging/media/as102/as102_fw.h index bd21f05..4bfc684 100644 --- a/drivers/staging/media/as102/as102_fw.h +++ b/drivers/staging/media/as102/as102_fw.h @@ -29,7 +29,7 @@ struct as10x_fw_pkt_t { union { unsigned char request[2]; unsigned char length[2]; - } u; + } __packed u; struct as10x_raw_fw_pkt raw; } __packed; diff --git a/drivers/staging/media/as102/as10x_cmd.h b/drivers/staging/media/as102/as10x_cmd.h index 4ea249e..e21ec6c 100644 --- a/drivers/staging/media/as102/as10x_cmd.h +++ b/drivers/staging/media/as102/as10x_cmd.h @@ -99,14 +99,14 @@ union as10x_turn_on { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_turn_off { @@ -114,14 +114,14 @@ union as10x_turn_off { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t err; - } rsp; + } __packed rsp; } __packed; union as10x_set_tune { @@ -131,14 +131,14 @@ union as10x_set_tune { uint16_t proc_id; /* tune params */ struct as10x_tune_args args; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* response error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_get_tune_status { @@ -146,7 +146,7 @@ union as10x_get_tune_status { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -155,7 +155,7 @@ union as10x_get_tune_status { uint8_t error; /* tune status */ struct as10x_tune_status sts; - } rsp; + } __packed rsp; } __packed; union as10x_get_tps { @@ -163,7 +163,7 @@ union as10x_get_tps { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -172,7 +172,7 @@ union as10x_get_tps { uint8_t error; /* tps details */ struct as10x_tps tps; - } rsp; + } __packed rsp; } __packed; union as10x_common { @@ -180,14 +180,14 @@ union as10x_common { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* response error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_add_pid_filter { @@ -201,7 +201,7 @@ union as10x_add_pid_filter { uint8_t stream_type; /* PID index in filter table */ uint8_t idx; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -210,7 +210,7 @@ union as10x_add_pid_filter { uint8_t error; /* Filter id */ uint8_t filter_id; - } rsp; + } __packed rsp; } __packed; union as10x_del_pid_filter { @@ -220,14 +220,14 @@ union as10x_del_pid_filter { uint16_t proc_id; /* PID to remove */ uint16_t pid; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* response error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_start_streaming { @@ -235,14 +235,14 @@ union as10x_start_streaming { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_stop_streaming { @@ -250,14 +250,14 @@ union as10x_stop_streaming { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_get_demod_stats { @@ -265,7 +265,7 @@ union as10x_get_demod_stats { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -274,7 +274,7 @@ union as10x_get_demod_stats { uint8_t error; /* demod stats */ struct as10x_demod_stats stats; - } rsp; + } __packed rsp; } __packed; union as10x_get_impulse_resp { @@ -282,7 +282,7 @@ union as10x_get_impulse_resp { struct { /* request identifier */ uint16_t proc_id; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -291,7 +291,7 @@ union as10x_get_impulse_resp { uint8_t error; /* impulse response ready */ uint8_t is_ready; - } rsp; + } __packed rsp; } __packed; union as10x_fw_context { @@ -305,7 +305,7 @@ union as10x_fw_context { uint16_t tag; /* context request type */ uint16_t type; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -316,7 +316,7 @@ union as10x_fw_context { uint16_t type; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_set_register { @@ -328,14 +328,14 @@ union as10x_set_register { struct as10x_register_addr reg_addr; /* register content */ struct as10x_register_value reg_val; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; union as10x_get_register { @@ -345,7 +345,7 @@ union as10x_get_register { uint16_t proc_id; /* register description */ struct as10x_register_addr reg_addr; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -354,7 +354,7 @@ union as10x_get_register { uint8_t error; /* register content */ struct as10x_register_value reg_val; - } rsp; + } __packed rsp; } __packed; union as10x_cfg_change_mode { @@ -364,14 +364,14 @@ union as10x_cfg_change_mode { uint16_t proc_id; /* mode */ uint8_t mode; - } req; + } __packed req; /* response */ struct { /* response identifier */ uint16_t proc_id; /* error */ uint8_t error; - } rsp; + } __packed rsp; } __packed; struct as10x_cmd_header_t { @@ -394,7 +394,7 @@ union as10x_dump_memory { struct as10x_register_addr reg_addr; /* nb blocks to read */ uint16_t num_blocks; - } req; + } __packed req; /* response */ struct { /* response identifier */ @@ -408,8 +408,8 @@ union as10x_dump_memory { uint8_t data8[DUMP_BLOCK_SIZE]; uint16_t data16[DUMP_BLOCK_SIZE / sizeof(uint16_t)]; uint32_t data32[DUMP_BLOCK_SIZE / sizeof(uint32_t)]; - } u; - } rsp; + } __packed u; + } __packed rsp; } __packed; union as10x_dumplog_memory { @@ -418,7 +418,7 @@ union as10x_dumplog_memory { uint16_t proc_id; /* dump memory type request */ uint8_t dump_req; - } req; + } __packed req; struct { /* request identifier */ uint16_t proc_id; @@ -428,7 +428,7 @@ union as10x_dumplog_memory { uint8_t dump_rsp; /* dump data */ uint8_t data[DUMP_BLOCK_SIZE]; - } rsp; + } __packed rsp; } __packed; union as10x_raw_data { @@ -437,14 +437,14 @@ union as10x_raw_data { uint16_t proc_id; uint8_t data[64 - sizeof(struct as10x_cmd_header_t) - 2 /* proc_id */]; - } req; + } __packed req; /* response */ struct { uint16_t proc_id; uint8_t error; uint8_t data[64 - sizeof(struct as10x_cmd_header_t) - 2 /* proc_id */ - 1 /* rc */]; - } rsp; + } __packed rsp; } __packed; struct as10x_cmd_t { @@ -469,7 +469,7 @@ struct as10x_cmd_t { union as10x_dump_memory dump_memory; union as10x_dumplog_memory dumplog_memory; union as10x_raw_data raw_data; - } body; + } __packed body; } __packed; struct as10x_token_cmd_t { diff --git a/drivers/staging/media/as102/as10x_types.h b/drivers/staging/media/as102/as10x_types.h index fde8140..af26e05 100644 --- a/drivers/staging/media/as102/as10x_types.h +++ b/drivers/staging/media/as102/as10x_types.h @@ -181,7 +181,7 @@ struct as10x_register_value { uint8_t value8; /* 8 bit value */ uint16_t value16; /* 16 bit value */ uint32_t value32; /* 32 bit value */ - } u; + } __packed u; } __packed; struct as10x_register_addr { diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 63800ba..e31949c 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -164,9 +164,9 @@ int cvm_oct_phy_setup_device(struct net_device *dev) int phy_addr = cvmx_helper_board_get_mii_address(priv->port); if (phy_addr != -1) { - char phy_id[20]; + char phy_id[MII_BUS_ID_SIZE + 3]; - snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr); + snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "mdio-octeon-0", phy_addr); priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0, PHY_INTERFACE_MODE_GMII); diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig index ea37473..6a43312 100644 --- a/drivers/staging/rtl8712/Kconfig +++ b/drivers/staging/rtl8712/Kconfig @@ -9,13 +9,6 @@ config R8712U This option adds the Realtek RTL8712 USB device such as the D-Link DWA-130. If built as a module, it will be called r8712u. -config R8712_AP - bool "Realtek RTL8712U AP code" - depends on R8712U - default N - ---help--- - This option allows the Realtek RTL8712 USB device to be an Access Point. - config R8712_TX_AGGR bool "Realtek RTL8712U Transmit Aggregation code" depends on R8712U && BROKEN diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 98a3d68..fb11743 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -476,8 +476,6 @@ static int netdev_close(struct net_device *pnetdev) r8712_free_assoc_resources(padapter); /*s2-4.*/ r8712_free_network_queue(padapter); - /* The interface is no longer Up: */ - padapter->bup = false; release_firmware(padapter->fw); /* never exit with a firmware callback pending */ wait_for_completion(&padapter->rtl8712_fw_ready); diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c index 507584b8..ef35bc2 100644 --- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c +++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c @@ -2380,13 +2380,7 @@ static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev) tmp_qual = padapter->recvpriv.signal; tmp_noise = padapter->recvpriv.noise; piwstats->qual.level = tmp_level; - /*piwstats->qual.qual = tmp_qual; - * The NetworkManager of Fedora 10, 13 will use the link - * quality for its display. - * So, use the fw_rssi on link quality variable because - * fw_rssi will be updated per 2 seconds. - */ - piwstats->qual.qual = tmp_level; + piwstats->qual.qual = tmp_qual; piwstats->qual.noise = tmp_noise; } piwstats->qual.updated = IW_QUAL_ALL_UPDATED; diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c index 81bde80..1247b3d 100644 --- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c +++ b/drivers/staging/rtl8712/rtl871x_sta_mgt.c @@ -42,10 +42,8 @@ static void _init_stainfo(struct sta_info *psta) _init_listhead(&psta->hash_list); _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv); _r8712_init_sta_recv_priv(&psta->sta_recvpriv); -#ifdef CONFIG_R8712_AP _init_listhead(&psta->asoc_list); _init_listhead(&psta->auth_list); -#endif } u32 _r8712_init_sta_priv(struct sta_priv *pstapriv) @@ -72,10 +70,8 @@ u32 _r8712_init_sta_priv(struct sta_priv *pstapriv) get_list_head(&pstapriv->free_sta_queue)); psta++; } -#ifdef CONFIG_R8712_AP _init_listhead(&pstapriv->asoc_list); _init_listhead(&pstapriv->auth_list); -#endif return _SUCCESS; } diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h index 48d6a14..f8016e9 100644 --- a/drivers/staging/rtl8712/sta_info.h +++ b/drivers/staging/rtl8712/sta_info.h @@ -90,7 +90,6 @@ struct sta_info { * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO * sta_info: (AP & STA) CAP/INFO */ -#ifdef CONFIG_R8712_AP struct list_head asoc_list; struct list_head auth_list; unsigned int expire_to; @@ -98,7 +97,6 @@ struct sta_info { unsigned int authalg; unsigned char chg_txt[128]; unsigned int tx_ra_bitmap; -#endif }; struct sta_priv { @@ -111,13 +109,11 @@ struct sta_priv { struct __queue sleep_q; struct __queue wakeup_q; struct _adapter *padapter; -#ifdef CONFIG_R8712_AP struct list_head asoc_list; struct list_head auth_list; unsigned int auth_to; /* sec, time to expire in authenticating. */ unsigned int assoc_to; /* sec, time to expire before associating. */ unsigned int expire_to; /* sec , time to expire after associated. */ -#endif }; static inline u32 wifi_mac_hash(u8 *mac) diff --git a/drivers/staging/vme/devices/vme_pio2.h b/drivers/staging/vme/devices/vme_pio2.h index 3c59313..72d9ce0 100644 --- a/drivers/staging/vme/devices/vme_pio2.h +++ b/drivers/staging/vme/devices/vme_pio2.h @@ -243,7 +243,7 @@ struct pio2_card { int pio2_cntr_reset(struct pio2_card *); int pio2_gpio_reset(struct pio2_card *); -int __init pio2_gpio_init(struct pio2_card *); -void __exit pio2_gpio_exit(struct pio2_card *); +int __devinit pio2_gpio_init(struct pio2_card *); +void pio2_gpio_exit(struct pio2_card *); #endif /* _VME_PIO2_H_ */ diff --git a/drivers/staging/vme/devices/vme_pio2_gpio.c b/drivers/staging/vme/devices/vme_pio2_gpio.c index dc837de..8584849 100644 --- a/drivers/staging/vme/devices/vme_pio2_gpio.c +++ b/drivers/staging/vme/devices/vme_pio2_gpio.c @@ -187,7 +187,7 @@ int pio2_gpio_reset(struct pio2_card *card) return 0; } -int __init pio2_gpio_init(struct pio2_card *card) +int __devinit pio2_gpio_init(struct pio2_card *card) { int retval = 0; char *label; @@ -220,7 +220,7 @@ int __init pio2_gpio_init(struct pio2_card *card) return retval; }; -void __exit pio2_gpio_exit(struct pio2_card *card) +void pio2_gpio_exit(struct pio2_card *card) { const char *label = card->gc.label; diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index ef7c52b..dce04be 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -299,10 +299,12 @@ static void zbud_free_and_delist(struct zbud_hdr *zh) struct zbud_page *zbpg = container_of(zh, struct zbud_page, buddy[budnum]); + spin_lock(&zbud_budlists_spinlock); spin_lock(&zbpg->lock); if (list_empty(&zbpg->bud_list)) { /* ignore zombie page... see zbud_evict_pages() */ spin_unlock(&zbpg->lock); + spin_unlock(&zbud_budlists_spinlock); return; } size = zbud_free(zh); @@ -310,7 +312,6 @@ static void zbud_free_and_delist(struct zbud_hdr *zh) zh_other = &zbpg->buddy[(budnum == 0) ? 1 : 0]; if (zh_other->size == 0) { /* was unbuddied: unlist and free */ chunks = zbud_size_to_chunks(size) ; - spin_lock(&zbud_budlists_spinlock); BUG_ON(list_empty(&zbud_unbuddied[chunks].list)); list_del_init(&zbpg->bud_list); zbud_unbuddied[chunks].count--; @@ -318,7 +319,6 @@ static void zbud_free_and_delist(struct zbud_hdr *zh) zbud_free_raw_page(zbpg); } else { /* was buddied: move remaining buddy to unbuddied list */ chunks = zbud_size_to_chunks(zh_other->size) ; - spin_lock(&zbud_budlists_spinlock); list_del_init(&zbpg->bud_list); zcache_zbud_buddied_count--; list_add_tail(&zbpg->bud_list, &zbud_unbuddied[chunks].list); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 501b27c..97c74ee 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -780,7 +780,7 @@ static int iscsit_alloc_buffs(struct iscsi_cmd *cmd) struct scatterlist *sgl; u32 length = cmd->se_cmd.data_length; int nents = DIV_ROUND_UP(length, PAGE_SIZE); - int i = 0, ret; + int i = 0, j = 0, ret; /* * If no SCSI payload is present, allocate the default iovecs used for * iSCSI PDU Header @@ -821,17 +821,15 @@ static int iscsit_alloc_buffs(struct iscsi_cmd *cmd) */ ret = iscsit_allocate_iovecs(cmd); if (ret < 0) - goto page_alloc_failed; + return -ENOMEM; return 0; page_alloc_failed: - while (i >= 0) { - __free_page(sg_page(&sgl[i])); - i--; - } - kfree(cmd->t_mem_sg); - cmd->t_mem_sg = NULL; + while (j < i) + __free_page(sg_page(&sgl[j++])); + + kfree(sgl); return -ENOMEM; } diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 6b35b37..dcef63b 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -812,9 +812,6 @@ static struct se_node_acl *lio_target_make_nodeacl( if (!se_nacl_new) return ERR_PTR(-ENOMEM); - acl = container_of(se_nacl_new, struct iscsi_node_acl, - se_node_acl); - cmdsn_depth = ISCSI_TPG_ATTRIB(tpg)->default_cmdsn_depth; /* * se_nacl_new may be released by core_tpg_add_initiator_node_acl() @@ -825,7 +822,8 @@ static struct se_node_acl *lio_target_make_nodeacl( if (IS_ERR(se_nacl)) return se_nacl; - stats_cg = &acl->se_node_acl.acl_fabric_stat_group; + acl = container_of(se_nacl, struct iscsi_node_acl, se_node_acl); + stats_cg = &se_nacl->acl_fabric_stat_group; stats_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index c47ff7f..92573c9 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -855,6 +855,9 @@ static int tcm_loop_queue_data_in(struct se_cmd *se_cmd) sc->result = SAM_STAT_GOOD; set_host_byte(sc, DID_OK); + if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) || + (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)) + scsi_set_resid(sc, se_cmd->residual_count); sc->scsi_done(sc); return 0; } @@ -880,6 +883,9 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd) sc->result = se_cmd->scsi_status; set_host_byte(sc, DID_OK); + if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) || + (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT)) + scsi_set_resid(sc, se_cmd->residual_count); sc->scsi_done(sc); return 0; } diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 01a2691..c7746a3 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -267,8 +268,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) * changed. */ if (primary) { - tg_pt_id = ((ptr[2] << 8) & 0xff); - tg_pt_id |= (ptr[3] & 0xff); + tg_pt_id = get_unaligned_be16(ptr + 2); /* * Locate the matching target port group ID from * the global tg_pt_gp list @@ -312,8 +312,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) * the Target Port in question for the the incoming * SET_TARGET_PORT_GROUPS op. */ - rtpi = ((ptr[2] << 8) & 0xff); - rtpi |= (ptr[3] & 0xff); + rtpi = get_unaligned_be16(ptr + 2); /* * Locate the matching relative target port identifer * for the struct se_device storage object. diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index f3d71fa..4f65b25 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -66,32 +66,15 @@ target_fill_alua_data(struct se_port *port, unsigned char *buf) } static int -target_emulate_inquiry_std(struct se_cmd *cmd) +target_emulate_inquiry_std(struct se_cmd *cmd, char *buf) { struct se_lun *lun = cmd->se_lun; struct se_device *dev = cmd->se_dev; - struct se_portal_group *tpg = lun->lun_sep->sep_tpg; - unsigned char *buf; - /* - * Make sure we at least have 6 bytes of INQUIRY response - * payload going back for EVPD=0 - */ - if (cmd->data_length < 6) { - pr_err("SCSI Inquiry payload length: %u" - " too small for EVPD=0\n", cmd->data_length); - return -EINVAL; - } + /* Set RMB (removable media) for tape devices */ + if (dev->transport->get_device_type(dev) == TYPE_TAPE) + buf[1] = 0x80; - buf = transport_kmap_data_sg(cmd); - - if (dev == tpg->tpg_virt_lun0.lun_se_dev) { - buf[0] = 0x3f; /* Not connected */ - } else { - buf[0] = dev->transport->get_device_type(dev); - if (buf[0] == TYPE_TAPE) - buf[1] = 0x80; - } buf[2] = dev->transport->get_device_rev(dev); /* @@ -112,29 +95,13 @@ target_emulate_inquiry_std(struct se_cmd *cmd) if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) target_fill_alua_data(lun->lun_sep, buf); - if (cmd->data_length < 8) { - buf[4] = 1; /* Set additional length to 1 */ - goto out; - } - - buf[7] = 0x32; /* Sync=1 and CmdQue=1 */ - - /* - * Do not include vendor, product, reversion info in INQUIRY - * response payload for cdbs with a small allocation length. - */ - if (cmd->data_length < 36) { - buf[4] = 3; /* Set additional length to 3 */ - goto out; - } + buf[7] = 0x2; /* CmdQue=1 */ snprintf(&buf[8], 8, "LIO-ORG"); snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model); snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision); buf[4] = 31; /* Set additional length to 31 */ -out: - transport_kunmap_data_sg(cmd); return 0; } @@ -152,12 +119,6 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial); unit_serial_len++; /* For NULL Terminator */ - if (((len + 4) + unit_serial_len) > cmd->data_length) { - len += unit_serial_len; - buf[2] = ((len >> 8) & 0xff); - buf[3] = (len & 0xff); - return 0; - } len += sprintf(&buf[4], "%s", dev->se_sub_dev->t10_wwn.unit_serial); len++; /* Extra Byte for NULL Terminator */ @@ -229,9 +190,6 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf) if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL)) goto check_t10_vend_desc; - if (off + 20 > cmd->data_length) - goto check_t10_vend_desc; - /* CODE SET == Binary */ buf[off++] = 0x1; @@ -283,12 +241,6 @@ check_t10_vend_desc: strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]); unit_serial_len++; /* For NULL Terminator */ - if ((len + (id_len + 4) + - (prod_len + unit_serial_len)) > - cmd->data_length) { - len += (prod_len + unit_serial_len); - goto check_port; - } id_len += sprintf(&buf[off+12], "%s:%s", prod, &dev->se_sub_dev->t10_wwn.unit_serial[0]); } @@ -306,7 +258,6 @@ check_t10_vend_desc: /* * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD */ -check_port: port = lun->lun_sep; if (port) { struct t10_alua_lu_gp *lu_gp; @@ -323,10 +274,6 @@ check_port: * Get the PROTOCOL IDENTIFIER as defined by spc4r17 * section 7.5.1 Table 362 */ - if (((len + 4) + 8) > cmd->data_length) { - len += 8; - goto check_tpgi; - } buf[off] = (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4); buf[off++] |= 0x1; /* CODE SET == Binary */ @@ -350,15 +297,10 @@ check_port: * Get the PROTOCOL IDENTIFIER as defined by spc4r17 * section 7.5.1 Table 362 */ -check_tpgi: if (dev->se_sub_dev->t10_alua.alua_type != SPC3_ALUA_EMULATED) goto check_scsi_name; - if (((len + 4) + 8) > cmd->data_length) { - len += 8; - goto check_lu_gp; - } tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem; if (!tg_pt_gp_mem) goto check_lu_gp; @@ -391,10 +333,6 @@ check_tpgi: * section 7.7.3.8 */ check_lu_gp: - if (((len + 4) + 8) > cmd->data_length) { - len += 8; - goto check_scsi_name; - } lu_gp_mem = dev->dev_alua_lu_gp_mem; if (!lu_gp_mem) goto check_scsi_name; @@ -435,10 +373,6 @@ check_scsi_name: /* Header size + Designation descriptor */ scsi_name_len += 4; - if (((len + 4) + scsi_name_len) > cmd->data_length) { - len += scsi_name_len; - goto set_len; - } buf[off] = (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4); buf[off++] |= 0x3; /* CODE SET == UTF-8 */ @@ -474,7 +408,6 @@ check_scsi_name: /* Header size + Designation descriptor */ len += (scsi_name_len + 4); } -set_len: buf[2] = ((len >> 8) & 0xff); buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */ return 0; @@ -484,9 +417,6 @@ set_len: static int target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf) { - if (cmd->data_length < 60) - return 0; - buf[3] = 0x3c; /* Set HEADSUP, ORDSUP, SIMPSUP */ buf[5] = 0x07; @@ -512,20 +442,6 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) have_tp = 1; - if (cmd->data_length < (0x10 + 4)) { - pr_debug("Received data_length: %u" - " too small for EVPD 0xb0\n", - cmd->data_length); - return -EINVAL; - } - - if (have_tp && cmd->data_length < (0x3c + 4)) { - pr_debug("Received data_length: %u" - " too small for TPE=1 EVPD 0xb0\n", - cmd->data_length); - have_tp = 0; - } - buf[0] = dev->transport->get_device_type(dev); buf[3] = have_tp ? 0x3c : 0x10; @@ -548,10 +464,9 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf) put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]); /* - * Exit now if we don't support TP or the initiator sent a too - * short buffer. + * Exit now if we don't support TP. */ - if (!have_tp || cmd->data_length < (0x3c + 4)) + if (!have_tp) return 0; /* @@ -589,10 +504,7 @@ target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf) buf[0] = dev->transport->get_device_type(dev); buf[3] = 0x3c; - - if (cmd->data_length >= 5 && - dev->se_sub_dev->se_dev_attrib.is_nonrot) - buf[5] = 1; + buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0; return 0; } @@ -671,8 +583,6 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) { int p; - if (cmd->data_length < 8) - return 0; /* * Only report the INQUIRY EVPD=1 pages after a valid NAA * Registered Extended LUN WWN has been set via ConfigFS @@ -681,8 +591,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) if (cmd->se_dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL) { buf[3] = ARRAY_SIZE(evpd_handlers); - for (p = 0; p < min_t(int, ARRAY_SIZE(evpd_handlers), - cmd->data_length - 4); ++p) + for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) buf[p + 4] = evpd_handlers[p].page; } @@ -693,45 +602,54 @@ int target_emulate_inquiry(struct se_task *task) { struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; - unsigned char *buf; + struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg; + unsigned char *buf, *map_buf; unsigned char *cdb = cmd->t_task_cdb; int p, ret; + map_buf = transport_kmap_data_sg(cmd); + /* + * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we + * know we actually allocated a full page. Otherwise, if the + * data buffer is too small, allocate a temporary buffer so we + * don't have to worry about overruns in all our INQUIRY + * emulation handling. + */ + if (cmd->data_length < SE_INQUIRY_BUF && + (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { + buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL); + if (!buf) { + transport_kunmap_data_sg(cmd); + cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + return -ENOMEM; + } + } else { + buf = map_buf; + } + + if (dev == tpg->tpg_virt_lun0.lun_se_dev) + buf[0] = 0x3f; /* Not connected */ + else + buf[0] = dev->transport->get_device_type(dev); + if (!(cdb[1] & 0x1)) { if (cdb[2]) { pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", cdb[2]); cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; + ret = -EINVAL; + goto out; } - ret = target_emulate_inquiry_std(cmd); + ret = target_emulate_inquiry_std(cmd, buf); goto out; } - /* - * Make sure we at least have 4 bytes of INQUIRY response - * payload for 0x00 going back for EVPD=1. Note that 0x80 - * and 0x83 will check for enough payload data length and - * jump to set_len: label when there is not enough inquiry EVPD - * payload length left for the next outgoing EVPD metadata - */ - if (cmd->data_length < 4) { - pr_err("SCSI Inquiry payload length: %u" - " too small for EVPD=1\n", cmd->data_length); - cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; - return -EINVAL; - } - - buf = transport_kmap_data_sg(cmd); - - buf[0] = dev->transport->get_device_type(dev); - for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) { if (cdb[2] == evpd_handlers[p].page) { buf[1] = cdb[2]; ret = evpd_handlers[p].emulate(cmd, buf); - goto out_unmap; + goto out; } } @@ -739,9 +657,13 @@ int target_emulate_inquiry(struct se_task *task) cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = -EINVAL; -out_unmap: - transport_kunmap_data_sg(cmd); out: + if (buf != map_buf) { + memcpy(map_buf, buf, cmd->data_length); + kfree(buf); + } + transport_kunmap_data_sg(cmd); + if (!ret) { task->task_scsi_status = GOOD; transport_complete_task(task, 1); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index edbcabb..ce6400d 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -657,7 +657,9 @@ int target_report_luns(struct se_task *se_task) unsigned char *buf; u32 cdb_offset = 0, lun_count = 0, offset = 8, i; - buf = (unsigned char *) transport_kmap_data_sg(se_cmd); + buf = transport_kmap_data_sg(se_cmd); + if (!buf) + return -ENOMEM; /* * If no struct se_session pointer is present, this struct se_cmd is @@ -695,12 +697,12 @@ int target_report_luns(struct se_task *se_task) * See SPC3 r07, page 159. */ done: - transport_kunmap_data_sg(se_cmd); lun_count *= 8; buf[0] = ((lun_count >> 24) & 0xff); buf[1] = ((lun_count >> 16) & 0xff); buf[2] = ((lun_count >> 8) & 0xff); buf[3] = (lun_count & 0xff); + transport_kunmap_data_sg(se_cmd); se_task->task_scsi_status = GOOD; transport_complete_task(se_task, 1); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index 9e7e26c..ced9e8a 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -325,10 +325,12 @@ static void ft_send_resp_status(struct fc_lport *lport, fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0); sp = fr_seq(fp); - if (sp) + if (sp) { lport->tt.seq_send(lport, sp, fp); - else + lport->tt.exch_done(sp); + } else { lport->tt.frame_send(lport, fp); + } } /* diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c index d15a071..0174d2d 100644 --- a/drivers/tty/moxa.c +++ b/drivers/tty/moxa.c @@ -1331,7 +1331,7 @@ static void moxa_start(struct tty_struct *tty) if (ch == NULL) return; - if (!(ch->statusflags & TXSTOPPED)) + if (!test_bit(TXSTOPPED, &ch->statusflags)) return; MoxaPortTxEnable(ch); diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index f809041..0121486 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -159,7 +159,7 @@ static void serial_omap_stop_tx(struct uart_port *port) serial_out(up, UART_IER, up->ier); } - if (!up->use_dma && pdata->set_forceidle) + if (!up->use_dma && pdata && pdata->set_forceidle) pdata->set_forceidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); @@ -298,7 +298,7 @@ static void serial_omap_start_tx(struct uart_port *port) if (!up->use_dma) { pm_runtime_get_sync(&up->pdev->dev); serial_omap_enable_ier_thri(up); - if (pdata->set_noidle) + if (pdata && pdata->set_noidle) pdata->set_noidle(up->pdev); pm_runtime_mark_last_busy(&up->pdev->dev); pm_runtime_put_autosuspend(&up->pdev->dev); @@ -1613,7 +1613,7 @@ static int serial_omap_runtime_resume(struct device *dev) struct uart_omap_port *up = dev_get_drvdata(dev); struct omap_uart_port_info *pdata = dev->platform_data; - if (up) { + if (up && pdata) { if (pdata->get_context_loss_count) { u32 loss_cnt = pdata->get_context_loss_count(dev); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 61b7fd2..9ec6d4e 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1229,17 +1229,20 @@ static void sci_dma_tx_complete(void *arg) port->icount.tx += sg_dma_len(&s->sg_tx); async_tx_ack(s->desc_tx); - s->cookie_tx = -EINVAL; s->desc_tx = NULL; if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (!uart_circ_empty(xmit)) { + s->cookie_tx = 0; schedule_work(&s->work_tx); - } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { - u16 ctrl = sci_in(port, SCSCR); - sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); + } else { + s->cookie_tx = -EINVAL; + if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { + u16 ctrl = sci_in(port, SCSCR); + sci_out(port, SCSCR, ctrl & ~SCSCR_TIE); + } } spin_unlock_irqrestore(&port->lock, flags); @@ -1501,8 +1504,10 @@ static void sci_start_tx(struct uart_port *port) } if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && - s->cookie_tx < 0) + s->cookie_tx < 0) { + s->cookie_tx = 0; schedule_work(&s->work_tx); + } #endif if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) { diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c index a0f3d6c..8308fc7 100644 --- a/drivers/tty/vt/consolemap.c +++ b/drivers/tty/vt/consolemap.c @@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) int err = 0, err1, i; struct uni_pagedir *p, *q; + /* Save original vc_unipagdir_loc in case we allocate a new one */ p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; if (p->readonly) return -EIO; @@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) err1 = con_clear_unimap(vc, NULL); if (err1) return err1; + /* + * Since refcount was > 1, con_clear_unimap() allocated a + * a new uni_pagedir for this vc. Re: p != q + */ q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc; - for (i = 0, l = 0; i < 32; i++) + + /* + * uni_pgdir is a 32*32*64 table with rows allocated + * when its first entry is added. The unicode value must + * still be incremented for empty rows. We are copying + * entries from "p" (old) to "q" (new). + */ + l = 0; /* unicode value */ + for (i = 0; i < 32; i++) if ((p1 = p->uni_pgdir[i])) for (j = 0; j < 32; j++) - if ((p2 = p1[j])) + if ((p2 = p1[j])) { for (k = 0; k < 64; k++, l++) if (p2[k] != 0xffff) { + /* + * Found one, copy entry for unicode + * l with fontpos value p2[k]. + */ err1 = con_insert_unipair(q, l, p2[k]); if (err1) { p->refcount++; *vc->vc_uni_pagedir_loc = (unsigned long)p; con_release_unimap(q); kfree(q); - return err1; + return err1; } - } - p = q; - } else if (p == dflt) + } + } else { + /* Account for row of 64 empty entries */ + l += 64; + } + else + /* Account for empty table */ + l += 32 * 64; + + /* + * Finished copying font table, set vc_uni_pagedir to new table + */ + p = q; + } else if (p == dflt) { dflt = NULL; - + } + + /* + * Insert user specified unicode pairs into new table. + */ while (ct--) { unsigned short unicode, fontpos; __get_user(unicode, &list->unicode); @@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) list++; } + /* + * Merge with fontmaps of any other virtual consoles. + */ if (con_unify_unimap(vc, p)) return err; for (i = 0; i <= 3; i++) - set_inverse_transl(vc, p, i); /* Update all inverse translations */ + set_inverse_transl(vc, p, i); /* Update inverse translations */ set_inverse_trans_unicode(vc, p); return err; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index d2b3cff..2f085fb 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -397,7 +397,7 @@ outnl: static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - int rv, cntr = 0; + int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; @@ -406,7 +406,8 @@ static ssize_t wdm_read if (rv < 0) return -ERESTARTSYS; - if (desc->length == 0) { + cntr = ACCESS_ONCE(desc->length); + if (cntr == 0) { desc->read = 0; retry: if (test_bit(WDM_DISCONNECTING, &desc->flags)) { @@ -456,26 +457,30 @@ retry: spin_unlock_irq(&desc->iuspin); goto retry; } - clear_bit(WDM_READ, &desc->flags); + cntr = desc->length; spin_unlock_irq(&desc->iuspin); } - cntr = count > desc->length ? desc->length : count; + if (cntr > count) + cntr = count; rv = copy_to_user(buffer, desc->ubuf, cntr); if (rv > 0) { rv = -EFAULT; goto err; } + spin_lock_irq(&desc->iuspin); + for (i = 0; i < desc->length - cntr; i++) desc->ubuf[i] = desc->ubuf[i + cntr]; - spin_lock_irq(&desc->iuspin); desc->length -= cntr; - spin_unlock_irq(&desc->iuspin); /* in case we had outstanding data */ if (!desc->length) clear_bit(WDM_READ, &desc->flags); + + spin_unlock_irq(&desc->iuspin); + rv = cntr; err: diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 7c9df63..73df745 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -86,7 +86,7 @@ again: id = -ENOMEM; } - return 0; + return id; } EXPORT_SYMBOL_GPL(dwc3_get_device_id); diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 064b6e2..acea57a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -440,6 +440,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->stream_capable = false; dep->desc = NULL; + dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; dep->flags = 0; @@ -485,16 +486,16 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: - strncat(dep->name, "-control", sizeof(dep->name)); + strlcat(dep->name, "-control", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_ISOC: - strncat(dep->name, "-isoc", sizeof(dep->name)); + strlcat(dep->name, "-isoc", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_BULK: - strncat(dep->name, "-bulk", sizeof(dep->name)); + strlcat(dep->name, "-bulk", sizeof(dep->name)); break; case USB_ENDPOINT_XFER_INT: - strncat(dep->name, "-int", sizeof(dep->name)); + strlcat(dep->name, "-int", sizeof(dep->name)); break; default: dev_err(dwc->dev, "invalid endpoint transfer type\n"); @@ -667,6 +668,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) { struct dwc3_request *req, *n; u32 trbs_left; + u32 max; unsigned int last_one = 0; BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); @@ -674,6 +676,13 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) /* the first request must not be queued */ trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; + /* Can't wrap around on a non-isoc EP since there's no link TRB */ + if (!usb_endpoint_xfer_isoc(dep->desc)) { + max = DWC3_TRB_NUM - (dep->free_slot & DWC3_TRB_MASK); + if (trbs_left > max) + trbs_left = max; + } + /* * if busy & slot are equal than it is either full or empty. If we are * starting to proceed requests then we are empty. Otherwise we ar @@ -1490,7 +1499,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, static void dwc3_gadget_start_isoc(struct dwc3 *dwc, struct dwc3_ep *dep, const struct dwc3_event_depevt *event) { - u32 uf; + u32 uf, mask; if (list_empty(&dep->request_list)) { dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n", @@ -1498,16 +1507,10 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc, return; } - if (event->parameters) { - u32 mask; - - mask = ~(dep->interval - 1); - uf = event->parameters & mask; - /* 4 micro frames in the future */ - uf += dep->interval * 4; - } else { - uf = 0; - } + mask = ~(dep->interval - 1); + uf = event->parameters & mask; + /* 4 micro frames in the future */ + uf += dep->interval * 4; __dwc3_gadget_kick_transfer(dep, uf, 1); } diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index c16ff55..18883bd 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -445,6 +445,7 @@ static void ep_init(struct udc_regs __iomem *regs, struct udc_ep *ep) VDBG(ep->dev, "ep-%d reset\n", ep->num); ep->desc = NULL; + ep->ep.desc = NULL; ep->ep.ops = &udc_ep_ops; INIT_LIST_HEAD(&ep->queue); diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 143a725..b1f6e43 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -558,6 +558,7 @@ static int at91_ep_disable (struct usb_ep * _ep) /* restore the endpoint's pristine config */ ep->desc = NULL; + ep->ep.desc = NULL; ep->ep.maxpacket = ep->maxpacket; /* reset fifos and endpoint */ diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e2fb6d5..5e10f65 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -659,6 +659,7 @@ static int usba_ep_disable(struct usb_ep *_ep) return -EINVAL; } ep->desc = NULL; + ep->ep.desc = NULL; list_splice_init(&ep->queue, &req_list); if (ep->can_dma) { diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 27e3137..9e89289 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2181,6 +2181,7 @@ static int ep_disable(struct usb_ep *ep) } while (mEp->dir != direction); mEp->desc = NULL; + mEp->ep.desc = NULL; spin_unlock_irqrestore(mEp->lock, flags); return retval; diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index c154064..21ab474 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -74,7 +74,7 @@ static inline struct f_gether *func_to_geth(struct usb_function *f) /* interface descriptor: */ -static struct usb_interface_descriptor subset_data_intf __initdata = { +static struct usb_interface_descriptor subset_data_intf = { .bLength = sizeof subset_data_intf, .bDescriptorType = USB_DT_INTERFACE, @@ -87,7 +87,7 @@ static struct usb_interface_descriptor subset_data_intf __initdata = { /* .iInterface = DYNAMIC */ }; -static struct usb_cdc_header_desc mdlm_header_desc __initdata = { +static struct usb_cdc_header_desc mdlm_header_desc = { .bLength = sizeof mdlm_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, @@ -95,7 +95,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = { .bcdCDC = cpu_to_le16(0x0110), }; -static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { +static struct usb_cdc_mdlm_desc mdlm_desc = { .bLength = sizeof mdlm_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_MDLM_TYPE, @@ -111,7 +111,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { * can't really use its struct. All we do here is say that we're using * the submode of "SAFE" which directly matches the CDC Subset. */ -static u8 mdlm_detail_desc[] __initdata = { +static u8 mdlm_detail_desc[] = { 6, USB_DT_CS_INTERFACE, USB_CDC_MDLM_DETAIL_TYPE, @@ -121,7 +121,7 @@ static u8 mdlm_detail_desc[] __initdata = { 0, /* network data capabilities ("raw" encapsulation) */ }; -static struct usb_cdc_ether_desc ether_desc __initdata = { +static struct usb_cdc_ether_desc ether_desc = { .bLength = sizeof ether_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_ETHERNET_TYPE, @@ -136,7 +136,7 @@ static struct usb_cdc_ether_desc ether_desc __initdata = { /* full speed support: */ -static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = { +static struct usb_endpoint_descriptor fs_subset_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -144,7 +144,7 @@ static struct usb_endpoint_descriptor fs_subset_in_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = { +static struct usb_endpoint_descriptor fs_subset_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -152,7 +152,7 @@ static struct usb_endpoint_descriptor fs_subset_out_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *fs_eth_function[] __initdata = { +static struct usb_descriptor_header *fs_eth_function[] = { (struct usb_descriptor_header *) &subset_data_intf, (struct usb_descriptor_header *) &mdlm_header_desc, (struct usb_descriptor_header *) &mdlm_desc, @@ -165,7 +165,7 @@ static struct usb_descriptor_header *fs_eth_function[] __initdata = { /* high speed support: */ -static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { +static struct usb_endpoint_descriptor hs_subset_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -173,7 +173,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { +static struct usb_endpoint_descriptor hs_subset_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -181,7 +181,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *hs_eth_function[] __initdata = { +static struct usb_descriptor_header *hs_eth_function[] = { (struct usb_descriptor_header *) &subset_data_intf, (struct usb_descriptor_header *) &mdlm_header_desc, (struct usb_descriptor_header *) &mdlm_desc, @@ -194,7 +194,7 @@ static struct usb_descriptor_header *hs_eth_function[] __initdata = { /* super speed support: */ -static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = { +static struct usb_endpoint_descriptor ss_subset_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -202,7 +202,7 @@ static struct usb_endpoint_descriptor ss_subset_in_desc __initdata = { .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = { +static struct usb_endpoint_descriptor ss_subset_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -210,7 +210,7 @@ static struct usb_endpoint_descriptor ss_subset_out_desc __initdata = { .wMaxPacketSize = cpu_to_le16(1024), }; -static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = { +static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc = { .bLength = sizeof ss_subset_bulk_comp_desc, .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, @@ -219,7 +219,7 @@ static struct usb_ss_ep_comp_descriptor ss_subset_bulk_comp_desc __initdata = { /* .bmAttributes = 0, */ }; -static struct usb_descriptor_header *ss_eth_function[] __initdata = { +static struct usb_descriptor_header *ss_eth_function[] = { (struct usb_descriptor_header *) &subset_data_intf, (struct usb_descriptor_header *) &mdlm_header_desc, (struct usb_descriptor_header *) &mdlm_desc, @@ -290,7 +290,7 @@ static void geth_disable(struct usb_function *f) /* serial function driver setup/binding */ -static int __init +static int geth_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; @@ -404,7 +404,7 @@ geth_unbind(struct usb_configuration *c, struct usb_function *f) * Caller must have called @gether_setup(). Caller is also responsible * for calling @gether_cleanup() before module unload. */ -int __init geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) { struct f_gether *geth; int status; diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index b95697c..877a2c4 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -1638,6 +1638,7 @@ static int qe_ep_disable(struct usb_ep *_ep) /* Nuke all pending requests (does flush) */ nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; ep->tx_req = NULL; qe_ep_reset(udc, ep->epnum); diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index b04712f..6b5fdf9 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -659,6 +659,7 @@ static int fsl_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); @@ -768,7 +769,7 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) * @is_last: return flag if it is the last dTD of the request * return: pointer to the built dTD */ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, - dma_addr_t *dma, int *is_last) + dma_addr_t *dma, int *is_last, gfp_t gfp_flags) { u32 swap_temp; struct ep_td_struct *dtd; @@ -777,7 +778,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, *length = min(req->req.length - req->req.actual, (unsigned)EP_MAX_LENGTH_TRANSFER); - dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma); + dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma); if (dtd == NULL) return dtd; @@ -827,7 +828,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length, } /* Generate dtd chain for a request */ -static int fsl_req_to_dtd(struct fsl_req *req) +static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags) { unsigned count; int is_last; @@ -836,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req *req) dma_addr_t dma; do { - dtd = fsl_build_dtd(req, &count, &dma, &is_last); + dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags); if (dtd == NULL) return -ENOMEM; @@ -910,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) req->req.actual = 0; req->dtd_count = 0; - spin_lock_irqsave(&udc->lock, flags); - /* build dtds and push them to device queue */ - if (!fsl_req_to_dtd(req)) { + if (!fsl_req_to_dtd(req, gfp_flags)) { + spin_lock_irqsave(&udc->lock, flags); fsl_queue_td(ep, req); } else { - spin_unlock_irqrestore(&udc->lock, flags); return -ENOMEM; } @@ -1295,7 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction) ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->mapped = 1; - if (fsl_req_to_dtd(req) == 0) + if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0) fsl_queue_td(ep, req); else return -ENOMEM; @@ -1379,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value, req->mapped = 1; /* prime the data phase */ - if ((fsl_req_to_dtd(req) == 0)) + if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0)) fsl_queue_td(ep, req); else /* no mem */ goto stall; diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 5af70fc..5977749 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -235,6 +235,7 @@ static void ep_reset(struct goku_udc_regs __iomem *regs, struct goku_ep *ep) ep->ep.maxpacket = MAX_FIFO_SIZE; ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; ep->irqs = 0; ep->dma = 0; diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index f888c3e..3493adf 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -60,9 +60,9 @@ static struct usb_device_descriptor device_desc = { /* .bDeviceClass = USB_CLASS_COMM, */ /* .bDeviceSubClass = 0, */ /* .bDeviceProtocol = 0, */ - .bDeviceClass = 0xEF, - .bDeviceSubClass = 2, - .bDeviceProtocol = 1, + .bDeviceClass = USB_CLASS_PER_INTERFACE, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index ae04266..4f18a0e 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1043,6 +1043,8 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) // FIXME don't call this with the spinlock held ... if (copy_to_user (buf, dev->req->buf, len)) retval = -EFAULT; + else + retval = len; clean_req (dev->gadget->ep0, dev->req); /* NOTE userspace can't yet choose to stall */ } diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index e2293c1..aca575a 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -487,6 +487,7 @@ static int langwell_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&dev->lock, flags); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index f97e737..168fe1f 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -608,6 +608,7 @@ static int mv_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; spin_unlock_irqrestore(&udc->lock, flags); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 576cd85..7d0835e 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -251,6 +251,7 @@ static int omap_ep_disable(struct usb_ep *_ep) spin_lock_irqsave(&ep->udc->lock, flags); ep->desc = NULL; + ep->ep.desc = NULL; nuke (ep, -ESHUTDOWN); ep->ep.maxpacket = ep->maxpacket; ep->has_dma = 0; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index a3fcaae..2d567ba 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -1493,6 +1493,7 @@ static int pch_udc_pcd_ep_disable(struct usb_ep *usbep) pch_udc_ep_disable(ep); pch_udc_disable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); ep->desc = NULL; + ep->ep.desc = NULL; INIT_LIST_HEAD(&ep->queue); spin_unlock_irqrestore(&ep->dev->lock, iflags); return 0; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index dd47063..33adf38 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -283,6 +283,7 @@ static int pxa25x_ep_disable (struct usb_ep *_ep) pxa25x_ep_fifo_flush (_ep); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 1; local_irq_restore(flags); @@ -1192,6 +1193,7 @@ static void udc_reinit(struct pxa25x_udc *dev) list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); ep->desc = NULL; + ep->ep.desc = NULL; ep->stopped = 0; INIT_LIST_HEAD (&ep->queue); ep->pio_irqs = 0; diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index df8661d..397d625 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -816,6 +816,7 @@ static int s3c_hsudc_ep_disable(struct usb_ep *_ep) s3c_hsudc_nuke_ep(hsep, -ESHUTDOWN); hsep->desc = 0; + hsep->ep.desc = NULL; hsep->stopped = 1; spin_unlock_irqrestore(&hsudc->lock, flags); @@ -1005,6 +1006,7 @@ static void s3c_hsudc_initep(struct s3c_hsudc *hsudc, hsep->ep.ops = &s3c_hsudc_ep_ops; hsep->fifo = hsudc->regs + S3C_BR(epnum); hsep->desc = 0; + hsep->ep.desc = NULL; hsep->stopped = 0; hsep->wedge = 0; diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 3f87cb9..ab9c65e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1148,6 +1148,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) dprintk(DEBUG_NORMAL, "ep_disable: %s\n", _ep->name); ep->desc = NULL; + ep->ep.desc = NULL; ep->halted = 1; s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN); @@ -1630,6 +1631,7 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) ep->dev = dev; ep->desc = NULL; + ep->ep.desc = NULL; ep->halted = 0; INIT_LIST_HEAD (&ep->queue); } diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b556a72..da487fd 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, unsigned int port_offset) { u32 portsc; + struct usb_hcd *hcd = ehci_to_hcd(ehci); + void __iomem *non_ehci = hcd->regs; portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]); portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW); @@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci, portsc |= PORT_PTS_PTW; /* fall through */ case FSL_USB2_PHY_UTMI: + /* enable UTMI PHY */ + setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN); portsc |= PORT_PTS_UTMI; break; case FSL_USB2_PHY_NONE: diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 4918062..bea5013 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -45,5 +45,6 @@ #define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */ #define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */ #define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */ +#define CTRL_UTMI_PHY_EN (1<<9) #define SNOOP_SIZE_2GB 0x1e #endif /* _EHCI_FSL_H */ diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 7916e56..ab333ac 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -94,7 +94,6 @@ struct platform_device * __devinit fsl_usb2_device_register( pdev->dev.parent = &ofdev->dev; pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; - pdev->dev.dma_mask = &pdev->archdata.dma_mask; *pdev->dev.dma_mask = *ofdev->dev.dma_mask; retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ac3d2ee..fdc2cdd 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -574,6 +574,15 @@ void musb_g_tx(struct musb *musb, u8 epnum) if (request->actual == request->length) { musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = musb_ep->desc ? next_request(musb_ep) : NULL; if (!req) { dev_dbg(musb->controller, "%s idle now\n", @@ -983,6 +992,15 @@ void musb_g_rx(struct musb *musb, u8 epnum) } #endif musb_g_giveback(musb_ep, request, 0); + /* + * In the giveback function the MUSB lock is + * released and acquired after sometime. During + * this time period the INDEX register could get + * changed by the gadget_queue function especially + * on SMP systems. Reselect the INDEX to be sure + * we are reading/modifying the right registers + */ + musb_ep_select(mbase, epnum); req = next_request(musb_ep); if (!req) diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index 7542aa9..cc72a8f 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -941,6 +941,11 @@ static int usbhsg_stop(struct usbhs_priv *priv) return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED); } +static void usbhs_mod_gadget_release(struct device *pdev) +{ + /* do nothing */ +} + int usbhs_mod_gadget_probe(struct usbhs_priv *priv) { struct usbhsg_gpriv *gpriv; @@ -989,6 +994,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) */ dev_set_name(&gpriv->gadget.dev, "gadget"); gpriv->gadget.dev.parent = dev; + gpriv->gadget.dev.release = usbhs_mod_gadget_release; gpriv->gadget.name = "renesas_usbhs_udc"; gpriv->gadget.ops = &usbhsg_gadget_ops; gpriv->gadget.max_speed = USB_SPEED_HIGH; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 08a5575..eeb03b7 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -49,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, unsigned int, unsigned int); static void cp210x_break_ctl(struct tty_struct *, int); static int cp210x_startup(struct usb_serial *); +static void cp210x_release(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); static bool debug; @@ -121,6 +122,8 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ @@ -149,6 +152,10 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); +struct cp210x_port_private { + __u8 bInterfaceNumber; +}; + static struct usb_driver cp210x_driver = { .name = "cp210x", .probe = usb_serial_probe, @@ -174,6 +181,7 @@ static struct usb_serial_driver cp210x_device = { .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_startup, + .release = cp210x_release, .dtr_rts = cp210x_dtr_rts }; @@ -261,6 +269,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); __le32 *buf; int result, i, length; @@ -276,7 +285,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, /* Issue the request, attempting to read 'size' bytes */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), request, REQTYPE_DEVICE_TO_HOST, 0x0000, - 0, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, 300); /* Convert data into an array of integers */ for (i = 0; i < length; i++) @@ -307,6 +316,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, unsigned int *data, int size) { struct usb_serial *serial = port->serial; + struct cp210x_port_private *port_priv = usb_get_serial_port_data(port); __le32 *buf; int result, i, length; @@ -328,12 +338,12 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, 0x0000, - 0, buf, size, 300); + port_priv->bInterfaceNumber, buf, size, 300); } else { result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); + port_priv->bInterfaceNumber, NULL, 0, 300); } kfree(buf); @@ -844,11 +854,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) static int cp210x_startup(struct usb_serial *serial) { + struct cp210x_port_private *port_priv; + int i; + /* cp210x buffers behave strangely unless device is reset */ usb_reset_device(serial->dev); + + for (i = 0; i < serial->num_ports; i++) { + port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL); + if (!port_priv) + return -ENOMEM; + + memset(port_priv, 0x00, sizeof(*port_priv)); + port_priv->bInterfaceNumber = + serial->interface->cur_altsetting->desc.bInterfaceNumber; + + usb_set_serial_port_data(serial->port[i], port_priv); + } + return 0; } +static void cp210x_release(struct usb_serial *serial) +{ + struct cp210x_port_private *port_priv; + int i; + + for (i = 0; i < serial->num_ports; i++) { + port_priv = usb_get_serial_port_data(serial->port[i]); + kfree(port_priv); + usb_set_serial_port_data(serial->port[i], NULL); + } +} + static int __init cp210x_init(void) { int retval; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f770415..8aa51d9 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -188,6 +188,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk }, { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) }, { USB_DEVICE(FTDI_VID, FTDI_232H_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, @@ -536,6 +537,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) }, { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) }, + { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) }, { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) }, { USB_DEVICE(OCT_VID, OCT_US101_PID) }, { USB_DEVICE(OCT_VID, OCT_DK201_PID) }, @@ -797,7 +802,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(HORNBY_VID, HORNBY_ELITE_PID) }, + { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -846,6 +851,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, + { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -868,7 +876,8 @@ static const char *ftdi_chip_name[] = { [FT232RL] = "FT232RL", [FT2232H] = "FT2232H", [FT4232H] = "FT4232H", - [FT232H] = "FT232H" + [FT232H] = "FT232H", + [FTX] = "FT-X" }; @@ -1169,7 +1178,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, break; case FT232BM: /* FT232BM chip */ case FT2232C: /* FT2232C chip */ - case FT232RL: + case FT232RL: /* FT232RL chip */ + case FTX: /* FT-X series */ if (baud <= 3000000) { __u16 product_id = le16_to_cpu( port->serial->dev->descriptor.idProduct); @@ -1458,10 +1468,14 @@ static void ftdi_determine_type(struct usb_serial_port *port) } else if (version < 0x900) { /* Assume it's an FT232RL */ priv->chip_type = FT232RL; - } else { + } else if (version < 0x1000) { /* Assume it's an FT232H */ priv->chip_type = FT232H; + } else { + /* Assume it's an FT-X series device */ + priv->chip_type = FTX; } + dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]); } @@ -1589,7 +1603,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port) priv->chip_type == FT232RL || priv->chip_type == FT2232H || priv->chip_type == FT4232H || - priv->chip_type == FT232H)) { + priv->chip_type == FT232H || + priv->chip_type == FTX)) { retval = device_create_file(&port->dev, &dev_attr_latency_timer); } @@ -1611,7 +1626,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port) priv->chip_type == FT232RL || priv->chip_type == FT2232H || priv->chip_type == FT4232H || - priv->chip_type == FT232H) { + priv->chip_type == FT232H || + priv->chip_type == FTX) { device_remove_file(&port->dev, &dev_attr_latency_timer); } } @@ -1763,7 +1779,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); - if (strcmp(udev->manufacturer, "CALAO Systems") == 0) + if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || + (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) return ftdi_jtag_probe(serial); return 0; @@ -2288,6 +2305,7 @@ static int ftdi_tiocmget(struct tty_struct *tty) case FT2232H: case FT4232H: case FT232H: + case FTX: len = 2; break; default: diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 19584fa..ed58c6f 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -157,7 +157,8 @@ enum ftdi_chip_type { FT232RL = 5, FT2232H = 6, FT4232H = 7, - FT232H = 8 + FT232H = 8, + FTX = 9, }; enum ftdi_sio_baudrate { diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 6f6058f..0838baf8 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -23,12 +23,15 @@ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ #define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */ +#define FTDI_FTX_PID 0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ /*** third-party PIDs (using FTDI_VID) ***/ +#define FTDI_LUMEL_PD12_PID 0x6002 + /* * Marvell OpenRD Base, Client * http://www.open-rd.org @@ -97,6 +100,8 @@ #define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ #define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ +#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8 + /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ /* the VID is the standard ftdi vid (FTDI_VID) */ #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ @@ -532,10 +537,14 @@ #define ADI_GNICEPLUS_PID 0xF001 /* - * Hornby Elite + * Microchip Technology, Inc. + * + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * Hornby Elite - Digital Command Control Console + * http://www.hornby.com/hornby-dcc/controllers/ */ -#define HORNBY_VID 0x04D8 -#define HORNBY_ELITE_PID 0x000A +#define MICROCHIP_VID 0x04D8 +#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */ /* * RATOC REX-USB60F @@ -680,6 +689,10 @@ #define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ #define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ #define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */ +#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */ +#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */ +#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */ /* * JETI SPECTROMETER SPECBOS 1201 diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index f740357..e129fcd 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -217,8 +217,10 @@ retry: clear_bit(i, &port->write_urbs_free); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, "%s - error submitting urb: %d\n", + if (!port->port.console) { + dev_err(&port->dev, "%s - error submitting urb: %d\n", __func__, result); + } set_bit(i, &port->write_urbs_free); spin_lock_irqsave(&port->lock, flags); port->tx_bytes -= count; diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 03b5e24..a354eaa 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -174,6 +174,7 @@ #define CLK_MULTI_REGISTER ((__u16)(0x02)) #define CLK_START_VALUE_REGISTER ((__u16)(0x03)) +#define GPIO_REGISTER ((__u16)(0x07)) #define SERIAL_LCR_DLAB ((__u16)(0x0080)) @@ -1101,14 +1102,25 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) mos7840_port->read_urb = port->read_urb; /* set up our bulk in urb */ - - usb_fill_bulk_urb(mos7840_port->read_urb, - serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - port->bulk_in_buffer, - mos7840_port->read_urb->transfer_buffer_length, - mos7840_bulk_in_callback, mos7840_port); + if ((serial->num_ports == 2) + && ((((__u16)port->number - + (__u16)(port->serial->minor)) % 2) != 0)) { + usb_fill_bulk_urb(mos7840_port->read_urb, + serial->dev, + usb_rcvbulkpipe(serial->dev, + (port->bulk_in_endpointAddress) + 2), + port->bulk_in_buffer, + mos7840_port->read_urb->transfer_buffer_length, + mos7840_bulk_in_callback, mos7840_port); + } else { + usb_fill_bulk_urb(mos7840_port->read_urb, + serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->bulk_in_buffer, + mos7840_port->read_urb->transfer_buffer_length, + mos7840_bulk_in_callback, mos7840_port); + } dbg("mos7840_open: bulkin endpoint is %d", port->bulk_in_endpointAddress); @@ -1519,13 +1531,25 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, memcpy(urb->transfer_buffer, current_position, transfer_size); /* fill urb with data and submit */ - usb_fill_bulk_urb(urb, - serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - urb->transfer_buffer, - transfer_size, - mos7840_bulk_out_data_callback, mos7840_port); + if ((serial->num_ports == 2) + && ((((__u16)port->number - + (__u16)(port->serial->minor)) % 2) != 0)) { + usb_fill_bulk_urb(urb, + serial->dev, + usb_sndbulkpipe(serial->dev, + (port->bulk_out_endpointAddress) + 2), + urb->transfer_buffer, + transfer_size, + mos7840_bulk_out_data_callback, mos7840_port); + } else { + usb_fill_bulk_urb(urb, + serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + urb->transfer_buffer, + transfer_size, + mos7840_bulk_out_data_callback, mos7840_port); + } data1 = urb->transfer_buffer; dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); @@ -1838,7 +1862,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, } else { #ifdef HW_flow_control - / *setting h/w flow control bit to 0 */ + /* setting h/w flow control bit to 0 */ Data = 0xb; mos7840_port->shadowMCR = Data; status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, @@ -2305,19 +2329,26 @@ static int mos7840_ioctl(struct tty_struct *tty, static int mos7840_calc_num_ports(struct usb_serial *serial) { - int mos7840_num_ports = 0; - - dbg("numberofendpoints: cur %d, alt %d", - (int)serial->interface->cur_altsetting->desc.bNumEndpoints, - (int)serial->interface->altsetting->desc.bNumEndpoints); - if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) { - mos7840_num_ports = serial->num_ports = 2; - } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) { + __u16 Data = 0x00; + int ret = 0; + int mos7840_num_ports; + + ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data, + VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); + + if ((Data & 0x01) == 0) { + mos7840_num_ports = 2; + serial->num_bulk_in = 2; + serial->num_bulk_out = 2; + serial->num_ports = 2; + } else { + mos7840_num_ports = 4; serial->num_bulk_in = 4; serial->num_bulk_out = 4; - mos7840_num_ports = serial->num_ports = 4; + serial->num_ports = 4; } - dbg ("mos7840_num_ports = %d", mos7840_num_ports); + return mos7840_num_ports; } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b54afce..2a54121 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -307,6 +307,9 @@ static void option_instat_callback(struct urb *urb); #define TELIT_VENDOR_ID 0x1bc7 #define TELIT_PRODUCT_UC864E 0x1003 #define TELIT_PRODUCT_UC864G 0x1004 +#define TELIT_PRODUCT_CC864_DUAL 0x1005 +#define TELIT_PRODUCT_CC864_SINGLE 0x1006 +#define TELIT_PRODUCT_DE910_DUAL 0x1010 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -484,6 +487,9 @@ static void option_instat_callback(struct urb *urb); #define LG_VENDOR_ID 0x1004 #define LG_PRODUCT_L02C 0x618f +/* MediaTek products */ +#define MEDIATEK_VENDOR_ID 0x0e8d + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -768,6 +774,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, @@ -892,6 +901,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, @@ -1198,6 +1209,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); @@ -1360,6 +1375,7 @@ static int option_probe(struct usb_serial *serial, serial->interface->cur_altsetting->desc.bInterfaceNumber, OPTION_BLACKLIST_RESERVED_IF, (const struct option_blacklist_info *) id->driver_info)) + return -ENODEV; /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */ if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID && diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index f98800f..138f732 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -24,39 +24,44 @@ static bool debug; +#define DEVICE_G1K(v, p) \ + USB_DEVICE(v, p), .driver_info = 1 + static const struct usb_device_id id_table[] = { - {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ - {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ - {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ - {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ - {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ - {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ - {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi QDL device */ - {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ - {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ - {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ - {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ - {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ - {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ - {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + /* Gobi 1000 devices */ + {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ + {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ + {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ + {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ + {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ + {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ + {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ + {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ + {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ + {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */ + {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ + {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + + /* Gobi 2000 devices */ + {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */ + {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */ {USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */ {USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */ @@ -92,6 +97,8 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */ {USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ + /* Gobi 3000 devices */ + {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */ @@ -122,8 +129,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) int retval = -ENODEV; __u8 nintf; __u8 ifnum; + bool is_gobi1k = id->driver_info ? true : false; dbg("%s", __func__); + dbg("Is Gobi 1000 = %d", is_gobi1k); nintf = serial->dev->actconfig->desc.bNumInterfaces; dbg("Num Interfaces = %d", nintf); @@ -169,15 +178,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) case 3: case 4: - /* Composite mode */ - /* ifnum == 0 is a broadband network adapter */ - if (ifnum == 1) { - /* - * Diagnostics Monitor (serial line 9600 8N1) - * Qualcomm DM protocol - * use "libqcdm" (ModemManager) for communication - */ - dbg("Diagnostics Monitor found"); + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ + + /* Gobi 1K USB layout: + * 0: serial port (doesn't respond) + * 1: serial port (doesn't respond) + * 2: AT-capable modem port + * 3: QMI/net + * + * Gobi 2K+ USB layout: + * 0: QMI/net + * 1: DM/DIAG (use libqcdm from ModemManager for communication) + * 2: AT-capable modem port + * 3: NMEA + */ + + if (ifnum == 1 && !is_gobi1k) { + dbg("Gobi 2K+ DM/DIAG interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, @@ -196,13 +215,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) retval = -ENODEV; kfree(data); } - } else if (ifnum==3) { + } else if (ifnum==3 && !is_gobi1k) { /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ - dbg("NMEA GPS interface found"); + dbg("Gobi 2K+ NMEA GPS interface found"); retval = usb_set_interface(serial->dev, ifnum, 0); if (retval < 0) { dev_err(&serial->dev->dev, diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index d32f720..eee2a96 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -507,9 +507,14 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) { int retval; u8 cmnd[12] = {0}; + u8 *buf; US_DEBUGP("%s, addr = 0xfe47, len = %d\n", __FUNCTION__, len); + buf = kmemdup(data, len, GFP_NOIO); + if (!buf) + return USB_STOR_TRANSPORT_ERROR; + cmnd[0] = 0xF0; cmnd[1] = 0x0E; cmnd[2] = 0xfe; @@ -517,7 +522,8 @@ static int __do_config_autodelink(struct us_data *us, u8 *data, u16 len) cmnd[4] = (u8)(len >> 8); cmnd[5] = (u8)len; - retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, data, len, DMA_TO_DEVICE, NULL); + retval = rts51x_bulk_transport_special(us, 0, cmnd, 12, buf, len, DMA_TO_DEVICE, NULL); + kfree(buf); if (retval != USB_STOR_TRANSPORT_GOOD) { return -EIO; } diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c index 772f601..6f54f74 100644 --- a/drivers/video/backlight/tosa_lcd.c +++ b/drivers/video/backlight/tosa_lcd.c @@ -271,7 +271,7 @@ static int tosa_lcd_resume(struct spi_device *spi) } #else #define tosa_lcd_suspend NULL -#define tosa_lcd_reume NULL +#define tosa_lcd_resume NULL #endif static struct spi_driver tosa_lcd_driver = { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index ac9141b..c6ce416 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1665,6 +1665,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) if (ret) return -EINVAL; + unlink_framebuffer(fb_info); if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); @@ -1672,7 +1673,6 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) registered_fb[i] = NULL; num_registered_fb--; fb_cleanup_device(fb_info); - device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); @@ -1681,6 +1681,22 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) return 0; } +int unlink_framebuffer(struct fb_info *fb_info) +{ + int i; + + i = fb_info->node; + if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) + return -EINVAL; + + if (fb_info->dev) { + device_destroy(fb_class, MKDEV(FB_MAJOR, i)); + fb_info->dev = NULL; + } + return 0; +} +EXPORT_SYMBOL(unlink_framebuffer); + void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary) { diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index a197731..a40c05e 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -1739,7 +1739,7 @@ static void dlfb_usb_disconnect(struct usb_interface *interface) for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_bin_file(info->dev, &edid_attr); - + unlink_framebuffer(info); usb_set_intfdata(interface, NULL); /* if clients still have us open, will be freed on last close */ diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index b1fd382..6ee1cb4 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -76,7 +76,7 @@ MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " unsigned int cifs_max_pending = CIFS_MAX_REQ; module_param(cifs_max_pending, int, 0444); MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " - "Default: 50 Range: 2 to 256"); + "Default: 32767 Range: 2 to 32767."); unsigned short echo_retries = 5; module_param(echo_retries, ushort, 0644); MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " @@ -1116,9 +1116,9 @@ init_cifs(void) if (cifs_max_pending < 2) { cifs_max_pending = 2; cFYI(1, "cifs_max_pending set to min of 2"); - } else if (cifs_max_pending > 256) { - cifs_max_pending = 256; - cFYI(1, "cifs_max_pending set to max of 256"); + } else if (cifs_max_pending > CIFS_MAX_REQ) { + cifs_max_pending = CIFS_MAX_REQ; + cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ); } rc = cifs_fscache_register(); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 76e7d8b..d47d20a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -55,14 +55,9 @@ /* * MAX_REQ is the maximum number of requests that WE will send - * on one socket concurrently. It also matches the most common - * value of max multiplex returned by servers. We may - * eventually want to use the negotiated value (in case - * future servers can handle more) when we are more confident that - * we will not have problems oveloading the socket with pending - * write data. + * on one socket concurrently. */ -#define CIFS_MAX_REQ 50 +#define CIFS_MAX_REQ 32767 #define RFC1001_NAME_LEN 15 #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1) @@ -263,6 +258,7 @@ struct TCP_Server_Info { bool session_estab; /* mark when very first sess is established */ u16 dialect; /* dialect index that server chose */ enum securityEnum secType; + bool oplocks:1; /* enable oplocks */ unsigned int maxReq; /* Clients should submit no more */ /* than maxReq distinct unanswered SMBs to the server when using */ /* multiplexed reads or writes */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 8b7794c..cd66b76 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -458,7 +458,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) goto neg_err_exit; } server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode); - server->maxReq = le16_to_cpu(rsp->MaxMpxCount); + server->maxReq = min_t(unsigned int, + le16_to_cpu(rsp->MaxMpxCount), + cifs_max_pending); + server->oplocks = server->maxReq > 1 ? enable_oplocks : false; server->maxBuf = le16_to_cpu(rsp->MaxBufSize); server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); /* even though we do not use raw we might as well set this @@ -564,7 +567,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) /* one byte, so no need to convert this or EncryptionKeyLen from little endian */ - server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); + server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), + cifs_max_pending); + server->oplocks = server->maxReq > 1 ? enable_oplocks : false; /* probably no need to store and check maxvcs */ server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 602f77c..0ac595c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -642,14 +642,10 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) spin_unlock(&GlobalMid_Lock); wake_up_all(&server->response_q); - /* - * Check if we have blocked requests that need to free. Note that - * cifs_max_pending is normally 50, but can be set at module install - * time to as little as two. - */ + /* Check if we have blocked requests that need to free. */ spin_lock(&GlobalMid_Lock); - if (atomic_read(&server->inFlight) >= cifs_max_pending) - atomic_set(&server->inFlight, cifs_max_pending - 1); + if (atomic_read(&server->inFlight) >= server->maxReq) + atomic_set(&server->inFlight, server->maxReq - 1); /* * We do not want to set the max_pending too low or we could end up * with the counter going negative. @@ -1910,6 +1906,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses->noautotune = volume_info->noautotune; tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; atomic_set(&tcp_ses->inFlight, 0); + tcp_ses->maxReq = 1; /* enough to send negotiate request */ init_waitqueue_head(&tcp_ses->response_q); init_waitqueue_head(&tcp_ses->request_q); INIT_LIST_HEAD(&tcp_ses->pending_mid_q); @@ -3371,7 +3368,7 @@ cifs_ra_pages(struct cifs_sb_info *cifs_sb) int cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) { - int rc = 0; + int rc; int xid; struct cifs_ses *pSesInfo; struct cifs_tcon *tcon; @@ -3398,6 +3395,7 @@ try_mount_again: FreeXid(xid); } #endif + rc = 0; tcon = NULL; pSesInfo = NULL; srvTcp = NULL; diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index bc7e244..d172c8e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -171,7 +171,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, } tcon = tlink_tcon(tlink); - if (enable_oplocks) + if (tcon->ses->server->oplocks) oplock = REQ_OPLOCK; if (nd) @@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, { int xid; int rc = 0; /* to get around spurious gcc warning, set to zero here */ - __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0; + __u32 oplock; __u16 fileHandle = 0; bool posix_open = false; struct cifs_sb_info *cifs_sb; @@ -518,6 +518,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } pTcon = tlink_tcon(tlink); + oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0; + /* * Don't allow the separator character in a path component. * The VFS will not allow "/", but "\" is allowed by posix. diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 5e64748..159fcc5 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -380,7 +380,7 @@ int cifs_open(struct inode *inode, struct file *file) cFYI(1, "inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags, full_path); - if (enable_oplocks) + if (tcon->ses->server->oplocks) oplock = REQ_OPLOCK; else oplock = 0; @@ -505,7 +505,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, pCifsFile->f_flags, full_path); - if (enable_oplocks) + if (tcon->ses->server->oplocks) oplock = REQ_OPLOCK; else oplock = 0; @@ -960,9 +960,9 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) INIT_LIST_HEAD(&locks_to_send); /* - * Allocating count locks is enough because no locks can be added to - * the list while we are holding cinode->lock_mutex that protects - * locking operations of this inode. + * Allocating count locks is enough because no FL_POSIX locks can be + * added to the list while we are holding cinode->lock_mutex that + * protects locking operations of this inode. */ for (; i < count; i++) { lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); @@ -973,18 +973,20 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) list_add_tail(&lck->llist, &locks_to_send); } - i = 0; el = locks_to_send.next; lock_flocks(); cifs_for_each_lock(cfile->dentry->d_inode, before) { + flock = *before; + if ((flock->fl_flags & FL_POSIX) == 0) + continue; if (el == &locks_to_send) { - /* something is really wrong */ + /* + * The list ended. We don't have enough allocated + * structures - something is really wrong. + */ cERROR(1, "Can't push all brlocks!"); break; } - flock = *before; - if ((flock->fl_flags & FL_POSIX) == 0) - continue; length = 1 + flock->fl_end - flock->fl_start; if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) type = CIFS_RDLCK; @@ -996,7 +998,6 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) lck->length = length; lck->type = type; lck->offset = flock->fl_start; - i++; el = el->next; } unlock_flocks(); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 0cc9584..99a27cf 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -265,12 +265,12 @@ static int wait_for_free_request(struct TCP_Server_Info *server, spin_lock(&GlobalMid_Lock); while (1) { - if (atomic_read(&server->inFlight) >= cifs_max_pending) { + if (atomic_read(&server->inFlight) >= server->maxReq) { spin_unlock(&GlobalMid_Lock); cifs_num_waiters_inc(server); wait_event(server->request_q, atomic_read(&server->inFlight) - < cifs_max_pending); + < server->maxReq); cifs_num_waiters_dec(server); spin_lock(&GlobalMid_Lock); } else { diff --git a/fs/dcache.c b/fs/dcache.c index bcbdb33..2576d14 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2405,6 +2405,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) if (d_ancestor(alias, dentry)) { /* Check for loops */ actual = ERR_PTR(-ELOOP); + spin_unlock(&inode->i_lock); } else if (IS_ROOT(alias)) { /* Is this an anonymous mountpoint that we * could splice into our tree? */ @@ -2414,7 +2415,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode) goto found; } else { /* Nope, but we must(!) avoid directory - * aliasing */ + * aliasing. This drops inode->i_lock */ actual = __d_unalias(inode, dentry, alias); } write_sequnlock(&rename_lock); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 513004f..3ce6a0c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -184,6 +184,8 @@ struct mpage_da_data { #define EXT4_IO_END_UNWRITTEN 0x0001 #define EXT4_IO_END_ERROR 0x0002 #define EXT4_IO_END_QUEUED 0x0004 +#define EXT4_IO_END_DIRECT 0x0008 +#define EXT4_IO_END_IN_FSYNC 0x0010 struct ext4_io_page { struct page *p_page; diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 5802fa1..95af6f8 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -261,43 +261,45 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle, /* super.c */ int ext4_force_commit(struct super_block *sb); -static inline int ext4_should_journal_data(struct inode *inode) +/* + * Ext4 inode journal modes + */ +#define EXT4_INODE_JOURNAL_DATA_MODE 0x01 /* journal data mode */ +#define EXT4_INODE_ORDERED_DATA_MODE 0x02 /* ordered data mode */ +#define EXT4_INODE_WRITEBACK_DATA_MODE 0x04 /* writeback data mode */ + +static inline int ext4_inode_journal_mode(struct inode *inode) { if (EXT4_JOURNAL(inode) == NULL) - return 0; - if (!S_ISREG(inode->i_mode)) - return 1; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) - return 1; - if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) - return 1; - return 0; + return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ + /* We do not support data journalling with delayed allocation */ + if (!S_ISREG(inode->i_mode) || + test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) + return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */ + if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) && + !test_opt(inode->i_sb, DELALLOC)) + return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */ + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) + return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */ + if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) + return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */ + else + BUG(); +} + +static inline int ext4_should_journal_data(struct inode *inode) +{ + return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE; } static inline int ext4_should_order_data(struct inode *inode) { - if (EXT4_JOURNAL(inode) == NULL) - return 0; - if (!S_ISREG(inode->i_mode)) - return 0; - if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) - return 0; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) - return 1; - return 0; + return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE; } static inline int ext4_should_writeback_data(struct inode *inode) { - if (EXT4_JOURNAL(inode) == NULL) - return 1; - if (!S_ISREG(inode->i_mode)) - return 0; - if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA)) - return 0; - if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA) - return 1; - return 0; + return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE; } /* diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 74f23c2..4394a757 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -300,6 +300,8 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) ext4_fsblk_t block = ext4_ext_pblock(ext); int len = ext4_ext_get_actual_len(ext); + if (len == 0) + return 0; return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len); } diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 00a2cb7..bb6c7d8 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c @@ -89,6 +89,7 @@ int ext4_flush_completed_IO(struct inode *inode) io = list_entry(ei->i_completed_io_list.next, ext4_io_end_t, list); list_del_init(&io->list); + io->flag |= EXT4_IO_END_IN_FSYNC; /* * Calling ext4_end_io_nolock() to convert completed * IO to written. @@ -108,6 +109,7 @@ int ext4_flush_completed_IO(struct inode *inode) if (ret < 0) ret2 = ret; spin_lock_irqsave(&ei->i_completed_io_lock, flags); + io->flag &= ~EXT4_IO_END_IN_FSYNC; } spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); return (ret2 < 0) ? ret2 : 0; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index feaa82f..aafc626 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -2482,13 +2482,14 @@ static int ext4_da_write_end(struct file *file, int write_mode = (int)(unsigned long)fsdata; if (write_mode == FALL_BACK_TO_NONDELALLOC) { - if (ext4_should_order_data(inode)) { + switch (ext4_inode_journal_mode(inode)) { + case EXT4_INODE_ORDERED_DATA_MODE: return ext4_ordered_write_end(file, mapping, pos, len, copied, page, fsdata); - } else if (ext4_should_writeback_data(inode)) { + case EXT4_INODE_WRITEBACK_DATA_MODE: return ext4_writeback_write_end(file, mapping, pos, len, copied, page, fsdata); - } else { + default: BUG(); } } @@ -2795,9 +2796,6 @@ out: /* queue the work to convert unwritten extents to written */ queue_work(wq, &io_end->work); - - /* XXX: probably should move into the real I/O completion handler */ - inode_dio_done(inode); } static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate) @@ -2921,9 +2919,12 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, iocb->private = NULL; EXT4_I(inode)->cur_aio_dio = NULL; if (!is_sync_kiocb(iocb)) { - iocb->private = ext4_init_io_end(inode, GFP_NOFS); - if (!iocb->private) + ext4_io_end_t *io_end = + ext4_init_io_end(inode, GFP_NOFS); + if (!io_end) return -ENOMEM; + io_end->flag |= EXT4_IO_END_DIRECT; + iocb->private = io_end; /* * we save the io structure for current async * direct IO, so that later ext4_map_blocks() @@ -3086,18 +3087,25 @@ static const struct address_space_operations ext4_da_aops = { void ext4_set_aops(struct inode *inode) { - if (ext4_should_order_data(inode) && - test_opt(inode->i_sb, DELALLOC)) - inode->i_mapping->a_ops = &ext4_da_aops; - else if (ext4_should_order_data(inode)) - inode->i_mapping->a_ops = &ext4_ordered_aops; - else if (ext4_should_writeback_data(inode) && - test_opt(inode->i_sb, DELALLOC)) - inode->i_mapping->a_ops = &ext4_da_aops; - else if (ext4_should_writeback_data(inode)) - inode->i_mapping->a_ops = &ext4_writeback_aops; - else + switch (ext4_inode_journal_mode(inode)) { + case EXT4_INODE_ORDERED_DATA_MODE: + if (test_opt(inode->i_sb, DELALLOC)) + inode->i_mapping->a_ops = &ext4_da_aops; + else + inode->i_mapping->a_ops = &ext4_ordered_aops; + break; + case EXT4_INODE_WRITEBACK_DATA_MODE: + if (test_opt(inode->i_sb, DELALLOC)) + inode->i_mapping->a_ops = &ext4_da_aops; + else + inode->i_mapping->a_ops = &ext4_writeback_aops; + break; + case EXT4_INODE_JOURNAL_DATA_MODE: inode->i_mapping->a_ops = &ext4_journalled_aops; + break; + default: + BUG(); + } } diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 4758518..dcdeef1 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -110,6 +110,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io) if (io->iocb) aio_complete(io->iocb, io->result, 0); + if (io->flag & EXT4_IO_END_DIRECT) + inode_dio_done(inode); /* Wake up anyone waiting on unwritten extent conversion */ if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) wake_up_all(ext4_ioend_wq(io->inode)); @@ -127,12 +129,18 @@ static void ext4_end_io_work(struct work_struct *work) unsigned long flags; spin_lock_irqsave(&ei->i_completed_io_lock, flags); + if (io->flag & EXT4_IO_END_IN_FSYNC) + goto requeue; if (list_empty(&io->list)) { spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); goto free; } if (!mutex_trylock(&inode->i_mutex)) { + bool was_queued; +requeue: + was_queued = !!(io->flag & EXT4_IO_END_QUEUED); + io->flag |= EXT4_IO_END_QUEUED; spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); /* * Requeue the work instead of waiting so that the work @@ -145,9 +153,8 @@ static void ext4_end_io_work(struct work_struct *work) * yield the cpu if it sees an end_io request that has already * been requeued. */ - if (io->flag & EXT4_IO_END_QUEUED) + if (was_queued) yield(); - io->flag |= EXT4_IO_END_QUEUED; return; } list_del_init(&io->list); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 1e85a7a..3645cd3 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -238,17 +238,10 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf, loff_t isize; ssize_t retval = 0; - mutex_lock(&inode->i_mutex); - /* validate length */ if (len == 0) goto out; - isize = i_size_read(inode); - if (!isize) - goto out; - - end_index = (isize - 1) >> huge_page_shift(h); for (;;) { struct page *page; unsigned long nr, ret; @@ -256,18 +249,21 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf, /* nr is the maximum number of bytes to copy from this page */ nr = huge_page_size(h); + isize = i_size_read(inode); + if (!isize) + goto out; + end_index = (isize - 1) >> huge_page_shift(h); if (index >= end_index) { if (index > end_index) goto out; nr = ((isize - 1) & ~huge_page_mask(h)) + 1; - if (nr <= offset) { + if (nr <= offset) goto out; - } } nr = nr - offset; /* Find the page */ - page = find_get_page(mapping, index); + page = find_lock_page(mapping, index); if (unlikely(page == NULL)) { /* * We have a HOLE, zero out the user-buffer for the @@ -279,17 +275,18 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf, else ra = 0; } else { + unlock_page(page); + /* * We have the page, copy it to user space buffer. */ ra = hugetlbfs_read_actor(page, offset, buf, len, nr); ret = ra; + page_cache_release(page); } if (ra < 0) { if (retval == 0) retval = ra; - if (page) - page_cache_release(page); goto out; } @@ -299,16 +296,12 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf, index += offset >> huge_page_shift(h); offset &= ~huge_page_mask(h); - if (page) - page_cache_release(page); - /* short read or no more work */ if ((ret != nr) || (len == 0)) break; } out: *ppos = ((loff_t)index << huge_page_shift(h)) + offset; - mutex_unlock(&inode->i_mutex); return retval; } diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 35ae096..52653306 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1949,6 +1949,8 @@ zap_buffer_unlocked: clear_buffer_mapped(bh); clear_buffer_req(bh); clear_buffer_new(bh); + clear_buffer_delay(bh); + clear_buffer_unwritten(bh); bh->b_bdev = NULL; return may_free; } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index c061b9a..2444780 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -440,7 +440,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \ __typeof__(type) num = which_strtol(val, &endp, 0); \ if (endp == val || *endp || num < (min) || num > (max)) \ return -EINVAL; \ - *((int *) kp->arg) = num; \ + *((type *) kp->arg) = num; \ return 0; \ } diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index d50b274..2b2d33b 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include "nfs4_fs.h" @@ -167,7 +169,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound if (hdr->minorversion <= 1) { hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */ } else { - printk(KERN_WARNING "%s: NFSv4 server callback with " + pr_warn_ratelimited("NFS: %s: NFSv4 server callback with " "illegal minor version %u!\n", __func__, hdr->minorversion); return htonl(NFS4ERR_MINOR_VERS_MISMATCH); diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 7f26540..ac889af 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -466,6 +466,17 @@ static void nfs_delegation_run_state_manager(struct nfs_client *clp) nfs4_schedule_state_manager(clp); } +void nfs_remove_bad_delegation(struct inode *inode) +{ + struct nfs_delegation *delegation; + + delegation = nfs_detach_delegation(NFS_I(inode), NFS_SERVER(inode)); + if (delegation) { + nfs_inode_find_state_and_recover(inode, &delegation->stateid); + nfs_free_delegation(delegation); + } +} + /** * nfs_expire_all_delegation_types * @clp: client to process diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index d9322e4..691a796 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -45,6 +45,7 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_handle_cb_pathdown(struct nfs_client *clp); int nfs_client_return_marked_delegations(struct nfs_client *clp); int nfs_delegations_present(struct nfs_client *clp); +void nfs_remove_bad_delegation(struct inode *inode); void nfs_delegation_mark_reclaim(struct nfs_client *clp); void nfs_delegation_reap_unclaimed(struct nfs_client *clp); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 4d7d0ae..8ccaf24 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -193,6 +193,7 @@ struct nfs4_exception { long timeout; int retry; struct nfs4_state *state; + struct inode *inode; }; struct nfs4_state_recovery_ops { @@ -327,6 +328,8 @@ extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct nfs4_state *, fmode_t); extern void nfs4_close_sync(struct nfs4_state *, fmode_t); extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t); +extern void nfs_inode_find_state_and_recover(struct inode *inode, + const nfs4_stateid *stateid); extern void nfs4_schedule_lease_recovery(struct nfs_client *); extern void nfs4_schedule_state_manager(struct nfs_client *); extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ec9f6ef..0cb7163 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -259,15 +259,28 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc { struct nfs_client *clp = server->nfs_client; struct nfs4_state *state = exception->state; + struct inode *inode = exception->inode; int ret = errorcode; exception->retry = 0; switch(errorcode) { case 0: return 0; + case -NFS4ERR_OPENMODE: + if (nfs_have_delegation(inode, FMODE_READ)) { + nfs_inode_return_delegation(inode); + exception->retry = 1; + return 0; + } + if (state == NULL) + break; + nfs4_schedule_stateid_recovery(server, state); + goto wait_on_recovery; + case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: - case -NFS4ERR_OPENMODE: + if (state != NULL) + nfs_remove_bad_delegation(state->inode); if (state == NULL) break; nfs4_schedule_stateid_recovery(server, state); @@ -1319,8 +1332,11 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state * The show must go on: exit, but mark the * stateid as needing recovery. */ + case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: + nfs_inode_find_state_and_recover(state->inode, + stateid); nfs4_schedule_stateid_recovery(server, state); case -EKEYEXPIRED: /* @@ -1829,7 +1845,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, * the user though... */ if (status == -NFS4ERR_BAD_SEQID) { - printk(KERN_WARNING "NFS: v4 server %s " + pr_warn_ratelimited("NFS: v4 server %s " " returned a bad sequence-id error!\n", NFS_SERVER(dir)->nfs_client->cl_hostname); exception.retry = 1; @@ -1900,7 +1916,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs4_state *state) { struct nfs_server *server = NFS_SERVER(inode); - struct nfs4_exception exception = { }; + struct nfs4_exception exception = { + .state = state, + .inode = inode, + }; int err; do { err = nfs4_handle_exception(server, @@ -2230,11 +2249,12 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, switch (err) { case 0: case -NFS4ERR_WRONGSEC: - break; + goto out; default: err = nfs4_handle_exception(server, err, &exception); } } while (exception.retry); +out: return err; } @@ -3714,8 +3734,11 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, if (task->tk_status >= 0) return 0; switch(task->tk_status) { + case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: + if (state != NULL) + nfs_remove_bad_delegation(state->inode); case -NFS4ERR_OPENMODE: if (state == NULL) break; @@ -4533,7 +4556,9 @@ out: static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) { - struct nfs4_exception exception = { }; + struct nfs4_exception exception = { + .state = state, + }; int err; do { @@ -4626,6 +4651,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) * The show must go on: exit, but mark the * stateid as needing recovery. */ + case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_BAD_STATEID: case -NFS4ERR_OPENMODE: @@ -5926,21 +5952,22 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) return; switch (task->tk_status) { /* Just ignore these failures */ - case NFS4ERR_DELEG_REVOKED: /* layout was recalled */ - case NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */ - case NFS4ERR_BADLAYOUT: /* no layout */ - case NFS4ERR_GRACE: /* loca_recalim always false */ + case -NFS4ERR_DELEG_REVOKED: /* layout was recalled */ + case -NFS4ERR_BADIOMODE: /* no IOMODE_RW layout for range */ + case -NFS4ERR_BADLAYOUT: /* no layout */ + case -NFS4ERR_GRACE: /* loca_recalim always false */ task->tk_status = 0; - } - - if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { - rpc_restart_call_prepare(task); - return; - } - - if (task->tk_status == 0) + break; + case 0: nfs_post_op_update_inode_force_wcc(data->args.inode, data->res.fattr); + break; + default: + if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { + rpc_restart_call_prepare(task); + return; + } + } } static void nfs4_layoutcommit_release(void *calldata) @@ -6043,11 +6070,12 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, case 0: case -NFS4ERR_WRONGSEC: case -NFS4ERR_NOTSUPP: - break; + goto out; default: err = nfs4_handle_exception(server, err, &exception); } } while (exception.retry); +out: return err; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 4539203..bacb271 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -996,7 +996,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) case -NFS4ERR_BAD_SEQID: if (seqid->sequence->flags & NFS_SEQID_CONFIRMED) return; - printk(KERN_WARNING "NFS: v4 server returned a bad" + pr_warn_ratelimited("NFS: v4 server returned a bad" " sequence-id error on an" " unconfirmed sequence %p!\n", seqid->sequence); @@ -1132,12 +1132,37 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4 { struct nfs_client *clp = server->nfs_client; - if (test_and_clear_bit(NFS_DELEGATED_STATE, &state->flags)) - nfs_async_inode_return_delegation(state->inode, &state->stateid); nfs4_state_mark_reclaim_nograce(clp, state); nfs4_schedule_state_manager(clp); } +void nfs_inode_find_state_and_recover(struct inode *inode, + const nfs4_stateid *stateid) +{ + struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; + struct nfs_inode *nfsi = NFS_I(inode); + struct nfs_open_context *ctx; + struct nfs4_state *state; + bool found = false; + + spin_lock(&inode->i_lock); + list_for_each_entry(ctx, &nfsi->open_files, list) { + state = ctx->state; + if (state == NULL) + continue; + if (!test_bit(NFS_DELEGATED_STATE, &state->flags)) + continue; + if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0) + continue; + nfs4_state_mark_reclaim_nograce(clp, state); + found = true; + } + spin_unlock(&inode->i_lock); + if (found) + nfs4_schedule_state_manager(clp); +} + + static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops) { struct inode *inode = state->inode; @@ -1801,7 +1826,7 @@ static void nfs4_state_manager(struct nfs_client *clp) } while (atomic_read(&clp->cl_count) > 1); return; out_error: - printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" + pr_warn_ratelimited("NFS: state manager failed on NFSv4 server %s" " with error %d\n", clp->cl_hostname, -status); nfs4_end_drain_session(clp); nfs4_clear_state_manager_bit(clp); diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 27da860..3551f1f 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c @@ -53,7 +53,7 @@ static struct dentry *proc_ns_instantiate(struct inode *dir, ei->ns_ops = ns_ops; ei->ns = ns; - dentry->d_op = &pid_dentry_operations; + d_set_d_op(dentry, &pid_dentry_operations); d_add(dentry, inode); /* Close the race of the process dying before we return the dentry */ if (pid_revalidate(dentry, NULL)) diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index a6b6217..53c3bce 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -188,20 +188,32 @@ static ssize_t proc_sys_write(struct file *filp, const char __user *buf, static int proc_sys_open(struct inode *inode, struct file *filp) { + struct ctl_table_header *head = grab_header(inode); struct ctl_table *table = PROC_I(inode)->sysctl_entry; + /* sysctl was unregistered */ + if (IS_ERR(head)) + return PTR_ERR(head); + if (table->poll) filp->private_data = proc_sys_poll_event(table->poll); + sysctl_head_finish(head); + return 0; } static unsigned int proc_sys_poll(struct file *filp, poll_table *wait) { struct inode *inode = filp->f_path.dentry->d_inode; + struct ctl_table_header *head = grab_header(inode); struct ctl_table *table = PROC_I(inode)->sysctl_entry; - unsigned long event = (unsigned long)filp->private_data; unsigned int ret = DEFAULT_POLLMASK; + unsigned long event; + + /* sysctl was unregistered */ + if (IS_ERR(head)) + return POLLERR | POLLHUP; if (!table->proc_handler) goto out; @@ -209,6 +221,7 @@ static unsigned int proc_sys_poll(struct file *filp, poll_table *wait) if (!table->poll) goto out; + event = (unsigned long)filp->private_data; poll_wait(filp, &table->poll->wait, wait); if (event != atomic_read(&table->poll->event)) { @@ -217,6 +230,8 @@ static unsigned int proc_sys_poll(struct file *filp, poll_table *wait) } out: + sysctl_head_finish(head); + return ret; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 7dcd2a2..3efa725 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -409,6 +409,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, } else { spin_unlock(&walk->mm->page_table_lock); } + + if (pmd_trans_unstable(pmd)) + return 0; /* * The mmap_sem held all the way back in m_start() is what * keeps khugepaged out of here and from collapsing things @@ -507,6 +510,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr, struct page *page; split_huge_page_pmd(walk->mm, pmd); + if (pmd_trans_unstable(pmd)) + return 0; pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) { @@ -670,6 +675,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, int err = 0; split_huge_page_pmd(walk->mm, pmd); + if (pmd_trans_unstable(pmd)) + return 0; /* find the first VMA at or above 'addr' */ vma = find_vma(walk->mm, addr); @@ -961,6 +968,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr, spin_unlock(&walk->mm->page_table_lock); } + if (pmd_trans_unstable(pmd)) + return 0; orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl); do { struct page *page = can_gather_numa_stats(*pte, md->vma, addr); diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 85eb816..feb2d69 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c @@ -136,12 +136,13 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *sec void *old_secdata; size_t old_secdata_len; - iattrs = sd->s_iattr; - if (!iattrs) - iattrs = sysfs_init_inode_attrs(sd); - if (!iattrs) - return -ENOMEM; + if (!sd->s_iattr) { + sd->s_iattr = sysfs_init_inode_attrs(sd); + if (!sd->s_iattr) + return -ENOMEM; + } + iattrs = sd->s_iattr; old_secdata = iattrs->ia_secdata; old_secdata_len = iattrs->ia_secdata_len; diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 8c3e463..9271f4c 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -350,9 +350,20 @@ xfs_iget_cache_miss( BUG(); } - spin_lock(&pag->pag_ici_lock); + /* + * These values must be set before inserting the inode into the radix + * tree as the moment it is inserted a concurrent lookup (allowed by the + * RCU locking mechanism) can find it and that lookup must see that this + * is an inode currently under construction (i.e. that XFS_INEW is set). + * The ip->i_flags_lock that protects the XFS_INEW flag forms the + * memory barrier that ensures this detection works correctly at lookup + * time. + */ + ip->i_udquot = ip->i_gdquot = NULL; + xfs_iflags_set(ip, XFS_INEW); /* insert the new inode */ + spin_lock(&pag->pag_ici_lock); error = radix_tree_insert(&pag->pag_ici_root, agino, ip); if (unlikely(error)) { WARN_ON(error != -EEXIST); @@ -360,11 +371,6 @@ xfs_iget_cache_miss( error = EAGAIN; goto out_preload_end; } - - /* These values _must_ be set before releasing the radix tree lock! */ - ip->i_udquot = ip->i_gdquot = NULL; - xfs_iflags_set(ip, XFS_INEW); - spin_unlock(&pag->pag_ici_lock); radix_tree_preload_end(); diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 0ed9ee7..a89c2f2 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3161,37 +3161,26 @@ xlog_recover_process_iunlinks( */ continue; } + /* + * Unlock the buffer so that it can be acquired in the normal + * course of the transaction to truncate and free each inode. + * Because we are not racing with anyone else here for the AGI + * buffer, we don't even need to hold it locked to read the + * initial unlinked bucket entries out of the buffer. We keep + * buffer reference though, so that it stays pinned in memory + * while we need the buffer. + */ agi = XFS_BUF_TO_AGI(agibp); + xfs_buf_unlock(agibp); for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { agino = be32_to_cpu(agi->agi_unlinked[bucket]); while (agino != NULLAGINO) { - /* - * Release the agi buffer so that it can - * be acquired in the normal course of the - * transaction to truncate and free the inode. - */ - xfs_buf_relse(agibp); - agino = xlog_recover_process_one_iunlink(mp, agno, agino, bucket); - - /* - * Reacquire the agibuffer and continue around - * the loop. This should never fail as we know - * the buffer was good earlier on. - */ - error = xfs_read_agi(mp, NULL, agno, &agibp); - ASSERT(error == 0); - agi = XFS_BUF_TO_AGI(agibp); } } - - /* - * Release the buffer for the current agi so we can - * go on to the next one. - */ - xfs_buf_relse(agibp); + xfs_buf_rele(agibp); } mp->m_dmevmask = mp_dmevmask; diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 76bff2b..a03c098 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -425,6 +425,8 @@ extern void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn, unsigned long size); #endif +#ifdef CONFIG_MMU + #ifndef CONFIG_TRANSPARENT_HUGEPAGE static inline int pmd_trans_huge(pmd_t pmd) { @@ -441,7 +443,66 @@ static inline int pmd_write(pmd_t pmd) return 0; } #endif /* __HAVE_ARCH_PMD_WRITE */ +#endif /* CONFIG_TRANSPARENT_HUGEPAGE */ + +/* + * This function is meant to be used by sites walking pagetables with + * the mmap_sem hold in read mode to protect against MADV_DONTNEED and + * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd + * into a null pmd and the transhuge page fault can convert a null pmd + * into an hugepmd or into a regular pmd (if the hugepage allocation + * fails). While holding the mmap_sem in read mode the pmd becomes + * stable and stops changing under us only if it's not null and not a + * transhuge pmd. When those races occurs and this function makes a + * difference vs the standard pmd_none_or_clear_bad, the result is + * undefined so behaving like if the pmd was none is safe (because it + * can return none anyway). The compiler level barrier() is critically + * important to compute the two checks atomically on the same pmdval. + */ +static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) +{ + /* depend on compiler for an atomic pmd read */ + pmd_t pmdval = *pmd; + /* + * The barrier will stabilize the pmdval in a register or on + * the stack so that it will stop changing under the code. + */ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + barrier(); +#endif + if (pmd_none(pmdval)) + return 1; + if (unlikely(pmd_bad(pmdval))) { + if (!pmd_trans_huge(pmdval)) + pmd_clear_bad(pmd); + return 1; + } + return 0; +} + +/* + * This is a noop if Transparent Hugepage Support is not built into + * the kernel. Otherwise it is equivalent to + * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in + * places that already verified the pmd is not none and they want to + * walk ptes while holding the mmap sem in read mode (write mode don't + * need this). If THP is not enabled, the pmd can't go away under the + * code even if MADV_DONTNEED runs, but if THP is enabled we need to + * run a pmd_trans_unstable before walking the ptes after + * split_huge_page_pmd returns (because it may have run when the pmd + * become null, but then a page fault can map in a THP and not a + * regular page). + */ +static inline int pmd_trans_unstable(pmd_t *pmd) +{ +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + return pmd_none_or_trans_huge_or_clear_bad(pmd); +#else + return 0; #endif +} + +#endif /* CONFIG_MMU */ #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h index 2292d1a..991ef01 100644 --- a/include/asm-generic/unistd.h +++ b/include/asm-generic/unistd.h @@ -218,7 +218,7 @@ __SC_COMP(__NR_pwritev, sys_pwritev, compat_sys_pwritev) /* fs/sendfile.c */ #define __NR3264_sendfile 71 -__SC_3264(__NR3264_sendfile, sys_sendfile64, sys_sendfile) +__SYSCALL(__NR3264_sendfile, sys_sendfile64) /* fs/select.c */ #define __NR_pselect6 72 diff --git a/include/linux/fb.h b/include/linux/fb.h index c18122f..a395b8c 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -1003,6 +1003,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); +extern int unlink_framebuffer(struct fb_info *fb_info); extern void remove_conflicting_framebuffers(struct apertures_struct *a, const char *name, bool primary); extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); diff --git a/include/linux/math64.h b/include/linux/math64.h index 23fcdfc..b8ba855 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h @@ -6,6 +6,8 @@ #if BITS_PER_LONG == 64 +#define div64_long(x,y) div64_s64((x),(y)) + /** * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder * @@ -45,6 +47,8 @@ static inline s64 div64_s64(s64 dividend, s64 divisor) #elif BITS_PER_LONG == 32 +#define div64_long(x,y) div_s64((x),(y)) + #ifndef div_u64_rem static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) { diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index a03a0ad..5a82c09 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -97,6 +97,7 @@ struct generic_pm_domain_data { struct gpd_dev_ops ops; struct gpd_timing_data td; bool need_restore; + bool always_on; }; static inline struct generic_pm_domain_data *to_gpd_data(struct pm_domain_data *pdd) @@ -125,6 +126,7 @@ static inline int pm_genpd_add_device(struct generic_pm_domain *genpd, extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, struct device *dev); +extern void pm_genpd_dev_always_on(struct device *dev, bool val); extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *new_subdomain); extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, @@ -163,6 +165,7 @@ static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd, { return -ENOSYS; } +static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {} static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *new_sd) { diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 93f4d03..fcabfb4 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -202,7 +202,8 @@ struct rtc_device struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */ int pie_enabled; struct work_struct irqwork; - + /* Some hardware can't support UIE mode */ + int uie_unsupported; #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL struct work_struct uie_task; diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index dc4e345..fe73eb8 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -118,9 +118,9 @@ /* Queue Algorithm Modifier default for restricted reordering in control mode page */ #define DA_EMULATE_REST_REORD 0 +#define SE_INQUIRY_BUF 512 #define SE_MODE_PAGE_BUF 512 - /* struct se_hba->hba_flags */ enum hba_flags_table { HBA_FLAGS_INTERNAL_USE = 0x01, diff --git a/kernel/futex.c b/kernel/futex.c index 1614be2..0677023 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -2641,6 +2641,16 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, } switch (cmd) { + case FUTEX_LOCK_PI: + case FUTEX_UNLOCK_PI: + case FUTEX_TRYLOCK_PI: + case FUTEX_WAIT_REQUEUE_PI: + case FUTEX_CMP_REQUEUE_PI: + if (!futex_cmpxchg_enabled) + return -ENOSYS; + } + + switch (cmd) { case FUTEX_WAIT: val3 = FUTEX_BITSET_MATCH_ANY; case FUTEX_WAIT_BITSET: @@ -2661,16 +2671,13 @@ long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, ret = futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); break; case FUTEX_LOCK_PI: - if (futex_cmpxchg_enabled) - ret = futex_lock_pi(uaddr, flags, val, timeout, 0); + ret = futex_lock_pi(uaddr, flags, val, timeout, 0); break; case FUTEX_UNLOCK_PI: - if (futex_cmpxchg_enabled) - ret = futex_unlock_pi(uaddr, flags); + ret = futex_unlock_pi(uaddr, flags); break; case FUTEX_TRYLOCK_PI: - if (futex_cmpxchg_enabled) - ret = futex_lock_pi(uaddr, flags, 0, timeout, 1); + ret = futex_lock_pi(uaddr, flags, 0, timeout, 1); break; case FUTEX_WAIT_REQUEUE_PI: val3 = FUTEX_BITSET_MATCH_ANY; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index fb7db75..25784d6 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type) return -EINVAL; type &= IRQ_TYPE_SENSE_MASK; - if (type != IRQ_TYPE_NONE) - ret = __irq_set_trigger(desc, irq, type); + ret = __irq_set_trigger(desc, irq, type); irq_put_desc_busunlock(desc, flags); return ret; } diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0f0d470..6ffd419 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -773,7 +773,7 @@ static int irq_thread(void *data) struct irqaction *action); int wake; - if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, + if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD, &action->thread_flags)) handler_fn = irq_forced_thread_fn; else diff --git a/kernel/module.c b/kernel/module.c index 2c93276..3d56b6f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2380,8 +2380,7 @@ static int copy_and_check(struct load_info *info, return -ENOEXEC; /* Suck in entire file: we'll want most of it. */ - /* vmalloc barfs on "unusual" numbers. Check here */ - if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL) + if ((hdr = vmalloc(len)) == NULL) return -ENOMEM; if (copy_from_user(hdr, umod, len) != 0) { diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index 6d6d288..7bef755 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -616,7 +616,7 @@ int hibernate(void) /* Allocate memory management structures */ error = create_basic_memory_bitmaps(); if (error) - goto Exit; + goto Enable_umh; printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync(); @@ -624,7 +624,7 @@ int hibernate(void) error = freeze_processes(); if (error) - goto Finish; + goto Free_bitmaps; error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM); if (error) @@ -657,8 +657,9 @@ int hibernate(void) Thaw: thaw_processes(); - Finish: + Free_bitmaps: free_basic_memory_bitmaps(); + Enable_umh: usermodehelper_enable(); Exit: pm_notifier_call_chain(PM_POST_HIBERNATION); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index f6117a4..4b85a7a 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -275,7 +275,7 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long secs) time_status |= STA_MODE; - return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); + return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs); } static void ntp_update_offset(long offset) diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index e66e9b6..75cbdb5 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -29,16 +29,17 @@ u64 uevent_seqnum; char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; -static DEFINE_SPINLOCK(sequence_lock); #ifdef CONFIG_NET struct uevent_sock { struct list_head list; struct sock *sk; }; static LIST_HEAD(uevent_sock_list); -static DEFINE_MUTEX(uevent_sock_mutex); #endif +/* This lock protects uevent_seqnum and uevent_sock_list */ +static DEFINE_MUTEX(uevent_sock_mutex); + /* the strings here must match the enum in include/linux/kobject.h */ static const char *kobject_actions[] = { [KOBJ_ADD] = "add", @@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, struct kobject *top_kobj; struct kset *kset; const struct kset_uevent_ops *uevent_ops; - u64 seq; int i = 0; int retval = 0; #ifdef CONFIG_NET @@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, else if (action == KOBJ_REMOVE) kobj->state_remove_uevent_sent = 1; + mutex_lock(&uevent_sock_mutex); /* we will send an event, so request a new sequence number */ - spin_lock(&sequence_lock); - seq = ++uevent_seqnum; - spin_unlock(&sequence_lock); - retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq); - if (retval) + retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum); + if (retval) { + mutex_unlock(&uevent_sock_mutex); goto exit; + } #if defined(CONFIG_NET) /* send netlink message */ - mutex_lock(&uevent_sock_mutex); list_for_each_entry(ue_sk, &uevent_sock_list, list) { struct sock *uevent_sock = ue_sk->sk; struct sk_buff *skb; @@ -290,8 +289,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, } else retval = -ENOMEM; } - mutex_unlock(&uevent_sock_mutex); #endif + mutex_unlock(&uevent_sock_mutex); /* call uevent_helper, usually only enabled during early boot */ if (uevent_helper[0] && !kobj_usermode_filter(kobj)) { diff --git a/mm/bootmem.c b/mm/bootmem.c index 668e94d..0131170 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -766,14 +766,13 @@ void * __init alloc_bootmem_section(unsigned long size, unsigned long section_nr) { bootmem_data_t *bdata; - unsigned long pfn, goal, limit; + unsigned long pfn, goal; pfn = section_nr_to_pfn(section_nr); goal = pfn << PAGE_SHIFT; - limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; - return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); + return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0); } #endif diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 58a08fc..cd412fc 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5234,6 +5234,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd, spinlock_t *ptl; split_huge_page_pmd(walk->mm, pmd); + if (pmd_trans_unstable(pmd)) + return 0; pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) @@ -5396,6 +5398,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd, spinlock_t *ptl; split_huge_page_pmd(walk->mm, pmd); + if (pmd_trans_unstable(pmd)) + return 0; retry: pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; addr += PAGE_SIZE) { diff --git a/mm/memory.c b/mm/memory.c index fa2f04e..10b4dda 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1247,16 +1247,24 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, do { next = pmd_addr_end(addr, end); if (pmd_trans_huge(*pmd)) { - if (next-addr != HPAGE_PMD_SIZE) { + if (next - addr != HPAGE_PMD_SIZE) { VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem)); split_huge_page_pmd(vma->vm_mm, pmd); } else if (zap_huge_pmd(tlb, vma, pmd, addr)) - continue; + goto next; /* fall through */ } - if (pmd_none_or_clear_bad(pmd)) - continue; + /* + * Here there can be other concurrent MADV_DONTNEED or + * trans huge page faults running, and if the pmd is + * none or trans huge it can change under us. This is + * because MADV_DONTNEED holds the mmap_sem in read + * mode. + */ + if (pmd_none_or_trans_huge_or_clear_bad(pmd)) + goto next; next = zap_pte_range(tlb, vma, pmd, addr, next, details); +next: cond_resched(); } while (pmd++, addr = next, addr != end); diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 47296fe..0a37570 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -512,7 +512,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud, do { next = pmd_addr_end(addr, end); split_huge_page_pmd(vma->vm_mm, pmd); - if (pmd_none_or_clear_bad(pmd)) + if (pmd_none_or_trans_huge_or_clear_bad(pmd)) continue; if (check_pte_range(vma, pmd, addr, next, nodes, flags, private)) diff --git a/mm/mincore.c b/mm/mincore.c index 636a868..936b4ce 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -164,7 +164,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud, } /* fall through */ } - if (pmd_none_or_clear_bad(pmd)) + if (pmd_none_or_trans_huge_or_clear_bad(pmd)) mincore_unmapped_range(vma, addr, next, vec); else mincore_pte_range(vma, pmd, addr, next, vec); diff --git a/mm/pagewalk.c b/mm/pagewalk.c index 2f5cf10..aa9701e 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -59,7 +59,7 @@ again: continue; split_huge_page_pmd(walk->mm, pmd); - if (pmd_none_or_clear_bad(pmd)) + if (pmd_none_or_trans_huge_or_clear_bad(pmd)) goto again; err = walk_pte_range(pmd, addr, next, walk); if (err) diff --git a/mm/slub.c b/mm/slub.c index 4907563..0342a5d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -3929,13 +3929,14 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, if (kmem_cache_open(s, n, size, align, flags, ctor)) { list_add(&s->list, &slab_caches); + up_write(&slub_lock); if (sysfs_slab_add(s)) { + down_write(&slub_lock); list_del(&s->list); kfree(n); kfree(s); goto err; } - up_write(&slub_lock); return s; } kfree(n); diff --git a/mm/sparse.c b/mm/sparse.c index 61d7cde..a8bc7d3 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -353,29 +353,21 @@ static void __init sparse_early_usemaps_alloc_node(unsigned long**usemap_map, usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid), usemap_count); - if (usemap) { - for (pnum = pnum_begin; pnum < pnum_end; pnum++) { - if (!present_section_nr(pnum)) - continue; - usemap_map[pnum] = usemap; - usemap += size; + if (!usemap) { + usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count); + if (!usemap) { + printk(KERN_WARNING "%s: allocation failed\n", __func__); + return; } - return; } - usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count); - if (usemap) { - for (pnum = pnum_begin; pnum < pnum_end; pnum++) { - if (!present_section_nr(pnum)) - continue; - usemap_map[pnum] = usemap; - usemap += size; - check_usemap_section_nr(nodeid, usemap_map[pnum]); - } - return; + for (pnum = pnum_begin; pnum < pnum_end; pnum++) { + if (!present_section_nr(pnum)) + continue; + usemap_map[pnum] = usemap; + usemap += size; + check_usemap_section_nr(nodeid, usemap_map[pnum]); } - - printk(KERN_WARNING "%s: allocation failed\n", __func__); } #ifndef CONFIG_SPARSEMEM_VMEMMAP diff --git a/mm/swapfile.c b/mm/swapfile.c index d999f09..f31b29d 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud, pmd = pmd_offset(pud, addr); do { next = pmd_addr_end(addr, end); - if (unlikely(pmd_trans_huge(*pmd))) - continue; - if (pmd_none_or_clear_bad(pmd)) + if (pmd_none_or_trans_huge_or_clear_bad(pmd)) continue; ret = unuse_pte_range(vma, pmd, addr, next, entry, page); if (ret) diff --git a/mm/vmscan.c b/mm/vmscan.c index c52b235..a3a738a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1643,18 +1643,6 @@ static void move_active_pages_to_lru(struct zone *zone, unsigned long pgmoved = 0; struct page *page; - if (buffer_heads_over_limit) { - spin_unlock_irq(&zone->lru_lock); - list_for_each_entry(page, list, lru) { - if (page_has_private(page) && trylock_page(page)) { - if (page_has_private(page)) - try_to_release_page(page, 0); - unlock_page(page); - } - } - spin_lock_irq(&zone->lru_lock); - } - while (!list_empty(list)) { struct lruvec *lruvec; @@ -1737,6 +1725,14 @@ static void shrink_active_list(unsigned long nr_to_scan, continue; } + if (unlikely(buffer_heads_over_limit)) { + if (page_has_private(page) && trylock_page(page)) { + if (page_has_private(page)) + try_to_release_page(page, 0); + unlock_page(page); + } + } + if (page_referenced(page, 0, mz->mem_cgroup, &vm_flags)) { nr_rotated += hpage_nr_pages(page); /* @@ -2235,6 +2231,14 @@ static bool shrink_zones(int priority, struct zonelist *zonelist, unsigned long nr_soft_scanned; bool aborted_reclaim = false; + /* + * If the number of buffer_heads in the machine exceeds the maximum + * allowed level, force direct reclaim to scan the highmem zone as + * highmem pages could be pinning lowmem pages storing buffer_heads + */ + if (buffer_heads_over_limit) + sc->gfp_mask |= __GFP_HIGHMEM; + for_each_zone_zonelist_nodemask(zone, z, zonelist, gfp_zone(sc->gfp_mask), sc->nodemask) { if (!populated_zone(zone)) @@ -2724,6 +2728,17 @@ loop_again: */ age_active_anon(zone, &sc, priority); + /* + * If the number of buffer_heads in the machine + * exceeds the maximum allowed level and this node + * has a highmem zone, force kswapd to reclaim from + * it to relieve lowmem pressure. + */ + if (buffer_heads_over_limit && is_highmem_idx(i)) { + end_zone = i; + break; + } + if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone), 0, 0)) { end_zone = i; @@ -2786,7 +2801,8 @@ loop_again: (zone->present_pages + KSWAPD_ZONE_BALANCE_GAP_RATIO-1) / KSWAPD_ZONE_BALANCE_GAP_RATIO); - if (!zone_watermark_ok_safe(zone, order, + if ((buffer_heads_over_limit && is_highmem_idx(i)) || + !zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) + balance_gap, end_zone, 0)) { shrink_zone(priority, zone, &sc); diff --git a/net/core/dev.c b/net/core/dev.c index 6ca32f6..a4bf943 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3569,7 +3569,8 @@ EXPORT_SYMBOL(napi_gro_receive); static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) { __skb_pull(skb, skb_headlen(skb)); - skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb)); + /* restore the reserve we had after netdev_alloc_skb_ip_align() */ + skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb)); skb->vlan_tci = 0; skb->dev = napi->dev; skb->skb_iif = 0; diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index f965dce..5c30296 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1133,6 +1133,8 @@ static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { .len = sizeof(struct ifla_vf_vlan) }, [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, .len = sizeof(struct ifla_vf_tx_rate) }, + [IFLA_VF_SPOOFCHK] = { .type = NLA_BINARY, + .len = sizeof(struct ifla_vf_spoofchk) }, }; static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index d97e071..ea58e27a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1416,8 +1416,9 @@ alloc_new_skb: */ skb->ip_summed = csummode; skb->csum = 0; - /* reserve for fragmentation */ - skb_reserve(skb, hh_len+sizeof(struct frag_hdr)); + /* reserve for fragmentation and ipsec header */ + skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + + dst_exthdrlen); if (sk->sk_type == SOCK_DGRAM) skb_shinfo(skb)->tx_flags = tx_flags; @@ -1425,9 +1426,9 @@ alloc_new_skb: /* * Find where to start putting bytes */ - data = skb_put(skb, fraglen + dst_exthdrlen); - skb_set_network_header(skb, exthdrlen + dst_exthdrlen); - data += fragheaderlen + dst_exthdrlen; + data = skb_put(skb, fraglen); + skb_set_network_header(skb, exthdrlen); + data += fragheaderlen; skb->transport_header = (skb->network_header + fragheaderlen); if (fraggap) { diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 22b7664..4d5915d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2461,8 +2461,12 @@ static int rt6_fill_node(struct net *net, rcu_read_lock(); n = dst_get_neighbour_noref(&rt->dst); - if (n) - NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key); + if (n) { + if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { + rcu_read_unlock(); + goto nla_put_failure; + } + } rcu_read_unlock(); if (rt->dst.dev) diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 8a90d75..b1bd16f 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -915,7 +915,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr, goto end_put_sess; } - inet = inet_sk(sk); + inet = inet_sk(tunnel->sock); if (tunnel->version == 2) { struct sockaddr_pppol2tp sp; len = sizeof(sp); diff --git a/net/rds/send.c b/net/rds/send.c index e2d63c5..96531d4 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -935,7 +935,6 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, /* Mirror Linux UDP mirror of BSD error message compatibility */ /* XXX: Perhaps MSG_MORE someday */ if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) { - printk(KERN_INFO "msg_flags 0x%08X\n", msg->msg_flags); ret = -EOPNOTSUPP; goto out; } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 465df9a..8c6598e 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -828,6 +828,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf, { ssize_t ret; + if (count == 0) + return -EINVAL; if (copy_from_user(kaddr, buf, count)) return -EFAULT; kaddr[count] = '\0'; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 3341d89..8efd96c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -501,14 +501,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next); */ void rpc_wake_up(struct rpc_wait_queue *queue) { - struct rpc_task *task, *next; struct list_head *head; spin_lock_bh(&queue->lock); head = &queue->tasks[queue->maxpriority]; for (;;) { - list_for_each_entry_safe(task, next, head, u.tk_wait.list) + while (!list_empty(head)) { + struct rpc_task *task; + task = list_first_entry(head, + struct rpc_task, + u.tk_wait.list); rpc_wake_up_task_queue_locked(queue, task); + } if (head == &queue->tasks[0]) break; head--; @@ -526,13 +530,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up); */ void rpc_wake_up_status(struct rpc_wait_queue *queue, int status) { - struct rpc_task *task, *next; struct list_head *head; spin_lock_bh(&queue->lock); head = &queue->tasks[queue->maxpriority]; for (;;) { - list_for_each_entry_safe(task, next, head, u.tk_wait.list) { + while (!list_empty(head)) { + struct rpc_task *task; + task = list_first_entry(head, + struct rpc_task, + u.tk_wait.list); task->tk_status = status; rpc_wake_up_task_queue_locked(queue, task); } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 39e02c5..2f6d11d 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -167,7 +167,7 @@ static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq) } if (xfrm_aevent_is_on(xs_net(x))) - xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); + x->repl->notify(x, XFRM_REPLAY_UPDATE); } static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb) @@ -279,7 +279,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq) replay_esn->bmp[nr] |= (1U << bitnr); if (xfrm_aevent_is_on(xs_net(x))) - xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); + x->repl->notify(x, XFRM_REPLAY_UPDATE); } static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event) @@ -473,7 +473,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) replay_esn->bmp[nr] |= (1U << bitnr); if (xfrm_aevent_is_on(xs_net(x))) - xfrm_replay_notify(x, XFRM_REPLAY_UPDATE); + x->repl->notify(x, XFRM_REPLAY_UPDATE); } static struct xfrm_replay xfrm_replay_legacy = { diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 4f554f2..063298a 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -9,7 +9,7 @@ config IMA select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_SHA1 - select TCG_TPM if !S390 && !UML + select TCG_TPM if HAS_IOMEM && !UML select TCG_TIS if TCG_TPM help The Trusted Computing Group(TCG) runtime Integrity diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index c1da422..b58b4b1 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -385,8 +385,8 @@ error: static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen) { static unsigned int alsa_rates[] = { - 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200, - 96000, 176400, 192000, 384000 + 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, + 88200, 96000, 176400, 192000, 384000 }; int i, j; diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index a5d4e80..dc5764d 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -395,7 +395,8 @@ static int p1022_ds_probe(struct platform_device *pdev) } if (strcasecmp(sprop, "i2s-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_I2S; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; @@ -412,31 +413,38 @@ static int p1022_ds_probe(struct platform_device *pdev) } mdata->clk_frequency = be32_to_cpup(iprop); } else if (strcasecmp(sprop, "i2s-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_I2S; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS; mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "lj-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "lj-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_LEFT_J; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS; mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "rj-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "rj-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS; mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else if (strcasecmp(sprop, "ac97-slave") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_AC97; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM; mdata->codec_clk_direction = SND_SOC_CLOCK_OUT; mdata->cpu_clk_direction = SND_SOC_CLOCK_IN; } else if (strcasecmp(sprop, "ac97-master") == 0) { - mdata->dai_format = SND_SOC_DAIFMT_AC97; + mdata->dai_format = SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS; mdata->codec_clk_direction = SND_SOC_CLOCK_IN; mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT; } else { diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index a57cfbc..29792af 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, return 0; } +static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream, + struct ssp_device *ssp, int value) +{ + uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0); + uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1); + uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP); + uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR); + + if (value && (sscr0 & SSCR0_SSE)) + pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (value) + sscr1 |= SSCR1_TSRE; + else + sscr1 &= ~SSCR1_TSRE; + } else { + if (value) + sscr1 |= SSCR1_RSRE; + else + sscr1 &= ~SSCR1_RSRE; + } + + pxa_ssp_write_reg(ssp, SSCR1, sscr1); + + if (value) { + pxa_ssp_write_reg(ssp, SSSR, sssr); + pxa_ssp_write_reg(ssp, SSPSP, sspsp); + pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE); + } +} + static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { @@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, pxa_ssp_enable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - val = pxa_ssp_read_reg(ssp, SSCR1); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val |= SSCR1_TSRE; - else - val |= SSCR1_RSRE; - pxa_ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_set_running_bit(substream, ssp, 1); val = pxa_ssp_read_reg(ssp, SSSR); pxa_ssp_write_reg(ssp, SSSR, val); break; case SNDRV_PCM_TRIGGER_START: - val = pxa_ssp_read_reg(ssp, SSCR1); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val |= SSCR1_TSRE; - else - val |= SSCR1_RSRE; - pxa_ssp_write_reg(ssp, SSCR1, val); - pxa_ssp_enable(ssp); + pxa_ssp_set_running_bit(substream, ssp, 1); break; case SNDRV_PCM_TRIGGER_STOP: - val = pxa_ssp_read_reg(ssp, SSCR1); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val &= ~SSCR1_TSRE; - else - val &= ~SSCR1_RSRE; - pxa_ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_set_running_bit(substream, ssp, 0); break; case SNDRV_PCM_TRIGGER_SUSPEND: pxa_ssp_disable(ssp); break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - val = pxa_ssp_read_reg(ssp, SSCR1); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - val &= ~SSCR1_TSRE; - else - val &= ~SSCR1_RSRE; - pxa_ssp_write_reg(ssp, SSCR1, val); + pxa_ssp_set_running_bit(substream, ssp, 0); break; default: