diff options
131 files changed, 980 insertions, 602 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-hsi b/Documentation/ABI/testing/sysfs-bus-hsi new file mode 100644 index 0000000..1b1b282 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-hsi @@ -0,0 +1,19 @@ +What: /sys/bus/hsi +Date: April 2012 +KernelVersion: 3.4 +Contact: Carlos Chinea <carlos.chinea@nokia.com> +Description: + High Speed Synchronous Serial Interface (HSI) is a + serial interface mainly used for connecting application + engines (APE) with cellular modem engines (CMT) in cellular + handsets. + The bus will be populated with devices (hsi_clients) representing + the protocols available in the system. Bus drivers implement + those protocols. + +What: /sys/bus/hsi/devices/.../modalias +Date: April 2012 +KernelVersion: 3.4 +Contact: Carlos Chinea <carlos.chinea@nokia.com> +Description: Stores the same MODALIAS value emitted by uevent + Format: hsi:<hsi_client device name> diff --git a/MAINTAINERS b/MAINTAINERS index 1a2f8f5..bb76fc4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3592,6 +3592,7 @@ S: Supported F: drivers/net/wireless/iwlegacy/ INTEL WIRELESS WIFI LINK (iwlwifi) +M: Johannes Berg <johannes.berg@intel.com> M: Wey-Yi Guy <wey-yi.w.guy@intel.com> M: Intel Linux Wireless <ilw@linux.intel.com> L: linux-wireless@vger.kernel.org @@ -7578,8 +7579,8 @@ F: Documentation/filesystems/xfs.txt F: fs/xfs/ XILINX AXI ETHERNET DRIVER -M: Ariane Keller <ariane.keller@tik.ee.ethz.ch> -M: Daniel Borkmann <daniel.borkmann@tik.ee.ethz.ch> +M: Anirudha Sarangi <anirudh@xilinx.com> +M: John Linn <John.Linn@xilinx.com> S: Maintained F: drivers/net/ethernet/xilinx/xilinx_axienet* diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 5b150af..fef42b2 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -118,14 +118,10 @@ static int twd_cpufreq_transition(struct notifier_block *nb, * The twd clock events must be reprogrammed to account for the new * frequency. The timer is local to a cpu, so cross-call to the * changing cpu. - * - * Only wait for it to finish, if the cpu is active to avoid - * deadlock when cpu1 is spinning on while(!cpu_active(cpu1)) during - * booting of that cpu. */ if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) smp_call_function_single(freqs->cpu, twd_update_frequency, - NULL, cpu_active(freqs->cpu)); + NULL, 1); return NOTIFY_OK; } diff --git a/arch/hexagon/kernel/dma.c b/arch/hexagon/kernel/dma.c index 3730221..0f2367c 100644 --- a/arch/hexagon/kernel/dma.c +++ b/arch/hexagon/kernel/dma.c @@ -22,6 +22,7 @@ #include <linux/bootmem.h> #include <linux/genalloc.h> #include <asm/dma-mapping.h> +#include <linux/module.h> struct dma_map_ops *dma_ops; EXPORT_SYMBOL(dma_ops); diff --git a/arch/hexagon/kernel/process.c b/arch/hexagon/kernel/process.c index 18c4f0b..ff02821 100644 --- a/arch/hexagon/kernel/process.c +++ b/arch/hexagon/kernel/process.c @@ -1,7 +1,7 @@ /* * Process creation support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -88,7 +88,7 @@ void (*idle_sleep)(void) = default_idle; void cpu_idle(void) { while (1) { - tick_nohz_stop_sched_tick(1); + tick_nohz_idle_enter(); local_irq_disable(); while (!need_resched()) { idle_sleep(); @@ -97,7 +97,7 @@ void cpu_idle(void) local_irq_disable(); } local_irq_enable(); - tick_nohz_restart_sched_tick(); + tick_nohz_idle_exit(); schedule(); } } diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c index 32342de..96c3b2c 100644 --- a/arch/hexagon/kernel/ptrace.c +++ b/arch/hexagon/kernel/ptrace.c @@ -28,6 +28,7 @@ #include <linux/ptrace.h> #include <linux/regset.h> #include <linux/user.h> +#include <linux/elf.h> #include <asm/user.h> diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 9b44a9e..1298141 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -1,7 +1,7 @@ /* * SMP support for Hexagon * - * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved. + * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,6 +28,7 @@ #include <linux/sched.h> #include <linux/smp.h> #include <linux/spinlock.h> +#include <linux/cpu.h> #include <asm/time.h> /* timer_interrupt */ #include <asm/hexagon_vm.h> @@ -177,7 +178,12 @@ void __cpuinit start_secondary(void) printk(KERN_INFO "%s cpu %d\n", __func__, current_thread_info()->cpu); + notify_cpu_starting(cpu); + + ipi_call_lock(); set_cpu_online(cpu, true); + ipi_call_unlock(); + local_irq_enable(); cpu_idle(); diff --git a/arch/hexagon/kernel/time.c b/arch/hexagon/kernel/time.c index 6bee15c..5d9b33b 100644 --- a/arch/hexagon/kernel/time.c +++ b/arch/hexagon/kernel/time.c @@ -28,6 +28,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/of_irq.h> +#include <linux/module.h> #include <asm/timer-regs.h> #include <asm/hexagon_vm.h> diff --git a/arch/hexagon/kernel/vdso.c b/arch/hexagon/kernel/vdso.c index f212a45..5d39f42 100644 --- a/arch/hexagon/kernel/vdso.c +++ b/arch/hexagon/kernel/vdso.c @@ -21,6 +21,7 @@ #include <linux/err.h> #include <linux/mm.h> #include <linux/vmalloc.h> +#include <linux/binfmts.h> #include <asm/vdso.h> diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi new file mode 100644 index 0000000..1cf0b77 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/pq3-mpic-message-B.dtsi @@ -0,0 +1,43 @@ +/* + * PQ3 MPIC Message (Group B) device tree stub [ controller @ offset 0x42400 ] + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +message@42400 { + compatible = "fsl,mpic-v3.1-msgr"; + reg = <0x42400 0x200>; + interrupts = < + 0xb4 2 0 0 + 0xb5 2 0 0 + 0xb6 2 0 0 + 0xb7 2 0 0>; +}; diff --git a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi index fdedf7b..71c30eb 100644 --- a/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi +++ b/arch/powerpc/boot/dts/fsl/pq3-mpic.dtsi @@ -53,6 +53,16 @@ timer@41100 { 3 0 3 0>; }; +message@41400 { + compatible = "fsl,mpic-v3.1-msgr"; + reg = <0x41400 0x200>; + interrupts = < + 0xb0 2 0 0 + 0xb1 2 0 0 + 0xb2 2 0 0 + 0xb3 2 0 0>; +}; + msi@41600 { compatible = "fsl,mpic-msi"; reg = <0x41600 0x80>; diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h index c65b929..c9f698a 100644 --- a/arch/powerpc/include/asm/mpic.h +++ b/arch/powerpc/include/asm/mpic.h @@ -275,9 +275,6 @@ struct mpic unsigned int isu_mask; /* Number of sources */ unsigned int num_sources; - /* default senses array */ - unsigned char *senses; - unsigned int senses_count; /* vector numbers used for internal sources (ipi/timers) */ unsigned int ipi_vecs[4]; @@ -415,21 +412,6 @@ extern struct mpic *mpic_alloc(struct device_node *node, extern void mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, phys_addr_t phys_addr); -/* Set default sense codes - * - * @mpic: controller - * @senses: array of sense codes - * @count: size of above array - * - * Optionally provide an array (indexed on hardware interrupt numbers - * for this MPIC) of default sense codes for the chip. Those are linux - * sense codes IRQ_TYPE_* - * - * The driver gets ownership of the pointer, don't dispose of it or - * anything like that. __init only. - */ -extern void mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count); - /* Initialize the controller. After this has been called, none of the above * should be called again for this mpic diff --git a/arch/powerpc/include/asm/mpic_msgr.h b/arch/powerpc/include/asm/mpic_msgr.h index 3ec37dc..326d33c 100644 --- a/arch/powerpc/include/asm/mpic_msgr.h +++ b/arch/powerpc/include/asm/mpic_msgr.h @@ -13,6 +13,7 @@ #include <linux/types.h> #include <linux/spinlock.h> +#include <asm/smp.h> struct mpic_msgr { u32 __iomem *base; diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index b86faa9..8a97aa7 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h @@ -15,11 +15,6 @@ #ifndef __ASM_POWERPC_REG_BOOKE_H__ #define __ASM_POWERPC_REG_BOOKE_H__ -#ifdef CONFIG_BOOKE_WDT -extern u32 booke_wdt_enabled; -extern u32 booke_wdt_period; -#endif /* CONFIG_BOOKE_WDT */ - /* Machine State Register (MSR) Fields */ #define MSR_GS (1<<28) /* Guest state */ #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 9825f29..ec8a53f 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -150,6 +150,9 @@ notrace void __init machine_init(u64 dt_ptr) } #ifdef CONFIG_BOOKE_WDT +extern u32 booke_wdt_enabled; +extern u32 booke_wdt_period; + /* Checks wdt=x and wdt_period=xx command-line option */ notrace int __init early_parse_wdt(char *p) { diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c index 9fef530..67dac22 100644 --- a/arch/powerpc/platforms/85xx/common.c +++ b/arch/powerpc/platforms/85xx/common.c @@ -21,6 +21,12 @@ static struct of_device_id __initdata mpc85xx_common_ids[] = { { .compatible = "fsl,qe", }, { .compatible = "fsl,cpm2", }, { .compatible = "fsl,srio", }, + /* So that the DMA channel nodes can be probed individually: */ + { .compatible = "fsl,eloplus-dma", }, + /* For the PMC driver */ + { .compatible = "fsl,mpc8548-guts", }, + /* Probably unnecessary? */ + { .compatible = "gpio-leds", }, {}, }; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 9a6f044..d208ebc 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -399,12 +399,6 @@ static int __init board_fixups(void) machine_arch_initcall(mpc8568_mds, board_fixups); machine_arch_initcall(mpc8569_mds, board_fixups); -static struct of_device_id mpc85xx_ids[] = { - { .compatible = "fsl,mpc8548-guts", }, - { .compatible = "gpio-leds", }, - {}, -}; - static int __init mpc85xx_publish_devices(void) { if (machine_is(mpc8568_mds)) @@ -412,10 +406,7 @@ static int __init mpc85xx_publish_devices(void) if (machine_is(mpc8569_mds)) simple_gpiochip_init("fsl,mpc8569mds-bcsr-gpio"); - mpc85xx_common_publish_devices(); - of_platform_bus_probe(NULL, mpc85xx_ids, NULL); - - return 0; + return mpc85xx_common_publish_devices(); } machine_device_initcall(mpc8568_mds, mpc85xx_publish_devices); diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index e74b7cd..f700c81 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -460,18 +460,7 @@ static void __init p1022_ds_setup_arch(void) pr_info("Freescale P1022 DS reference board\n"); } -static struct of_device_id __initdata p1022_ds_ids[] = { - /* So that the DMA channel nodes can be probed individually: */ - { .compatible = "fsl,eloplus-dma", }, - {}, -}; - -static int __init p1022_ds_publish_devices(void) -{ - mpc85xx_common_publish_devices(); - return of_platform_bus_probe(NULL, p1022_ds_ids, NULL); -} -machine_device_initcall(p1022_ds, p1022_ds_publish_devices); +machine_device_initcall(p1022_ds, mpc85xx_common_publish_devices); machine_arch_initcall(p1022_ds, swiotlb_setup_bus_notifier); diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 996c5ff..03685a3 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c @@ -366,11 +366,20 @@ static void kw_i2c_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&host->lock, flags); + + /* + * If the timer is pending, that means we raced with the + * irq, in which case we just return + */ + if (timer_pending(&host->timeout_timer)) + goto skip; + kw_i2c_handle_interrupt(host, kw_read_reg(reg_isr)); if (host->state != state_idle) { host->timeout_timer.expires = jiffies + KW_POLL_TIMEOUT; add_timer(&host->timeout_timer); } + skip: spin_unlock_irqrestore(&host->lock, flags); } diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 309d38e..a75e37d 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1076,7 +1076,7 @@ static void eeh_add_device_late(struct pci_dev *dev) pr_debug("EEH: Adding device %s\n", pci_name(dev)); dn = pci_device_to_OF_node(dev); - edev = pci_dev_to_eeh_dev(dev); + edev = of_node_to_eeh_dev(dn); if (edev->pdev == dev) { pr_debug("EEH: Already referenced !\n"); return; diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 9ac71eb..395af13 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -604,18 +604,14 @@ static struct mpic *mpic_find(unsigned int irq) } /* Determine if the linux irq is an IPI */ -static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int irq) +static unsigned int mpic_is_ipi(struct mpic *mpic, unsigned int src) { - unsigned int src = virq_to_hw(irq); - return (src >= mpic->ipi_vecs[0] && src <= mpic->ipi_vecs[3]); } /* Determine if the linux irq is a timer */ -static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int irq) +static unsigned int mpic_is_tm(struct mpic *mpic, unsigned int src) { - unsigned int src = virq_to_hw(irq); - return (src >= mpic->timer_vecs[0] && src <= mpic->timer_vecs[7]); } @@ -876,21 +872,45 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type) if (src >= mpic->num_sources) return -EINVAL; + vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); + + /* We don't support "none" type */ if (flow_type == IRQ_TYPE_NONE) - if (mpic->senses && src < mpic->senses_count) - flow_type = mpic->senses[src]; - if (flow_type == IRQ_TYPE_NONE) - flow_type = IRQ_TYPE_LEVEL_LOW; + flow_type = IRQ_TYPE_DEFAULT; + + /* Default: read HW settings */ + if (flow_type == IRQ_TYPE_DEFAULT) { + switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) | + MPIC_INFO(VECPRI_SENSE_MASK))) { + case MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE): + flow_type = IRQ_TYPE_EDGE_RISING; + break; + case MPIC_INFO(VECPRI_SENSE_EDGE) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE): + flow_type = IRQ_TYPE_EDGE_FALLING; + break; + case MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_POSITIVE): + flow_type = IRQ_TYPE_LEVEL_HIGH; + break; + case MPIC_INFO(VECPRI_SENSE_LEVEL) | + MPIC_INFO(VECPRI_POLARITY_NEGATIVE): + flow_type = IRQ_TYPE_LEVEL_LOW; + break; + } + } + /* Apply to irq desc */ irqd_set_trigger_type(d, flow_type); + /* Apply to HW */ if (mpic_is_ht_interrupt(mpic, src)) vecpri = MPIC_VECPRI_POLARITY_POSITIVE | MPIC_VECPRI_SENSE_EDGE; else vecpri = mpic_type_to_vecpri(mpic, flow_type); - vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) | MPIC_INFO(VECPRI_SENSE_MASK)); vnew |= vecpri; @@ -1026,7 +1046,7 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq); /* Set default irq type */ - irq_set_irq_type(virq, IRQ_TYPE_NONE); + irq_set_irq_type(virq, IRQ_TYPE_DEFAULT); /* If the MPIC was reset, then all vectors have already been * initialized. Otherwise, a per source lazy initialization @@ -1417,12 +1437,6 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, mpic->num_sources = isu_first + mpic->isu_size; } -void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count) -{ - mpic->senses = senses; - mpic->senses_count = count; -} - void __init mpic_init(struct mpic *mpic) { int i, cpu; @@ -1555,12 +1569,12 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) return; raw_spin_lock_irqsave(&mpic_lock, flags); - if (mpic_is_ipi(mpic, irq)) { + if (mpic_is_ipi(mpic, src)) { reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) & ~MPIC_VECPRI_PRIORITY_MASK; mpic_ipi_write(src - mpic->ipi_vecs[0], reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); - } else if (mpic_is_tm(mpic, irq)) { + } else if (mpic_is_tm(mpic, src)) { reg = mpic_tm_read(src - mpic->timer_vecs[0]) & ~MPIC_VECPRI_PRIORITY_MASK; mpic_tm_write(src - mpic->timer_vecs[0], diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index 6e7fa38..483d8fa 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c @@ -27,6 +27,7 @@ static struct mpic_msgr **mpic_msgrs; static unsigned int mpic_msgr_count; +static DEFINE_RAW_SPINLOCK(msgrs_lock); static inline void _mpic_msgr_mer_write(struct mpic_msgr *msgr, u32 value) { @@ -56,12 +57,11 @@ struct mpic_msgr *mpic_msgr_get(unsigned int reg_num) if (reg_num >= mpic_msgr_count) return ERR_PTR(-ENODEV); - raw_spin_lock_irqsave(&msgr->lock, flags); - if (mpic_msgrs[reg_num]->in_use == MSGR_FREE) { - msgr = mpic_msgrs[reg_num]; + raw_spin_lock_irqsave(&msgrs_lock, flags); + msgr = mpic_msgrs[reg_num]; + if (msgr->in_use == MSGR_FREE) msgr->in_use = MSGR_INUSE; - } - raw_spin_unlock_irqrestore(&msgr->lock, flags); + raw_spin_unlock_irqrestore(&msgrs_lock, flags); return msgr; } @@ -228,7 +228,7 @@ static __devinit int mpic_msgr_probe(struct platform_device *dev) reg_number = block_number * MPIC_MSGR_REGISTERS_PER_BLOCK + i; msgr->base = msgr_block_addr + i * MPIC_MSGR_STRIDE; - msgr->mer = msgr->base + MPIC_MSGR_MER_OFFSET; + msgr->mer = (u32 *)((u8 *)msgr->base + MPIC_MSGR_MER_OFFSET); msgr->in_use = MSGR_FREE; msgr->num = i; raw_spin_lock_init(&msgr->lock); diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index a055993..c85e3ac 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -33,6 +33,9 @@ __HEAD ENTRY(startup_32) #ifdef CONFIG_EFI_STUB + jmp preferred_addr + + .balign 0x10 /* * We don't need the return address, so set up the stack so * efi_main() can find its arugments. @@ -41,12 +44,17 @@ ENTRY(startup_32) call efi_main cmpl $0, %eax - je preferred_addr movl %eax, %esi - call 1f + jne 2f 1: + /* EFI init failed, so hang. */ + hlt + jmp 1b +2: + call 3f +3: popl %eax - subl $1b, %eax + subl $3b, %eax subl BP_pref_address(%esi), %eax add BP_code32_start(%esi), %eax leal preferred_addr(%eax), %eax diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 558d76c..87e03a1 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -200,18 +200,28 @@ ENTRY(startup_64) * entire text+data+bss and hopefully all of memory. */ #ifdef CONFIG_EFI_STUB - pushq %rsi + /* + * The entry point for the PE/COFF executable is 0x210, so only + * legacy boot loaders will execute this jmp. + */ + jmp preferred_addr + + .org 0x210 mov %rcx, %rdi mov %rdx, %rsi call efi_main - popq %rsi - cmpq $0,%rax - je preferred_addr movq %rax,%rsi - call 1f + cmpq $0,%rax + jne 2f 1: + /* EFI init failed, so hang. */ + hlt + jmp 1b +2: + call 3f +3: popq %rax - subq $1b, %rax + subq $3b, %rax subq BP_pref_address(%rsi), %rax add BP_code32_start(%esi), %eax leaq preferred_addr(%rax), %rax diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index ed54976..24443a3 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -205,8 +205,13 @@ int main(int argc, char ** argv) put_unaligned_le32(file_sz, &buf[pe_header + 0x50]); #ifdef CONFIG_X86_32 - /* Address of entry point */ - put_unaligned_le32(i, &buf[pe_header + 0x28]); + /* + * Address of entry point. + * + * The EFI stub entry point is +16 bytes from the start of + * the .text section. + */ + put_unaligned_le32(i + 16, &buf[pe_header + 0x28]); /* .text size */ put_unaligned_le32(file_sz, &buf[pe_header + 0xb0]); @@ -217,9 +222,11 @@ int main(int argc, char ** argv) /* * Address of entry point. startup_32 is at the beginning and * the 64-bit entry point (startup_64) is always 512 bytes - * after. + * after. The EFI stub entry point is 16 bytes after that, as + * the first instruction allows legacy loaders to jump over + * the EFI stub initialisation */ - put_unaligned_le32(i + 512, &buf[pe_header + 0x28]); + put_unaligned_le32(i + 528, &buf[pe_header + 0x28]); /* .text size */ put_unaligned_le32(file_sz, &buf[pe_header + 0xc0]); diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h index 3427b77..7ef7c30 100644 --- a/arch/x86/include/asm/posix_types.h +++ b/arch/x86/include/asm/posix_types.h @@ -7,9 +7,9 @@ #else # ifdef __i386__ # include "posix_types_32.h" -# elif defined(__LP64__) -# include "posix_types_64.h" -# else +# elif defined(__ILP32__) # include "posix_types_x32.h" +# else +# include "posix_types_64.h" # endif #endif diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h index 4a08538..5ca71c0 100644 --- a/arch/x86/include/asm/sigcontext.h +++ b/arch/x86/include/asm/sigcontext.h @@ -257,7 +257,7 @@ struct sigcontext { __u64 oldmask; __u64 cr2; struct _fpstate __user *fpstate; /* zero when no FPU context */ -#ifndef __LP64__ +#ifdef __ILP32__ __u32 __fpstate_pad; #endif __u64 reserved1[8]; diff --git a/arch/x86/include/asm/siginfo.h b/arch/x86/include/asm/siginfo.h index fc1aa55..34c47b3 100644 --- a/arch/x86/include/asm/siginfo.h +++ b/arch/x86/include/asm/siginfo.h @@ -2,7 +2,13 @@ #define _ASM_X86_SIGINFO_H #ifdef __x86_64__ -# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +# ifdef __ILP32__ /* x32 */ +typedef long long __kernel_si_clock_t __attribute__((aligned(4))); +# define __ARCH_SI_CLOCK_T __kernel_si_clock_t +# define __ARCH_SI_ATTRIBUTES __attribute__((aligned(8))) +# else /* x86-64 */ +# define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) +# endif #endif #include <asm-generic/siginfo.h> diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 37cdc9d..4437001 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h @@ -63,10 +63,10 @@ #else # ifdef __i386__ # include <asm/unistd_32.h> -# elif defined(__LP64__) -# include <asm/unistd_64.h> -# else +# elif defined(__ILP32__) # include <asm/unistd_x32.h> +# else +# include <asm/unistd_64.h> # endif #endif diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index baaca8d..764b66a 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -195,6 +195,5 @@ extern struct x86_msi_ops x86_msi; extern void x86_init_noop(void); extern void x86_init_uint_noop(unsigned int unused); -extern void x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node); #endif diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c index 103b6ab..146a49c 100644 --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -24,6 +24,10 @@ unsigned long acpi_realmode_flags; static char temp_stack[4096]; #endif +asmlinkage void acpi_enter_s3(void) +{ + acpi_enter_sleep_state(3, wake_sleep_flags); +} /** * acpi_suspend_lowlevel - save kernel state * diff --git a/arch/x86/kernel/acpi/sleep.h b/arch/x86/kernel/acpi/sleep.h index 416d4be..d68677a 100644 --- a/arch/x86/kernel/acpi/sleep.h +++ b/arch/x86/kernel/acpi/sleep.h @@ -3,12 +3,16 @@ */ #include <asm/trampoline.h> +#include <linux/linkage.h> extern unsigned long saved_video_mode; extern long saved_magic; extern int wakeup_pmode_return; +extern u8 wake_sleep_flags; +extern asmlinkage void acpi_enter_s3(void); + extern unsigned long acpi_copy_wakeup_routine(unsigned long); extern void wakeup_long64(void); diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S index 13ab7205..7261083 100644 --- a/arch/x86/kernel/acpi/wakeup_32.S +++ b/arch/x86/kernel/acpi/wakeup_32.S @@ -74,9 +74,7 @@ restore_registers: ENTRY(do_suspend_lowlevel) call save_processor_state call save_registers - pushl $3 - call acpi_enter_sleep_state - addl $4, %esp + call acpi_enter_s3 # In case of S3 failure, we'll emerge here. Jump # to ret_point to recover diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 8ea5164..014d1d2 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -71,9 +71,7 @@ ENTRY(do_suspend_lowlevel) movq %rsi, saved_rsi addq $8, %rsp - movl $3, %edi - xorl %eax, %eax - call acpi_enter_sleep_state + call acpi_enter_s3 /* in case something went wrong, restore the machine status and go on */ jmp resume_point diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 11544d8..edc2448 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1637,9 +1637,11 @@ static int __init apic_verify(void) mp_lapic_addr = APIC_DEFAULT_PHYS_BASE; /* The BIOS may have set up the APIC at some other address */ - rdmsr(MSR_IA32_APICBASE, l, h); - if (l & MSR_IA32_APICBASE_ENABLE) - mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; + if (boot_cpu_data.x86 >= 6) { + rdmsr(MSR_IA32_APICBASE, l, h); + if (l & MSR_IA32_APICBASE_ENABLE) + mp_lapic_addr = l & MSR_IA32_APICBASE_BASE; + } pr_info("Found and enabled local APIC!\n"); return 0; @@ -1657,13 +1659,15 @@ int __init apic_force_enable(unsigned long addr) * MSR. This can only be done in software for Intel P6 or later * and AMD K7 (Model > 1) or later. */ - rdmsr(MSR_IA32_APICBASE, l, h); - if (!(l & MSR_IA32_APICBASE_ENABLE)) { - pr_info("Local APIC disabled by BIOS -- reenabling.\n"); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | addr; - wrmsr(MSR_IA32_APICBASE, l, h); - enabled_via_apicbase = 1; + if (boot_cpu_data.x86 >= 6) { + rdmsr(MSR_IA32_APICBASE, l, h); + if (!(l & MSR_IA32_APICBASE_ENABLE)) { + pr_info("Local APIC disabled by BIOS -- reenabling.\n"); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | addr; + wrmsr(MSR_IA32_APICBASE, l, h); + enabled_via_apicbase = 1; + } } return apic_verify(); } @@ -2209,10 +2213,12 @@ static void lapic_resume(void) * FIXME! This will be wrong if we ever support suspend on * SMP! We'll need to do this as part of the CPU restore! */ - rdmsr(MSR_IA32_APICBASE, l, h); - l &= ~MSR_IA32_APICBASE_BASE; - l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; - wrmsr(MSR_IA32_APICBASE, l, h); + if (boot_cpu_data.x86 >= 6) { + rdmsr(MSR_IA32_APICBASE, l, h); + l &= ~MSR_IA32_APICBASE_BASE; + l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr; + wrmsr(MSR_IA32_APICBASE, l, h); + } } maxlvt = lapic_get_maxlvt(); diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 899803e..23e7542 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -207,8 +207,11 @@ static void __init map_csrs(void) static void fixup_cpu_id(struct cpuinfo_x86 *c, int node) { - c->phys_proc_id = node; - per_cpu(cpu_llc_id, smp_processor_id()) = node; + + if (c->phys_proc_id != node) { + c->phys_proc_id = node; + per_cpu(cpu_llc_id, smp_processor_id()) = node; + } } static int __init numachip_system_init(void) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 0a44b90..1c67ca1 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -26,7 +26,8 @@ * contact AMD for precise details and a CPU swap. * * See http://www.multimania.com/poulot/k6bug.html - * http://www.amd.com/K6/k6docs/revgd.html + * and section 2.6.2 of "AMD-K6 Processor Revision Guide - Model 6" + * (Publication # 21266 Issue Date: August 1998) * * The following test is erm.. interesting. AMD neglected to up * the chip setting when fixing the bug but they also tweaked some @@ -94,7 +95,6 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) "system stability may be impaired when more than 32 MB are used.\n"); else printk(KERN_CONT "probably OK (after B9730xxxx).\n"); - printk(KERN_INFO "Please see http://membres.lycos.fr/poulot/k6bug.html\n"); } /* K6 with old style WHCR */ @@ -353,10 +353,11 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) node = per_cpu(cpu_llc_id, cpu); /* - * If core numbers are inconsistent, it's likely a multi-fabric platform, - * so invoke platform-specific handler + * On multi-fabric platform (e.g. Numascale NumaChip) a + * platform-specific handler needs to be called to fixup some + * IDs of the CPU. */ - if (c->phys_proc_id != node) + if (x86_cpuinit.fixup_cpu_id) x86_cpuinit.fixup_cpu_id(c, node); if (!node_online(node)) { diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 67e2583..cf79302 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1163,15 +1163,6 @@ static void dbg_restore_debug_regs(void) #endif /* ! CONFIG_KGDB */ /* - * Prints an error where the NUMA and configured core-number mismatch and the - * platform didn't override this to fix it up - */ -void __cpuinit x86_default_fixup_cpu_id(struct cpuinfo_x86 *c, int node) -{ - pr_err("NUMA core number %d differs from configured core number %d\n", node, c->phys_proc_id); -} - -/* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT * and IDT. We reload them nevertheless, this function acts as a diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 7734bcb..2d6e649 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -235,6 +235,7 @@ int init_fpu(struct task_struct *tsk) if (tsk_used_math(tsk)) { if (HAVE_HWFP && tsk == current) unlazy_fpu(tsk); + tsk->thread.fpu.last_cpu = ~0; return 0; } diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 73465aa..8a2ce8f 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -82,11 +82,6 @@ static int collect_cpu_info_amd(int cpu, struct cpu_signature *csig) { struct cpuinfo_x86 *c = &cpu_data(cpu); - if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { - pr_warning("CPU%d: family %d not supported\n", cpu, c->x86); - return -1; - } - csig->rev = c->microcode; pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev); @@ -380,6 +375,13 @@ static struct microcode_ops microcode_amd_ops = { struct microcode_ops * __init init_amd_microcode(void) { + struct cpuinfo_x86 *c = &cpu_data(0); + + if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) { + pr_warning("AMD CPU family 0x%x not supported\n", c->x86); + return NULL; + } + patch = (void *)get_zeroed_page(GFP_KERNEL); if (!patch) return NULL; diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 87a0f86..c9bda6d 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -419,10 +419,8 @@ static int mc_device_add(struct device *dev, struct subsys_interface *sif) if (err) return err; - if (microcode_init_cpu(cpu) == UCODE_ERROR) { - sysfs_remove_group(&dev->kobj, &mc_attr_group); + if (microcode_init_cpu(cpu) == UCODE_ERROR) return -EINVAL; - } return err; } @@ -528,11 +526,11 @@ static int __init microcode_init(void) microcode_ops = init_intel_microcode(); else if (c->x86_vendor == X86_VENDOR_AMD) microcode_ops = init_amd_microcode(); - - if (!microcode_ops) { + else pr_err("no support for this CPU vendor\n"); + + if (!microcode_ops) return -ENODEV; - } microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0); diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index e9f265f..9cf71d0 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -93,7 +93,6 @@ struct x86_init_ops x86_init __initdata = { struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { .early_percpu_clock_init = x86_init_noop, .setup_percpu_clockev = setup_secondary_APIC_clock, - .fixup_cpu_id = x86_default_fixup_cpu_id, }; static void default_nmi_init(void) { }; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 1d661b5..eb6fd23 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -28,23 +28,33 @@ #include "internal.h" #include "sleep.h" +u8 wake_sleep_flags = ACPI_NO_OPTIONAL_METHODS; static unsigned int gts, bfs; -module_param(gts, uint, 0644); -module_param(bfs, uint, 0644); -MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); -MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); - -static u8 wake_sleep_flags(void) +static int set_param_wake_flag(const char *val, struct kernel_param *kp) { - u8 flags = ACPI_NO_OPTIONAL_METHODS; + int ret = param_set_int(val, kp); - if (gts) - flags |= ACPI_EXECUTE_GTS; - if (bfs) - flags |= ACPI_EXECUTE_BFS; + if (ret) + return ret; - return flags; + if (kp->arg == (const char *)>s) { + if (gts) + wake_sleep_flags |= ACPI_EXECUTE_GTS; + else + wake_sleep_flags &= ~ACPI_EXECUTE_GTS; + } + if (kp->arg == (const char *)&bfs) { + if (bfs) + wake_sleep_flags |= ACPI_EXECUTE_BFS; + else + wake_sleep_flags &= ~ACPI_EXECUTE_BFS; + } + return ret; } +module_param_call(gts, set_param_wake_flag, param_get_int, >s, 0644); +module_param_call(bfs, set_param_wake_flag, param_get_int, &bfs, 0644); +MODULE_PARM_DESC(gts, "Enable evaluation of _GTS on suspend."); +MODULE_PARM_DESC(bfs, "Enable evaluation of _BFS on resume".); static u8 sleep_states[ACPI_S_STATE_COUNT]; @@ -263,7 +273,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) { acpi_status status = AE_OK; u32 acpi_state = acpi_target_sleep_state; - u8 flags = wake_sleep_flags(); int error; ACPI_FLUSH_CPU_CACHE(); @@ -271,7 +280,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) switch (acpi_state) { case ACPI_STATE_S1: barrier(); - status = acpi_enter_sleep_state(acpi_state, flags); + status = acpi_enter_sleep_state(acpi_state, wake_sleep_flags); break; case ACPI_STATE_S3: @@ -286,7 +295,7 @@ static int acpi_suspend_enter(suspend_state_t pm_state) acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(acpi_state, flags); + acpi_leave_sleep_state_prep(acpi_state, wake_sleep_flags); /* ACPI 3.0 specs (P62) says that it's the responsibility * of the OSPM to clear the status bit [ implying that the @@ -550,30 +559,27 @@ static int acpi_hibernation_begin(void) static int acpi_hibernation_enter(void) { - u8 flags = wake_sleep_flags(); acpi_status status = AE_OK; ACPI_FLUSH_CPU_CACHE(); /* This shouldn't return. If it returns, we have a problem */ - status = acpi_enter_sleep_state(ACPI_STATE_S4, flags); + status = acpi_enter_sleep_state(ACPI_STATE_S4, wake_sleep_flags); /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags); + acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); return ACPI_SUCCESS(status) ? 0 : -EFAULT; } static void acpi_hibernation_leave(void) { - u8 flags = wake_sleep_flags(); - /* * If ACPI is not enabled by the BIOS and the boot kernel, we need to * enable it here. */ acpi_enable(); /* Reprogram control registers and execute _BFS */ - acpi_leave_sleep_state_prep(ACPI_STATE_S4, flags); + acpi_leave_sleep_state_prep(ACPI_STATE_S4, wake_sleep_flags); /* Check the hardware signature */ if (facs && s4_hardware_signature != facs->hardware_signature) { printk(KERN_EMERG "ACPI: Hardware changed while hibernated, " @@ -828,12 +834,10 @@ static void acpi_power_off_prepare(void) static void acpi_power_off(void) { - u8 flags = wake_sleep_flags(); - /* acpi_sleep_prepare(ACPI_STATE_S5) should have already been called */ printk(KERN_DEBUG "%s called\n", __func__); local_irq_disable(); - acpi_enter_sleep_state(ACPI_STATE_S5, flags); + acpi_enter_sleep_state(ACPI_STATE_S5, wake_sleep_flags); } /* diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index cdcf75c..3e2a600 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -404,16 +404,19 @@ int bcma_sprom_get(struct bcma_bus *bus) return -EOPNOTSUPP; if (!bcma_sprom_ext_available(bus)) { + bool sprom_onchip; + /* * External SPROM takes precedence so check * on-chip OTP only when no external SPROM * is present. */ - if (bcma_sprom_onchip_available(bus)) { + sprom_onchip = bcma_sprom_onchip_available(bus); + if (sprom_onchip) { /* determine offset */ offset = bcma_sprom_onchip_offset(bus); } - if (!offset) { + if (!offset || !sprom_onchip) { /* * Maybe there is no SPROM on the device? * Now we ask the arch code if there is some sprom diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c index 88a050d..3ad91f6 100644 --- a/drivers/hsi/clients/hsi_char.c +++ b/drivers/hsi/clients/hsi_char.c @@ -123,7 +123,7 @@ struct hsc_client_data { static unsigned int hsc_major; /* Maximum buffer size that hsi_char will accept from userspace */ static unsigned int max_data_size = 0x1000; -module_param(max_data_size, uint, S_IRUSR | S_IWUSR); +module_param(max_data_size, uint, 0); MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)"); static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg, diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c index 4e2d79b..2d58f93 100644 --- a/drivers/hsi/hsi.c +++ b/drivers/hsi/hsi.c @@ -21,26 +21,13 @@ */ #include <linux/hsi/hsi.h> #include <linux/compiler.h> -#include <linux/rwsem.h> #include <linux/list.h> -#include <linux/spinlock.h> #include <linux/kobject.h> #include <linux/slab.h> #include <linux/string.h> +#include <linux/notifier.h> #include "hsi_core.h" -static struct device_type hsi_ctrl = { - .name = "hsi_controller", -}; - -static struct device_type hsi_cl = { - .name = "hsi_client", -}; - -static struct device_type hsi_port = { - .name = "hsi_port", -}; - static ssize_t modalias_show(struct device *dev, struct device_attribute *a __maybe_unused, char *buf) { @@ -54,8 +41,7 @@ static struct device_attribute hsi_bus_dev_attrs[] = { static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) { - if (dev->type == &hsi_cl) - add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); + add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); return 0; } @@ -80,12 +66,10 @@ static void hsi_client_release(struct device *dev) static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) { struct hsi_client *cl; - unsigned long flags; cl = kzalloc(sizeof(*cl), GFP_KERNEL); if (!cl) return; - cl->device.type = &hsi_cl; cl->tx_cfg = info->tx_cfg; cl->rx_cfg = info->rx_cfg; cl->device.bus = &hsi_bus_type; @@ -93,14 +77,11 @@ static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) cl->device.release = hsi_client_release; dev_set_name(&cl->device, info->name); cl->device.platform_data = info->platform_data; - spin_lock_irqsave(&port->clock, flags); - list_add_tail(&cl->link, &port->clients); - spin_unlock_irqrestore(&port->clock, flags); if (info->archdata) cl->device.archdata = *info->archdata; if (device_register(&cl->device) < 0) { pr_err("hsi: failed to register client: %s\n", info->name); - kfree(cl); + put_device(&cl->device); } } @@ -120,13 +101,6 @@ static void hsi_scan_board_info(struct hsi_controller *hsi) static int hsi_remove_client(struct device *dev, void *data __maybe_unused) { - struct hsi_client *cl = to_hsi_client(dev); - struct hsi_port *port = to_hsi_port(dev->parent); - unsigned long flags; - - spin_lock_irqsave(&port->clock, flags); - list_del(&cl->link); - spin_unlock_irqrestore(&port->clock, flags); device_unregister(dev); return 0; @@ -140,12 +114,17 @@ static int hsi_remove_port(struct device *dev, void *data __maybe_unused) return 0; } -static void hsi_controller_release(struct device *dev __maybe_unused) +static void hsi_controller_release(struct device *dev) { + struct hsi_controller *hsi = to_hsi_controller(dev); + + kfree(hsi->port); + kfree(hsi); } -static void hsi_port_release(struct device *dev __maybe_unused) +static void hsi_port_release(struct device *dev) { + kfree(to_hsi_port(dev)); } /** @@ -170,20 +149,12 @@ int hsi_register_controller(struct hsi_controller *hsi) unsigned int i; int err; - hsi->device.type = &hsi_ctrl; - hsi->device.bus = &hsi_bus_type; - hsi->device.release = hsi_controller_release; - err = device_register(&hsi->device); + err = device_add(&hsi->device); if (err < 0) return err; for (i = 0; i < hsi->num_ports; i++) { - hsi->port[i].device.parent = &hsi->device; - hsi->port[i].device.bus = &hsi_bus_type; - hsi->port[i].device.release = hsi_port_release; - hsi->port[i].device.type = &hsi_port; - INIT_LIST_HEAD(&hsi->port[i].clients); - spin_lock_init(&hsi->port[i].clock); - err = device_register(&hsi->port[i].device); + hsi->port[i]->device.parent = &hsi->device; + err = device_add(&hsi->port[i]->device); if (err < 0) goto out; } @@ -192,7 +163,9 @@ int hsi_register_controller(struct hsi_controller *hsi) return 0; out: - hsi_unregister_controller(hsi); + while (i-- > 0) + device_del(&hsi->port[i]->device); + device_del(&hsi->device); return err; } @@ -223,6 +196,29 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) } /** + * hsi_put_controller - Free an HSI controller + * + * @hsi: Pointer to the HSI controller to freed + * + * HSI controller drivers should only use this function if they need + * to free their allocated hsi_controller structures before a successful + * call to hsi_register_controller. Other use is not allowed. + */ +void hsi_put_controller(struct hsi_controller *hsi) +{ + unsigned int i; + + if (!hsi) + return; + + for (i = 0; i < hsi->num_ports; i++) + if (hsi->port && hsi->port[i]) + put_device(&hsi->port[i]->device); + put_device(&hsi->device); +} +EXPORT_SYMBOL_GPL(hsi_put_controller); + +/** * hsi_alloc_controller - Allocate an HSI controller and its ports * @n_ports: Number of ports on the HSI controller * @flags: Kernel allocation flags @@ -232,55 +228,52 @@ static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) { struct hsi_controller *hsi; - struct hsi_port *port; + struct hsi_port **port; unsigned int i; if (!n_ports) return NULL; - port = kzalloc(sizeof(*port)*n_ports, flags); - if (!port) - return NULL; hsi = kzalloc(sizeof(*hsi), flags); if (!hsi) - goto out; - for (i = 0; i < n_ports; i++) { - dev_set_name(&port[i].device, "port%d", i); - port[i].num = i; - port[i].async = hsi_dummy_msg; - port[i].setup = hsi_dummy_cl; - port[i].flush = hsi_dummy_cl; - port[i].start_tx = hsi_dummy_cl; - port[i].stop_tx = hsi_dummy_cl; - port[i].release = hsi_dummy_cl; - mutex_init(&port[i].lock); + return NULL; + port = kzalloc(sizeof(*port)*n_ports, flags); + if (!port) { + kfree(hsi); + return NULL; } hsi->num_ports = n_ports; hsi->port = port; + hsi->device.release = hsi_controller_release; + device_initialize(&hsi->device); + + for (i = 0; i < n_ports; i++) { + port[i] = kzalloc(sizeof(**port), flags); + if (port[i] == NULL) + goto out; + port[i]->num = i; + port[i]->async = hsi_dummy_msg; + port[i]->setup = hsi_dummy_cl; + port[i]->flush = hsi_dummy_cl; + port[i]->start_tx = hsi_dummy_cl; + port[i]->stop_tx = hsi_dummy_cl; + port[i]->release = hsi_dummy_cl; + mutex_init(&port[i]->lock); + ATOMIC_INIT_NOTIFIER_HEAD(&port[i]->n_head); + dev_set_name(&port[i]->device, "port%d", i); + hsi->port[i]->device.release = hsi_port_release; + device_initialize(&hsi->port[i]->device); + } return hsi; out: - kfree(port); + hsi_put_controller(hsi); return NULL; } EXPORT_SYMBOL_GPL(hsi_alloc_controller); /** - * hsi_free_controller - Free an HSI controller - * @hsi: Pointer to HSI controller - */ -void hsi_free_controller(struct hsi_controller *hsi) -{ - if (!hsi) - return; - - kfree(hsi->port); - kfree(hsi); -} -EXPORT_SYMBOL_GPL(hsi_free_controller); - -/** * hsi_free_msg - Free an HSI message * @msg: Pointer to the HSI message * @@ -414,37 +407,67 @@ void hsi_release_port(struct hsi_client *cl) } EXPORT_SYMBOL_GPL(hsi_release_port); -static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused) +static int hsi_event_notifier_call(struct notifier_block *nb, + unsigned long event, void *data __maybe_unused) { - if (cl->hsi_start_rx) - (*cl->hsi_start_rx)(cl); + struct hsi_client *cl = container_of(nb, struct hsi_client, nb); + + (*cl->ehandler)(cl, event); return 0; } -static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused) +/** + * hsi_register_port_event - Register a client to receive port events + * @cl: HSI client that wants to receive port events + * @cb: Event handler callback + * + * Clients should register a callback to be able to receive + * events from the ports. Registration should happen after + * claiming the port. + * The handler can be called in interrupt context. + * + * Returns -errno on error, or 0 on success. + */ +int hsi_register_port_event(struct hsi_client *cl, + void (*handler)(struct hsi_client *, unsigned long)) { - if (cl->hsi_stop_rx) - (*cl->hsi_stop_rx)(cl); + struct hsi_port *port = hsi_get_port(cl); - return 0; + if (!handler || cl->ehandler) + return -EINVAL; + if (!hsi_port_claimed(cl)) + return -EACCES; + cl->ehandler = handler; + cl->nb.notifier_call = hsi_event_notifier_call; + + return atomic_notifier_chain_register(&port->n_head, &cl->nb); } +EXPORT_SYMBOL_GPL(hsi_register_port_event); -static int hsi_port_for_each_client(struct hsi_port *port, void *data, - int (*fn)(struct hsi_client *cl, void *data)) +/** + * hsi_unregister_port_event - Stop receiving port events for a client + * @cl: HSI client that wants to stop receiving port events + * + * Clients should call this function before releasing their associated + * port. + * + * Returns -errno on error, or 0 on success. + */ +int hsi_unregister_port_event(struct hsi_client *cl) { - struct hsi_client *cl; + struct hsi_port *port = hsi_get_port(cl); + int err; - spin_lock(&port->clock); - list_for_each_entry(cl, &port->clients, link) { - spin_unlock(&port->clock); - (*fn)(cl, data); - spin_lock(&port->clock); - } - spin_unlock(&port->clock); + WARN_ON(!hsi_port_claimed(cl)); - return 0; + err = atomic_notifier_chain_unregister(&port->n_head, &cl->nb); + if (!err) + cl->ehandler = NULL; + + return err; } +EXPORT_SYMBOL_GPL(hsi_unregister_port_event); /** * hsi_event -Notifies clients about port events @@ -458,22 +481,12 @@ static int hsi_port_for_each_client(struct hsi_port *port, void *data, * Events: * HSI_EVENT_START_RX - Incoming wake line high * HSI_EVENT_STOP_RX - Incoming wake line down + * + * Returns -errno on error, or 0 on success. */ -void hsi_event(struct hsi_port *port, unsigned int event) +int hsi_event(struct hsi_port *port, unsigned long event) { - int (*fn)(struct hsi_client *cl, void *data); - - switch (event) { - case HSI_EVENT_START_RX: - fn = hsi_start_rx; - break; - case HSI_EVENT_STOP_RX: - fn = hsi_stop_rx; - break; - default: - return; - } - hsi_port_for_each_client(port, NULL, fn); + return atomic_notifier_call_chain(&port->n_head, event, NULL); } EXPORT_SYMBOL_GPL(hsi_event); diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index b0ba524..68965e6 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -859,7 +859,7 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) int ret; unsigned redundancy = 0; struct raid_dev *dev; - struct md_rdev *rdev, *freshest; + struct md_rdev *rdev, *tmp, *freshest; struct mddev *mddev = &rs->md; switch (rs->raid_type->level) { @@ -877,7 +877,7 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) } freshest = NULL; - rdev_for_each(rdev, mddev) { + rdev_for_each_safe(rdev, tmp, mddev) { if (!rdev->meta_bdev) continue; diff --git a/drivers/md/md.c b/drivers/md/md.c index b572e1e..477eb2e 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7560,14 +7560,14 @@ void md_check_recovery(struct mddev *mddev) * any transients in the value of "sync_action". */ set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); /* Clear some bits that don't mean anything, but * might be left set */ clear_bit(MD_RECOVERY_INTR, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery); - if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) + if (!test_and_clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || + test_bit(MD_RECOVERY_FROZEN, &mddev->recovery)) goto unlock; /* no recovery is running. * remove any failed drives, then @@ -8140,7 +8140,8 @@ static int md_notify_reboot(struct notifier_block *this, for_each_mddev(mddev, tmp) { if (mddev_trylock(mddev)) { - __md_stop_writes(mddev); + if (mddev->pers) + __md_stop_writes(mddev); mddev->safemode = 2; mddev_unlock(mddev); } diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 25197b6..b8b4c7b 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -89,16 +89,16 @@ static int __init arcrimi_probe(struct net_device *dev) BUGLVL(D_NORMAL) printk(VERSION); BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); - BUGMSG(D_NORMAL, "Given: node %02Xh, shmem %lXh, irq %d\n", + BUGLVL(D_NORMAL) printk("Given: node %02Xh, shmem %lXh, irq %d\n", dev->dev_addr[0], dev->mem_start, dev->irq); if (dev->mem_start <= 0 || dev->irq <= 0) { - BUGMSG(D_NORMAL, "No autoprobe for RIM I; you " + BUGLVL(D_NORMAL) printk("No autoprobe for RIM I; you " "must specify the shmem and irq!\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { - BUGMSG(D_NORMAL, "You need to specify your card's station " + BUGLVL(D_NORMAL) printk("You need to specify your card's station " "ID!\n"); return -ENODEV; } @@ -109,7 +109,7 @@ static int __init arcrimi_probe(struct net_device *dev) * will be taken. */ if (!request_mem_region(dev->mem_start, MIRROR_SIZE, "arcnet (90xx)")) { - BUGMSG(D_NORMAL, "Card memory already allocated\n"); + BUGLVL(D_NORMAL) printk("Card memory already allocated\n"); return -ENODEV; } return arcrimi_found(dev); diff --git a/drivers/net/caif/caif_hsi.c b/drivers/net/caif/caif_hsi.c index 9a66e2a..9c1c8cd 100644 --- a/drivers/net/caif/caif_hsi.c +++ b/drivers/net/caif/caif_hsi.c @@ -744,14 +744,14 @@ static void cfhsi_wake_up(struct work_struct *work) size_t fifo_occupancy = 0; /* Wakeup timeout */ - dev_err(&cfhsi->ndev->dev, "%s: Timeout.\n", + dev_dbg(&cfhsi->ndev->dev, "%s: Timeout.\n", __func__); /* Check FIFO to check if modem has sent something. */ WARN_ON(cfhsi->dev->cfhsi_fifo_occupancy(cfhsi->dev, &fifo_occupancy)); - dev_err(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n", + dev_dbg(&cfhsi->ndev->dev, "%s: Bytes in FIFO: %u.\n", __func__, (unsigned) fifo_occupancy); /* Check if we misssed the interrupt. */ @@ -1210,7 +1210,7 @@ int cfhsi_probe(struct platform_device *pdev) static void cfhsi_shutdown(struct cfhsi *cfhsi) { - u8 *tx_buf, *rx_buf; + u8 *tx_buf, *rx_buf, *flip_buf; /* Stop TXing */ netif_tx_stop_all_queues(cfhsi->ndev); @@ -1234,7 +1234,7 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi) /* Store bufferes: will be freed later. */ tx_buf = cfhsi->tx_buf; rx_buf = cfhsi->rx_buf; - + flip_buf = cfhsi->rx_flip_buf; /* Flush transmit queues. */ cfhsi_abort_tx(cfhsi); @@ -1247,6 +1247,7 @@ static void cfhsi_shutdown(struct cfhsi *cfhsi) /* Free buffers. */ kfree(tx_buf); kfree(rx_buf); + kfree(flip_buf); } int cfhsi_remove(struct platform_device *pdev) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 5234586..629c4ba 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -875,6 +875,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) PCAN_USBPRO_INFO_FW, &fi, sizeof(fi)); if (err) { + kfree(usb_if); dev_err(dev->netdev->dev.parent, "unable to read %s firmware info (err %d)\n", pcan_usb_pro.name, err); @@ -885,6 +886,7 @@ static int pcan_usb_pro_init(struct peak_usb_device *dev) PCAN_USBPRO_INFO_BL, &bi, sizeof(bi)); if (err) { + kfree(usb_if); dev_err(dev->netdev->dev.parent, "unable to read %s bootloader info (err %d)\n", pcan_usb_pro.name, err); diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index d5c6d92..442d91a 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -107,14 +107,14 @@ static int dummy_dev_init(struct net_device *dev) return 0; } -static void dummy_dev_free(struct net_device *dev) +static void dummy_dev_uninit(struct net_device *dev) { free_percpu(dev->dstats); - free_netdev(dev); } static const struct net_device_ops dummy_netdev_ops = { .ndo_init = dummy_dev_init, + .ndo_uninit = dummy_dev_uninit, .ndo_start_xmit = dummy_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_rx_mode = set_multicast_list, @@ -128,7 +128,7 @@ static void dummy_setup(struct net_device *dev) /* Initialize the device structure. */ dev->netdev_ops = &dummy_netdev_ops; - dev->destructor = dummy_dev_free; + dev->destructor = free_netdev; /* Fill in device structure with ethernet-generic values. */ dev->tx_queue_len = 0; diff --git a/drivers/net/ethernet/atheros/atlx/atl1.c b/drivers/net/ethernet/atheros/atlx/atl1.c index 40ac414..c926857 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.c +++ b/drivers/net/ethernet/atheros/atlx/atl1.c @@ -2476,7 +2476,7 @@ static irqreturn_t atl1_intr(int irq, void *data) "pcie phy link down %x\n", status); if (netif_running(adapter->netdev)) { /* reset MAC */ iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); + schedule_work(&adapter->reset_dev_task); return IRQ_HANDLED; } } @@ -2488,7 +2488,7 @@ static irqreturn_t atl1_intr(int irq, void *data) "pcie DMA r/w error (status = 0x%x)\n", status); iowrite32(0, adapter->hw.hw_addr + REG_IMR); - schedule_work(&adapter->pcie_dma_to_rst_task); + schedule_work(&adapter->reset_dev_task); return IRQ_HANDLED; } @@ -2633,10 +2633,10 @@ static void atl1_down(struct atl1_adapter *adapter) atl1_clean_rx_ring(adapter); } -static void atl1_tx_timeout_task(struct work_struct *work) +static void atl1_reset_dev_task(struct work_struct *work) { struct atl1_adapter *adapter = - container_of(work, struct atl1_adapter, tx_timeout_task); + container_of(work, struct atl1_adapter, reset_dev_task); struct net_device *netdev = adapter->netdev; netif_device_detach(netdev); @@ -3038,12 +3038,10 @@ static int __devinit atl1_probe(struct pci_dev *pdev, (unsigned long)adapter); adapter->phy_timer_pending = false; - INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task); + INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task); INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task); - INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task); - err = register_netdev(netdev); if (err) goto err_common; diff --git a/drivers/net/ethernet/atheros/atlx/atl1.h b/drivers/net/ethernet/atheros/atlx/atl1.h index 109d6da..e04bf4d 100644 --- a/drivers/net/ethernet/atheros/atlx/atl1.h +++ b/drivers/net/ethernet/atheros/atlx/atl1.h @@ -758,9 +758,8 @@ struct atl1_adapter { u16 link_speed; u16 link_duplex; spinlock_t lock; - struct work_struct tx_timeout_task; + struct work_struct reset_dev_task; struct work_struct link_chg_task; - struct work_struct pcie_dma_to_rst_task; struct timer_list phy_config_timer; bool phy_timer_pending; diff --git a/drivers/net/ethernet/atheros/atlx/atlx.c b/drivers/net/ethernet/atheros/atlx/atlx.c index 3cd8837..c9e9dc5 100644 --- a/drivers/net/ethernet/atheros/atlx/atlx.c +++ b/drivers/net/ethernet/atheros/atlx/atlx.c @@ -194,7 +194,7 @@ static void atlx_tx_timeout(struct net_device *netdev) { struct atlx_adapter *adapter = netdev_priv(netdev); /* Do the reset outside of interrupt context */ - schedule_work(&adapter->tx_timeout_task); + schedule_work(&adapter->reset_dev_task); } /* diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index ad95324..64392ec 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -942,6 +942,12 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params, const u8 max_num_of_cos = (port) ? DCBX_E3B0_MAX_NUM_COS_PORT1 : DCBX_E3B0_MAX_NUM_COS_PORT0; + if (pri >= max_num_of_cos) { + DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " + "parameter Illegal strict priority\n"); + return -EINVAL; + } + if (sp_pri_to_cos[pri] != DCBX_INVALID_COS) { DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " "parameter There can't be two COS's with " @@ -949,12 +955,6 @@ static int bnx2x_ets_e3b0_sp_pri_to_cos_set(const struct link_params *params, return -EINVAL; } - if (pri > max_num_of_cos) { - DP(NETIF_MSG_LINK, "bnx2x_ets_e3b0_sp_pri_to_cos_set invalid " - "parameter Illegal strict priority\n"); - return -EINVAL; - } - sp_pri_to_cos[pri] = cos_entry; return 0; diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 64c7644..b461c24 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1310,10 +1310,6 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) oem_reg |= HV_OEM_BITS_LPLU; - - /* Set Restart auto-neg to activate the bits */ - if (!hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; } else { if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) @@ -1324,6 +1320,11 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) oem_reg |= HV_OEM_BITS_LPLU; } + /* Set Restart auto-neg to activate the bits */ + if ((d0_state || (hw->mac.type != e1000_pchlan)) && + !hw->phy.ops.check_reset_block(hw)) + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg); release: @@ -3682,7 +3683,11 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) if (hw->mac.type >= e1000_pchlan) { e1000_oem_bits_config_ich8lan(hw, false); - e1000_phy_hw_reset_ich8lan(hw); + + /* Reset PHY to activate OEM bits on 82577/8 */ + if (hw->mac.type == e1000_pchlan) + e1000e_phy_hw_reset_generic(hw); + ret_val = hw->phy.ops.acquire(hw); if (ret_val) return; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index 027d7a7..ed1b47d 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -622,6 +622,16 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx, if (adapter->hw.mac.type == ixgbe_mac_82599EB) set_bit(__IXGBE_RX_CSUM_UDP_ZERO_ERR, &ring->state); +#ifdef IXGBE_FCOE + if (adapter->netdev->features & NETIF_F_FCOE_MTU) { + struct ixgbe_ring_feature *f; + f = &adapter->ring_feature[RING_F_FCOE]; + if ((rxr_idx >= f->mask) && + (rxr_idx < f->mask + f->indices)) + set_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state); + } + +#endif /* IXGBE_FCOE */ /* apply Rx specific ring traits */ ring->count = adapter->rx_ring_count; ring->queue_index = rxr_idx; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 3e26b1f..a7f3cd8 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -3154,14 +3154,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter) set_ring_rsc_enabled(rx_ring); else clear_ring_rsc_enabled(rx_ring); -#ifdef IXGBE_FCOE - if (netdev->features & NETIF_F_FCOE_MTU) { - struct ixgbe_ring_feature *f; - f = &adapter->ring_feature[RING_F_FCOE]; - if ((i >= f->mask) && (i < f->mask + f->indices)) - set_bit(__IXGBE_RX_FCOE_BUFSZ, &rx_ring->state); - } -#endif /* IXGBE_FCOE */ } } @@ -4836,7 +4828,9 @@ static int ixgbe_resume(struct pci_dev *pdev) pci_wake_from_d3(pdev, false); + rtnl_lock(); err = ixgbe_init_interrupt_scheme(adapter); + rtnl_unlock(); if (err) { e_dev_err("Cannot initialize interrupts for device\n"); return err; @@ -4893,6 +4887,16 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake) if (wufc) { ixgbe_set_rx_mode(netdev); + /* + * enable the optics for both mult-speed fiber and + * 82599 SFP+ fiber as we can WoL. + */ + if (hw->mac.ops.enable_tx_laser && + (hw->phy.multispeed_fiber || + (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber && + hw->mac.type == ixgbe_mac_82599EB))) + hw->mac.ops.enable_tx_laser(hw); + /* turn on all-multi mode if wake on multicast is enabled */ if (wufc & IXGBE_WUFC_MC) { fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index c722aa6..f8dda00 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -889,16 +889,17 @@ static int ks8851_net_stop(struct net_device *dev) netif_stop_queue(dev); mutex_lock(&ks->lock); + /* turn off the IRQs and ack any outstanding */ + ks8851_wrreg16(ks, KS_IER, 0x0000); + ks8851_wrreg16(ks, KS_ISR, 0xffff); + mutex_unlock(&ks->lock); /* stop any outstanding work */ flush_work(&ks->irq_work); flush_work(&ks->tx_work); flush_work(&ks->rxctrl_work); - /* turn off the IRQs and ack any outstanding */ - ks8851_wrreg16(ks, KS_IER, 0x0000); - ks8851_wrreg16(ks, KS_ISR, 0xffff); - + mutex_lock(&ks->lock); /* shutdown RX process */ ks8851_wrreg16(ks, KS_RXCR1, 0x0000); @@ -907,6 +908,7 @@ static int ks8851_net_stop(struct net_device *dev) /* set powermode to soft power down to save power */ ks8851_set_powermode(ks, PMECR_PM_SOFTDOWN); + mutex_unlock(&ks->lock); /* ensure any queued tx buffers are dumped */ while (!skb_queue_empty(&ks->txq)) { @@ -918,7 +920,6 @@ static int ks8851_net_stop(struct net_device *dev) dev_kfree_skb(txb); } - mutex_unlock(&ks->lock); return 0; } @@ -1418,6 +1419,7 @@ static int __devinit ks8851_probe(struct spi_device *spi) struct net_device *ndev; struct ks8851_net *ks; int ret; + unsigned cider; ndev = alloc_etherdev(sizeof(struct ks8851_net)); if (!ndev) @@ -1484,8 +1486,8 @@ static int __devinit ks8851_probe(struct spi_device *spi) ks8851_soft_reset(ks, GRR_GSR); /* simple check for a valid chip being connected to the bus */ - - if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) { + cider = ks8851_rdreg16(ks, KS_CIDER); + if ((cider & ~CIDER_REV_MASK) != CIDER_ID) { dev_err(&spi->dev, "failed to read device ID\n"); ret = -ENODEV; goto err_id; @@ -1516,15 +1518,14 @@ static int __devinit ks8851_probe(struct spi_device *spi) } netdev_info(ndev, "revision %d, MAC %pM, IRQ %d, %s EEPROM\n", - CIDER_REV_GET(ks8851_rdreg16(ks, KS_CIDER)), - ndev->dev_addr, ndev->irq, + CIDER_REV_GET(cider), ndev->dev_addr, ndev->irq, ks->rc_ccr & CCR_EEPROM ? "has" : "no"); return 0; err_netdev: - free_irq(ndev->irq, ndev); + free_irq(ndev->irq, ks); err_id: err_irq: diff --git a/drivers/net/ethernet/micrel/ks8851_mll.c b/drivers/net/ethernet/micrel/ks8851_mll.c index b8104d9..5ffde23 100644 --- a/drivers/net/ethernet/micrel/ks8851_mll.c +++ b/drivers/net/ethernet/micrel/ks8851_mll.c @@ -40,7 +40,7 @@ #define DRV_NAME "ks8851_mll" static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 }; -#define MAX_RECV_FRAMES 32 +#define MAX_RECV_FRAMES 255 #define MAX_BUF_SIZE 2048 #define TX_BUF_SIZE 2000 #define RX_BUF_SIZE 2000 diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c index ef723b1..eaf9ff0 100644 --- a/drivers/net/ethernet/micrel/ksz884x.c +++ b/drivers/net/ethernet/micrel/ksz884x.c @@ -5675,7 +5675,7 @@ static int netdev_set_mac_address(struct net_device *dev, void *addr) memcpy(hw->override_addr, mac->sa_data, ETH_ALEN); } - memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN); + memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN); interrupt = hw_block_intr(hw); diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index abc7907..b3287c0 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -958,6 +958,11 @@ static inline void cp_start_hw (struct cp_private *cp) cpw8(Cmd, RxOn | TxOn); } +static void cp_enable_irq(struct cp_private *cp) +{ + cpw16_f(IntrMask, cp_intr_mask); +} + static void cp_init_hw (struct cp_private *cp) { struct net_device *dev = cp->dev; @@ -997,8 +1002,6 @@ static void cp_init_hw (struct cp_private *cp) cpw16(MultiIntr, 0); - cpw16_f(IntrMask, cp_intr_mask); - cpw8_f(Cfg9346, Cfg9346_Lock); } @@ -1130,6 +1133,8 @@ static int cp_open (struct net_device *dev) if (rc) goto err_out_hw; + cp_enable_irq(cp); + netif_carrier_off(dev); mii_check_media(&cp->mii_if, netif_msg_link(cp), true); netif_start_queue(dev); @@ -2031,6 +2036,7 @@ static int cp_resume (struct pci_dev *pdev) /* FIXME: sh*t may happen if the Rx ring buffer is depleted */ cp_init_rings_index (cp); cp_init_hw (cp); + cp_enable_irq(cp); netif_start_queue (dev); spin_lock_irqsave (&cp->lock, flags); diff --git a/drivers/net/ethernet/smsc/smsc911x.c b/drivers/net/ethernet/smsc/smsc911x.c index 4a69710..cd3defb 100644 --- a/drivers/net/ethernet/smsc/smsc911x.c +++ b/drivers/net/ethernet/smsc/smsc911x.c @@ -1166,10 +1166,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat) /* Quickly dumps bad packets */ static void -smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes) +smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords) { - unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2; - if (likely(pktwords >= 4)) { unsigned int timeout = 500; unsigned int val; @@ -1233,7 +1231,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) continue; } - skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN); + skb = netdev_alloc_skb(dev, pktwords << 2); if (unlikely(!skb)) { SMSC_WARN(pdata, rx_err, "Unable to allocate skb for rx packet"); @@ -1243,14 +1241,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget) break; } - skb->data = skb->head; - skb_reset_tail_pointer(skb); + pdata->ops->rx_readfifo(pdata, + (unsigned int *)skb->data, pktwords); /* Align IP on 16B boundary */ skb_reserve(skb, NET_IP_ALIGN); skb_put(skb, pktlength - 4); - pdata->ops->rx_readfifo(pdata, - (unsigned int *)skb->head, pktwords); skb->protocol = eth_type_trans(skb, dev); skb_checksum_none_assert(skb); netif_receive_skb(skb); @@ -1565,7 +1561,7 @@ static int smsc911x_open(struct net_device *dev) smsc911x_reg_write(pdata, FIFO_INT, temp); /* set RX Data offset to 2 bytes for alignment */ - smsc911x_reg_write(pdata, RX_CFG, (2 << 8)); + smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8)); /* enable NAPI polling before enabling RX interrupts */ napi_enable(&pdata->napi); @@ -2382,7 +2378,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, &pdev->dev); pdata = netdev_priv(dev); - dev->irq = irq_res->start; irq_flags = irq_res->flags & IRQF_TRIGGER_MASK; pdata->ioaddr = ioremap_nocache(res->start, res_size); @@ -2446,7 +2441,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev) if (retval) { SMSC_WARN(pdata, probe, "Unable to claim requested irq: %d", dev->irq); - goto out_free_irq; + goto out_disable_resources; } retval = register_netdev(dev); diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c index 2757c7d..e4e4708 100644 --- a/drivers/net/ethernet/ti/davinci_mdio.c +++ b/drivers/net/ethernet/ti/davinci_mdio.c @@ -181,6 +181,11 @@ static inline int wait_for_user_access(struct davinci_mdio_data *data) __davinci_mdio_reset(data); return -EAGAIN; } + + reg = __raw_readl(®s->user[0].access); + if ((reg & USERACCESS_GO) == 0) + return 0; + dev_err(data->dev, "timed out waiting for user access\n"); return -ETIMEDOUT; } diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index cc83af0..44b8d2b 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -2,9 +2,7 @@ * Definitions for Xilinx Axi Ethernet device driver. * * Copyright (c) 2009 Secret Lab Technologies, Ltd. - * Copyright (c) 2010 Xilinx, Inc. All rights reserved. - * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> - * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved. */ #ifndef XILINX_AXIENET_H diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 2fcbeba..9c365e1 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -4,9 +4,9 @@ * Copyright (c) 2008 Nissin Systems Co., Ltd., Yoshio Kashiwagi * Copyright (c) 2005-2008 DLA Systems, David H. Lynch Jr. <dhlii@dlasys.net> * Copyright (c) 2008-2009 Secret Lab Technologies Ltd. - * Copyright (c) 2010 Xilinx, Inc. All rights reserved. - * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> - * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu> + * Copyright (c) 2010 - 2011 PetaLogix + * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved. * * This is a driver for the Xilinx Axi Ethernet which is used in the Virtex6 * and Spartan6. diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c index d70b6e7..e90e1f4 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -2,9 +2,9 @@ * MDIO bus driver for the Xilinx Axi Ethernet device * * Copyright (c) 2009 Secret Lab Technologies, Ltd. - * Copyright (c) 2010 Xilinx, Inc. All rights reserved. - * Copyright (c) 2012 Daniel Borkmann, <daniel.borkmann@tik.ee.ethz.ch> - * Copyright (c) 2012 Ariane Keller, <ariane.keller@tik.ee.ethz.ch> + * Copyright (c) 2010 - 2011 Michal Simek <monstr@monstr.eu> + * Copyright (c) 2010 - 2011 PetaLogix + * Copyright (c) 2010 - 2012 Xilinx, Inc. All rights reserved. */ #include <linux/of_address.h> diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index dd29478..2d59138 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -44,6 +44,7 @@ struct net_device_context { /* point back to our device context */ struct hv_device *device_ctx; struct delayed_work dwork; + struct work_struct work; }; @@ -51,30 +52,22 @@ static int ring_size = 128; module_param(ring_size, int, S_IRUGO); MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); -struct set_multicast_work { - struct work_struct work; - struct net_device *net; -}; - static void do_set_multicast(struct work_struct *w) { - struct set_multicast_work *swk = - container_of(w, struct set_multicast_work, work); - struct net_device *net = swk->net; - - struct net_device_context *ndevctx = netdev_priv(net); + struct net_device_context *ndevctx = + container_of(w, struct net_device_context, work); struct netvsc_device *nvdev; struct rndis_device *rdev; nvdev = hv_get_drvdata(ndevctx->device_ctx); - if (nvdev == NULL) - goto out; + if (nvdev == NULL || nvdev->ndev == NULL) + return; rdev = nvdev->extension; if (rdev == NULL) - goto out; + return; - if (net->flags & IFF_PROMISC) + if (nvdev->ndev->flags & IFF_PROMISC) rndis_filter_set_packet_filter(rdev, NDIS_PACKET_TYPE_PROMISCUOUS); else @@ -82,21 +75,13 @@ static void do_set_multicast(struct work_struct *w) NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_MULTICAST | NDIS_PACKET_TYPE_DIRECTED); - -out: - kfree(w); } static void netvsc_set_multicast_list(struct net_device *net) { - struct set_multicast_work *swk = - kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC); - if (swk == NULL) - return; + struct net_device_context *net_device_ctx = netdev_priv(net); - swk->net = net; - INIT_WORK(&swk->work, do_set_multicast); - schedule_work(&swk->work); + schedule_work(&net_device_ctx->work); } static int netvsc_open(struct net_device *net) @@ -125,6 +110,8 @@ static int netvsc_close(struct net_device *net) netif_tx_disable(net); + /* Make sure netvsc_set_multicast_list doesn't re-enable filter! */ + cancel_work_sync(&net_device_ctx->work); ret = rndis_filter_close(device_obj); if (ret != 0) netdev_err(net, "unable to close device (ret %d).\n", ret); @@ -335,6 +322,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) nvdev->start_remove = true; cancel_delayed_work_sync(&ndevctx->dwork); + cancel_work_sync(&ndevctx->work); netif_tx_disable(ndev); rndis_filter_device_remove(hdev); @@ -403,6 +391,7 @@ static int netvsc_probe(struct hv_device *dev, net_device_ctx->device_ctx = dev; hv_set_drvdata(dev, net); INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); + INIT_WORK(&net_device_ctx->work, do_set_multicast); net->netdev_ops = &device_ops; @@ -456,6 +445,7 @@ static int netvsc_remove(struct hv_device *dev) ndev_ctx = netdev_priv(net); cancel_delayed_work_sync(&ndev_ctx->dwork); + cancel_work_sync(&ndev_ctx->work); /* Stop outbound asap */ netif_tx_disable(net); diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index f08c85a..5ac46f5 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c @@ -40,6 +40,7 @@ MODULE_LICENSE("GPL"); #define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */ #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ +#define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ static int ip175c_config_init(struct phy_device *phydev) { @@ -185,6 +186,15 @@ static int ip175c_config_aneg(struct phy_device *phydev) return 0; } +static int ip101a_g_ack_interrupt(struct phy_device *phydev) +{ + int err = phy_read(phydev, IP101A_G_IRQ_CONF_STATUS); + if (err < 0) + return err; + + return 0; +} + static struct phy_driver ip175c_driver = { .phy_id = 0x02430d80, .name = "ICPlus IP175C", @@ -204,7 +214,6 @@ static struct phy_driver ip1001_driver = { .phy_id_mask = 0x0ffffff0, .features = PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, - .flags = PHY_HAS_INTERRUPT, .config_init = &ip1001_config_init, .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, @@ -220,6 +229,7 @@ static struct phy_driver ip101a_g_driver = { .features = PHY_BASIC_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause, .flags = PHY_HAS_INTERRUPT, + .ack_interrupt = ip101a_g_ack_interrupt, .config_init = &ip101a_g_config_init, .config_aneg = &genphy_config_aneg, .read_status = &genphy_read_status, diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 33f8c51..21d7151 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -235,7 +235,7 @@ struct ppp_net { /* Prototypes. */ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct file *file, unsigned int cmd, unsigned long arg); -static int ppp_xmit_process(struct ppp *ppp); +static void ppp_xmit_process(struct ppp *ppp); static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); static void ppp_push(struct ppp *ppp); static void ppp_channel_push(struct channel *pch); @@ -969,8 +969,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) put_unaligned_be16(proto, pp); skb_queue_tail(&ppp->file.xq, skb); - if (!ppp_xmit_process(ppp)) - netif_stop_queue(dev); + ppp_xmit_process(ppp); return NETDEV_TX_OK; outf: @@ -1048,11 +1047,10 @@ static void ppp_setup(struct net_device *dev) * Called to do any work queued up on the transmit side * that can now be done. */ -static int +static void ppp_xmit_process(struct ppp *ppp) { struct sk_buff *skb; - int ret = 0; ppp_xmit_lock(ppp); if (!ppp->closing) { @@ -1062,13 +1060,12 @@ ppp_xmit_process(struct ppp *ppp) ppp_send_frame(ppp, skb); /* If there's no work left to do, tell the core net code that we can accept some more. */ - if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) { + if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) netif_wake_queue(ppp->dev); - ret = 1; - } + else + netif_stop_queue(ppp->dev); } ppp_xmit_unlock(ppp); - return ret; } static inline struct sk_buff * diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 552d24b..d316503b 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -365,6 +365,27 @@ static const struct driver_info qmi_wwan_force_int4 = { .data = BIT(4), /* interface whitelist bitmap */ }; +/* Sierra Wireless provide equally useless interface descriptors + * Devices in QMI mode can be switched between two different + * configurations: + * a) USB interface #8 is QMI/wwan + * b) USB interfaces #8, #19 and #20 are QMI/wwan + * + * Both configurations provide a number of other interfaces (serial++), + * some of which have the same endpoint configuration as we expect, so + * a whitelist or blacklist is necessary. + * + * FIXME: The below whitelist should include BIT(20). It does not + * because I cannot get it to work... + */ +static const struct driver_info qmi_wwan_sierra = { + .description = "Sierra Wireless wwan/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_gobi, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ +}; #define HUAWEI_VENDOR_ID 0x12D1 #define QMI_GOBI_DEVICE(vend, prod) \ @@ -445,6 +466,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* Sierra Wireless MC77xx in QMI mode */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1199, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 187d01c..a234948 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -1051,6 +1051,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &smsc75xx_ethtool_ops; dev->net->flags |= IFF_MULTICAST; dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD; + dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; return 0; } diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 4de2760..af8acc8 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -626,16 +626,15 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* This can happen with OOM and indirect buffers. */ if (unlikely(capacity < 0)) { if (likely(capacity == -ENOMEM)) { - if (net_ratelimit()) { + if (net_ratelimit()) dev_warn(&dev->dev, "TX queue failure: out of memory\n"); - } else { + } else { dev->stats.tx_fifo_errors++; if (net_ratelimit()) dev_warn(&dev->dev, "Unexpected TX queue failure: %d\n", capacity); - } } dev->stats.tx_dropped++; kfree_skb(skb); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index ebb9f24..1a62318 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -2483,6 +2483,7 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent) pr_err("Control memory remap failed\n"); pci_release_regions(pdev); pci_disable_device(pdev); + iounmap(card->mem); kfree(card); return -ENODEV; } diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 8faa129..8c50d9d 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -19,6 +19,7 @@ #include <linux/nl80211.h> #include <linux/platform_device.h> #include <linux/etherdevice.h> +#include <linux/export.h> #include <ar231x_platform.h> #include "ath5k.h" #include "debug.h" @@ -119,7 +120,7 @@ static int ath_ahb_probe(struct platform_device *pdev) if (res == NULL) { dev_err(&pdev->dev, "no IRQ resource found\n"); ret = -ENXIO; - goto err_out; + goto err_iounmap; } irq = res->start; @@ -128,7 +129,7 @@ static int ath_ahb_probe(struct platform_device *pdev) if (hw == NULL) { dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); ret = -ENOMEM; - goto err_out; + goto err_iounmap; } ah = hw->priv; @@ -185,6 +186,8 @@ static int ath_ahb_probe(struct platform_device *pdev) err_free_hw: ieee80211_free_hw(hw); platform_set_drvdata(pdev, NULL); + err_iounmap: + iounmap(mem); err_out: return ret; } diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2504ab0..798ea57 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1548,6 +1548,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &hw->conf; + bool reset_channel = false; ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); @@ -1556,6 +1557,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); if (sc->ps_idle) ath_cancel_work(sc); + else + /* + * The chip needs a reset to properly wake up from + * full sleep + */ + reset_channel = ah->chip_fullsleep; } /* @@ -1584,7 +1591,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) } } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { + if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; int old_pos = -1; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 834e6bc..23eaa1b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1820,6 +1820,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_frame_info *fi = get_frame_info(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ath_buf *bf; + int fragno; u16 seqno; bf = ath_tx_get_buffer(sc); @@ -1831,9 +1832,16 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ATH_TXBUF_RESET(bf); if (tid) { + fragno = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; seqno = tid->seq_next; hdr->seq_ctrl = cpu_to_le16(tid->seq_next << IEEE80211_SEQ_SEQ_SHIFT); - INCR(tid->seq_next, IEEE80211_SEQ_MAX); + + if (fragno) + hdr->seq_ctrl |= cpu_to_le16(fragno); + + if (!ieee80211_has_morefrags(hdr->frame_control)) + INCR(tid->seq_next, IEEE80211_SEQ_MAX); + bf->bf_state.seqno = seqno; } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 231ddf4..7083db7 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -7614,6 +7614,7 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, { int len_mpdu; struct ieee80211_rx_status rx_status; + struct ieee80211_hdr *hdr; memset(&rx_status, 0, sizeof(rx_status)); prep_mac80211_status(wlc, rxh, p, &rx_status); @@ -7623,6 +7624,13 @@ brcms_c_recvctl(struct brcms_c_info *wlc, struct d11rxhdr *rxh, skb_pull(p, D11_PHY_HDR_LEN); __skb_trim(p, len_mpdu); + /* unmute transmit */ + if (wlc->hw->suspended_fifos) { + hdr = (struct ieee80211_hdr *)p->data; + if (ieee80211_is_beacon(hdr->frame_control)) + brcms_b_mute(wlc->hw, false); + } + memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status)); ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p); } diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 3fa1ece..2fa879b 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c @@ -103,7 +103,7 @@ static const u32 cipher_suites[] = { * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1 * in the firmware spec */ -static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type) +static int lbs_auth_to_authtype(enum nl80211_auth_type auth_type) { int ret = -ENOTSUPP; @@ -1411,7 +1411,12 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, goto done; } - lbs_set_authtype(priv, sme); + ret = lbs_set_authtype(priv, sme); + if (ret == -ENOTSUPP) { + wiphy_err(wiphy, "unsupported authtype 0x%x\n", sme->auth_type); + goto done; + } + lbs_set_radio(priv, preamble, 1); /* Do the actual association */ diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h index 445ff21..2f218f9 100644 --- a/drivers/net/wireless/mwifiex/pcie.h +++ b/drivers/net/wireless/mwifiex/pcie.h @@ -48,15 +48,15 @@ #define PCIE_HOST_INT_STATUS_MASK 0xC3C #define PCIE_SCRATCH_2_REG 0xC40 #define PCIE_SCRATCH_3_REG 0xC44 -#define PCIE_SCRATCH_4_REG 0xCC0 -#define PCIE_SCRATCH_5_REG 0xCC4 -#define PCIE_SCRATCH_6_REG 0xCC8 -#define PCIE_SCRATCH_7_REG 0xCCC -#define PCIE_SCRATCH_8_REG 0xCD0 -#define PCIE_SCRATCH_9_REG 0xCD4 -#define PCIE_SCRATCH_10_REG 0xCD8 -#define PCIE_SCRATCH_11_REG 0xCDC -#define PCIE_SCRATCH_12_REG 0xCE0 +#define PCIE_SCRATCH_4_REG 0xCD0 +#define PCIE_SCRATCH_5_REG 0xCD4 +#define PCIE_SCRATCH_6_REG 0xCD8 +#define PCIE_SCRATCH_7_REG 0xCDC +#define PCIE_SCRATCH_8_REG 0xCE0 +#define PCIE_SCRATCH_9_REG 0xCE4 +#define PCIE_SCRATCH_10_REG 0xCE8 +#define PCIE_SCRATCH_11_REG 0xCEC +#define PCIE_SCRATCH_12_REG 0xCF0 #define CPU_INTR_DNLD_RDY BIT(0) #define CPU_INTR_DOOR_BELL BIT(1) diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index a05fc9c..e6c08ee 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -212,6 +212,7 @@ static struct dmi_system_id __devinitdata dell_quirks[] = { }, .driver_data = &quirk_dell_vostro_v130, }, + { } }; static struct calling_interface_buffer *buffer; diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index f7ba316e..0ffdb3c 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -1565,7 +1565,7 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) ips->poll_turbo_status = true; if (!ips_get_i915_syms(ips)) { - dev_err(&dev->dev, "failed to get i915 symbols, graphics turbo disabled\n"); + dev_info(&dev->dev, "failed to get i915 symbols, graphics turbo disabled until i915 loads\n"); ips->gpu_turbo_enabled = false; } else { dev_dbg(&dev->dev, "graphics turbo enabled\n"); diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f0da2c3..1f21d2a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -238,7 +238,7 @@ static void handle_tx(struct vhost_net *net) vq->heads[vq->upend_idx].len = len; ubuf->callback = vhost_zerocopy_callback; - ubuf->arg = vq->ubufs; + ubuf->ctx = vq->ubufs; ubuf->desc = vq->upend_idx; msg.msg_control = ubuf; msg.msg_controllen = sizeof(ubuf); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 947f00d..51e4c1e 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1598,10 +1598,9 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs) kfree(ubufs); } -void vhost_zerocopy_callback(void *arg) +void vhost_zerocopy_callback(struct ubuf_info *ubuf) { - struct ubuf_info *ubuf = arg; - struct vhost_ubuf_ref *ubufs = ubuf->arg; + struct vhost_ubuf_ref *ubufs = ubuf->ctx; struct vhost_virtqueue *vq = ubufs->vq; /* set len = 1 to mark this desc buffers done DMA */ diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 8dcf4cc..8de1fd5 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -188,7 +188,7 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *); int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log, unsigned int log_num, u64 len); -void vhost_zerocopy_callback(void *arg); +void vhost_zerocopy_callback(struct ubuf_info *); int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq); #define vq_err(vq, fmt, ...) do { \ diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index fa5c07d..4c58d4a 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -1737,6 +1737,18 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) return 1; /* + * Even if the convert is compat with all granted locks, + * QUECVT forces it behind other locks on the convert queue. + */ + + if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) { + if (list_empty(&r->res_convertqueue)) + return 1; + else + goto out; + } + + /* * The NOORDER flag is set to avoid the standard vms rules on grant * order. */ diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 6da1935..e1fb1d5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1597,7 +1597,9 @@ static int parse_options(char *options, struct super_block *sb, unsigned int *journal_ioprio, int is_remount) { +#ifdef CONFIG_QUOTA struct ext4_sb_info *sbi = EXT4_SB(sb); +#endif char *p; substring_t args[MAX_OPT_ARGS]; int token; diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index f8411bd..5f5e70e 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -200,10 +200,11 @@ static int make_mode(const unsigned int lmstate) return -1; } -static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, +static u32 make_flags(struct gfs2_glock *gl, const unsigned int gfs_flags, const int req) { u32 lkf = DLM_LKF_VALBLK; + u32 lkid = gl->gl_lksb.sb_lkid; if (gfs_flags & LM_FLAG_TRY) lkf |= DLM_LKF_NOQUEUE; @@ -227,8 +228,11 @@ static u32 make_flags(const u32 lkid, const unsigned int gfs_flags, BUG(); } - if (lkid != 0) + if (lkid != 0) { lkf |= DLM_LKF_CONVERT; + if (test_bit(GLF_BLOCKING, &gl->gl_flags)) + lkf |= DLM_LKF_QUECVT; + } return lkf; } @@ -250,7 +254,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state, char strname[GDLM_STRNAME_BYTES] = ""; req = make_mode(req_state); - lkf = make_flags(gl->gl_lksb.sb_lkid, flags, req); + lkf = make_flags(gl, flags, req); gfs2_glstats_inc(gl, GFS2_LKS_DCOUNT); gfs2_sbstats_inc(gl, GFS2_LKS_DCOUNT); if (gl->gl_lksb.sb_lkid) { diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 806525a..840f70f 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -723,7 +723,7 @@ start_journal_io: if (commit_transaction->t_need_data_flush && (journal->j_fs_dev != journal->j_dev) && (journal->j_flags & JBD2_BARRIER)) - blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); + blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL); /* Done it all: now write the commit record asynchronously. */ if (JBD2_HAS_INCOMPAT_FEATURE(journal, @@ -859,7 +859,7 @@ wait_for_iobuf: if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && journal->j_flags & JBD2_BARRIER) { - blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL); + blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); } if (err) diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 4aaf031..8789210 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1429,7 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry } open_flags = nd->intent.open.flags; - attr.ia_valid = 0; + attr.ia_valid = ATTR_OPEN; ctx = create_nfs_open_context(dentry, open_flags); res = ERR_CAST(ctx); @@ -1536,7 +1536,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) if (IS_ERR(ctx)) goto out; - attr.ia_valid = 0; + attr.ia_valid = ATTR_OPEN; if (openflags & O_TRUNC) { attr.ia_valid |= ATTR_SIZE; attr.ia_size = 0; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 97ecc86..b6db9e3 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -59,6 +59,7 @@ struct nfs_unique_id { #define NFS_SEQID_CONFIRMED 1 struct nfs_seqid_counter { + ktime_t create_time; int owner_id; int flags; u32 counter; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f82bde0..60d5f4c 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, p->o_arg.open_flags = flags; p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); p->o_arg.clientid = server->nfs_client->cl_clientid; - p->o_arg.id = sp->so_seqid.owner_id; + p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time); + p->o_arg.id.uniquifier = sp->so_seqid.owner_id; p->o_arg.name = &dentry->d_name; p->o_arg.server = server; p->o_arg.bitmask = server->attr_bitmask; @@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) goto unlock_no_action; rcu_read_unlock(); } - /* Update sequence id. */ - data->o_arg.id = sp->so_seqid.owner_id; + /* Update client id. */ data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; @@ -1954,10 +1954,19 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, }; int err; do { - err = nfs4_handle_exception(server, - _nfs4_do_setattr(inode, cred, fattr, sattr, state), - &exception); + err = _nfs4_do_setattr(inode, cred, fattr, sattr, state); + switch (err) { + case -NFS4ERR_OPENMODE: + if (state && !(state->state & FMODE_WRITE)) { + err = -EBADF; + if (sattr->ia_valid & ATTR_OPEN) + err = -EACCES; + goto out; + } + } + err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); +out: return err; } @@ -4558,7 +4567,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) { struct nfs_server *server = NFS_SERVER(state->inode); - struct nfs4_exception exception = { }; + struct nfs4_exception exception = { + .inode = state->inode, + }; int err; do { @@ -4576,7 +4587,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) { struct nfs_server *server = NFS_SERVER(state->inode); - struct nfs4_exception exception = { }; + struct nfs4_exception exception = { + .inode = state->inode, + }; int err; err = nfs4_set_lock_state(state, request); @@ -4676,6 +4689,7 @@ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock * { struct nfs4_exception exception = { .state = state, + .inode = state->inode, }; int err; @@ -4721,6 +4735,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request) if (state == NULL) return -ENOLCK; + /* + * Don't rely on the VFS having checked the file open mode, + * since it won't do this for flock() locks. + */ + switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) { + case F_RDLCK: + if (!(filp->f_mode & FMODE_READ)) + return -EBADF; + break; + case F_WRLCK: + if (!(filp->f_mode & FMODE_WRITE)) + return -EBADF; + } + do { status = nfs4_proc_setlk(state, cmd, request); if ((status != -EAGAIN) || IS_SETLK(cmd)) diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 0f43414..7f0fcfc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -393,6 +393,7 @@ nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp) static void nfs4_init_seqid_counter(struct nfs_seqid_counter *sc) { + sc->create_time = ktime_get(); sc->flags = 0; sc->counter = 0; spin_lock_init(&sc->lock); @@ -434,13 +435,17 @@ nfs4_alloc_state_owner(struct nfs_server *server, static void nfs4_drop_state_owner(struct nfs4_state_owner *sp) { - if (!RB_EMPTY_NODE(&sp->so_server_node)) { + struct rb_node *rb_node = &sp->so_server_node; + + if (!RB_EMPTY_NODE(rb_node)) { struct nfs_server *server = sp->so_server; struct nfs_client *clp = server->nfs_client; spin_lock(&clp->cl_lock); - rb_erase(&sp->so_server_node, &server->state_owners); - RB_CLEAR_NODE(&sp->so_server_node); + if (!RB_EMPTY_NODE(rb_node)) { + rb_erase(rb_node, &server->state_owners); + RB_CLEAR_NODE(rb_node); + } spin_unlock(&clp->cl_lock); } } @@ -516,6 +521,14 @@ out: /** * nfs4_put_state_owner - Release a nfs4_state_owner * @sp: state owner data to release + * + * Note that we keep released state owners on an LRU + * list. + * This caches valid state owners so that they can be + * reused, to avoid the OPEN_CONFIRM on minor version 0. + * It also pins the uniquifier of dropped state owners for + * a while, to ensure that those state owner names are + * never reused. */ void nfs4_put_state_owner(struct nfs4_state_owner *sp) { @@ -525,15 +538,9 @@ void nfs4_put_state_owner(struct nfs4_state_owner *sp) if (!atomic_dec_and_lock(&sp->so_count, &clp->cl_lock)) return; - if (!RB_EMPTY_NODE(&sp->so_server_node)) { - sp->so_expires = jiffies; - list_add_tail(&sp->so_lru, &server->state_owners_lru); - spin_unlock(&clp->cl_lock); - } else { - nfs4_remove_state_owner_locked(sp); - spin_unlock(&clp->cl_lock); - nfs4_free_state_owner(sp); - } + sp->so_expires = jiffies; + list_add_tail(&sp->so_lru, &server->state_owners_lru); + spin_unlock(&clp->cl_lock); } /** diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c74fdb1..77fc5f9 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -74,7 +74,7 @@ static int nfs4_stat_to_errno(int); /* lock,open owner id: * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) */ -#define open_owner_id_maxsz (1 + 1 + 4) +#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2) #define lock_owner_id_maxsz (1 + 1 + 4) #define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) #define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) @@ -1340,12 +1340,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena */ encode_nfs4_seqid(xdr, arg->seqid); encode_share_access(xdr, arg->fmode); - p = reserve_space(xdr, 32); + p = reserve_space(xdr, 36); p = xdr_encode_hyper(p, arg->clientid); - *p++ = cpu_to_be32(20); + *p++ = cpu_to_be32(24); p = xdr_encode_opaque_fixed(p, "open id:", 8); *p++ = cpu_to_be32(arg->server->s_dev); - xdr_encode_hyper(p, arg->id); + *p++ = cpu_to_be32(arg->id.uniquifier); + xdr_encode_hyper(p, arg->id.create_time); } static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 9a0e8ef4..0a4be28 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -322,7 +322,7 @@ out_bad: while (!list_empty(res)) { data = list_entry(res->next, struct nfs_read_data, list); list_del(&data->list); - nfs_readdata_free(data); + nfs_readdata_release(data); } nfs_readpage_release(req); return -ENOMEM; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 37412f7..1e6715f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -2767,11 +2767,15 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type, char *root_devname; size_t len; - len = strlen(hostname) + 3; + len = strlen(hostname) + 5; root_devname = kmalloc(len, GFP_KERNEL); if (root_devname == NULL) return ERR_PTR(-ENOMEM); - snprintf(root_devname, len, "%s:/", hostname); + /* Does hostname needs to be enclosed in brackets? */ + if (strchr(hostname, ':')) + snprintf(root_devname, len, "[%s]:/", hostname); + else + snprintf(root_devname, len, "%s:/", hostname); root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data); kfree(root_devname); return root_mnt; diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 2c68818..c074623 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -682,7 +682,8 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, req->wb_bytes = rqend - req->wb_offset; out_unlock: spin_unlock(&inode->i_lock); - nfs_clear_request_commit(req); + if (req) + nfs_clear_request_commit(req); return req; out_flushme: spin_unlock(&inode->i_lock); @@ -1018,7 +1019,7 @@ out_bad: while (!list_empty(res)) { data = list_entry(res->next, struct nfs_write_data, list); list_del(&data->list); - nfs_writedata_free(data); + nfs_writedata_release(data); } nfs_redirty_request(req); return -ENOMEM; diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 0dd4e87..5e5e386 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -35,6 +35,14 @@ typedef union sigval { #define __ARCH_SI_BAND_T long #endif +#ifndef __ARCH_SI_CLOCK_T +#define __ARCH_SI_CLOCK_T __kernel_clock_t +#endif + +#ifndef __ARCH_SI_ATTRIBUTES +#define __ARCH_SI_ATTRIBUTES +#endif + #ifndef HAVE_ARCH_SIGINFO_T typedef struct siginfo { @@ -72,8 +80,8 @@ typedef struct siginfo { __kernel_pid_t _pid; /* which child */ __ARCH_SI_UID_T _uid; /* sender's uid */ int _status; /* exit code */ - __kernel_clock_t _utime; - __kernel_clock_t _stime; + __ARCH_SI_CLOCK_T _utime; + __ARCH_SI_CLOCK_T _stime; } _sigchld; /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ @@ -91,7 +99,7 @@ typedef struct siginfo { int _fd; } _sigpoll; } _sifields; -} siginfo_t; +} __ARCH_SI_ATTRIBUTES siginfo_t; #endif diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h index 4b17806..56fae86 100644 --- a/include/linux/hsi/hsi.h +++ b/include/linux/hsi/hsi.h @@ -26,9 +26,9 @@ #include <linux/device.h> #include <linux/mutex.h> #include <linux/scatterlist.h> -#include <linux/spinlock.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/notifier.h> /* HSI message ttype */ #define HSI_MSG_READ 0 @@ -121,18 +121,18 @@ static inline int hsi_register_board_info(struct hsi_board_info const *info, * @device: Driver model representation of the device * @tx_cfg: HSI TX configuration * @rx_cfg: HSI RX configuration - * @hsi_start_rx: Called after incoming wake line goes high - * @hsi_stop_rx: Called after incoming wake line goes low + * @e_handler: Callback for handling port events (RX Wake High/Low) + * @pclaimed: Keeps tracks if the clients claimed its associated HSI port + * @nb: Notifier block for port events */ struct hsi_client { struct device device; struct hsi_config tx_cfg; struct hsi_config rx_cfg; - void (*hsi_start_rx)(struct hsi_client *cl); - void (*hsi_stop_rx)(struct hsi_client *cl); /* private: */ + void (*ehandler)(struct hsi_client *, unsigned long); unsigned int pclaimed:1; - struct list_head link; + struct notifier_block nb; }; #define to_hsi_client(dev) container_of(dev, struct hsi_client, device) @@ -147,6 +147,10 @@ static inline void *hsi_client_drvdata(struct hsi_client *cl) return dev_get_drvdata(&cl->device); } +int hsi_register_port_event(struct hsi_client *cl, + void (*handler)(struct hsi_client *, unsigned long)); +int hsi_unregister_port_event(struct hsi_client *cl); + /** * struct hsi_client_driver - Driver associated to an HSI client * @driver: Driver model representation of the driver @@ -214,8 +218,7 @@ void hsi_free_msg(struct hsi_msg *msg); * @start_tx: Callback to inform that a client wants to TX data * @stop_tx: Callback to inform that a client no longer wishes to TX data * @release: Callback to inform that a client no longer uses the port - * @clients: List of hsi_clients using the port. - * @clock: Lock to serialize access to the clients list. + * @n_head: Notifier chain for signaling port events to the clients. */ struct hsi_port { struct device device; @@ -231,14 +234,14 @@ struct hsi_port { int (*start_tx)(struct hsi_client *cl); int (*stop_tx)(struct hsi_client *cl); int (*release)(struct hsi_client *cl); - struct list_head clients; - spinlock_t clock; + /* private */ + struct atomic_notifier_head n_head; }; #define to_hsi_port(dev) container_of(dev, struct hsi_port, device) #define hsi_get_port(cl) to_hsi_port((cl)->device.parent) -void hsi_event(struct hsi_port *port, unsigned int event); +int hsi_event(struct hsi_port *port, unsigned long event); int hsi_claim_port(struct hsi_client *cl, unsigned int share); void hsi_release_port(struct hsi_client *cl); @@ -270,13 +273,13 @@ struct hsi_controller { struct module *owner; unsigned int id; unsigned int num_ports; - struct hsi_port *port; + struct hsi_port **port; }; #define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device) struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); -void hsi_free_controller(struct hsi_controller *hsi); +void hsi_put_controller(struct hsi_controller *hsi); int hsi_register_controller(struct hsi_controller *hsi); void hsi_unregister_controller(struct hsi_controller *hsi); @@ -294,7 +297,7 @@ static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, unsigned int num) { - return (num < hsi->num_ports) ? &hsi->port[num] : NULL; + return (num < hsi->num_ports) ? hsi->port[num] : NULL; } /* diff --git a/include/linux/irq.h b/include/linux/irq.h index 7810406..b27cfcf 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -49,6 +49,12 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data); * IRQ_TYPE_LEVEL_LOW - low level triggered * IRQ_TYPE_LEVEL_MASK - Mask to filter out the level bits * IRQ_TYPE_SENSE_MASK - Mask for all the above bits + * IRQ_TYPE_DEFAULT - For use by some PICs to ask irq_set_type + * to setup the HW to a sane default (used + * by irqdomain map() callbacks to synchronize + * the HW state and SW flags for a newly + * allocated descriptor). + * * IRQ_TYPE_PROBE - Special flag for probing in progress * * Bits which can be modified via irq_set/clear/modify_status_flags() @@ -77,6 +83,7 @@ enum { IRQ_TYPE_LEVEL_LOW = 0x00000008, IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH), IRQ_TYPE_SENSE_MASK = 0x0000000f, + IRQ_TYPE_DEFAULT = IRQ_TYPE_SENSE_MASK, IRQ_TYPE_PROBE = 0x00000010, diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index bfd0d1b..7ba3551 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h @@ -312,6 +312,11 @@ struct nfs4_layoutreturn { int rpc_status; }; +struct stateowner_id { + __u64 create_time; + __u32 uniquifier; +}; + /* * Arguments to the open call. */ @@ -321,7 +326,7 @@ struct nfs_openargs { int open_flags; fmode_t fmode; __u64 clientid; - __u64 id; + struct stateowner_id id; union { struct { struct iattr * attrs; /* UNCHECKED, GUARDED */ diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 70a3f8d..775292a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -238,11 +238,12 @@ enum { /* * The callback notifies userspace to release buffers when skb DMA is done in * lower device, the skb last reference should be 0 when calling this. - * The desc is used to track userspace buffer index. + * The ctx field is used to track device context. + * The desc field is used to track userspace buffer index. */ struct ubuf_info { - void (*callback)(void *); - void *arg; + void (*callback)(struct ubuf_info *); + void *ctx; unsigned long desc; }; diff --git a/include/net/dst.h b/include/net/dst.h index 59c5d18..ff4da42 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -36,7 +36,11 @@ struct dst_entry { struct net_device *dev; struct dst_ops *ops; unsigned long _metrics; - unsigned long expires; + union { + unsigned long expires; + /* point to where the dst_entry copied from */ + struct dst_entry *from; + }; struct dst_entry *path; struct neighbour __rcu *_neighbour; #ifdef CONFIG_XFRM diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index b26bb81..0ae759a 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -123,6 +123,54 @@ static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) return ((struct rt6_info *)dst)->rt6i_idev; } +static inline void rt6_clean_expires(struct rt6_info *rt) +{ + if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) + dst_release(rt->dst.from); + + rt->rt6i_flags &= ~RTF_EXPIRES; + rt->dst.from = NULL; +} + +static inline void rt6_set_expires(struct rt6_info *rt, unsigned long expires) +{ + if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) + dst_release(rt->dst.from); + + rt->rt6i_flags |= RTF_EXPIRES; + rt->dst.expires = expires; +} + +static inline void rt6_update_expires(struct rt6_info *rt, int timeout) +{ + if (!(rt->rt6i_flags & RTF_EXPIRES)) { + if (rt->dst.from) + dst_release(rt->dst.from); + /* dst_set_expires relies on expires == 0 + * if it has not been set previously. + */ + rt->dst.expires = 0; + } + + dst_set_expires(&rt->dst, timeout); + rt->rt6i_flags |= RTF_EXPIRES; +} + +static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from) +{ + struct dst_entry *new = (struct dst_entry *) from; + + if (!(rt->rt6i_flags & RTF_EXPIRES) && rt->dst.from) { + if (new == rt->dst.from) + return; + dst_release(rt->dst.from); + } + + rt->rt6i_flags &= ~RTF_EXPIRES; + rt->dst.from = new; + dst_hold(new); +} + struct fib6_walker_t { struct list_head lh; struct fib6_node *root, *node; diff --git a/include/net/red.h b/include/net/red.h index 77d4c37..ef46058 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -245,7 +245,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms * * dummy packets as a burst after idle time, i.e. * - * p->qavg *= (1-W)^m + * v->qavg *= (1-W)^m * * This is an apparently overcomplicated solution (f.e. we have to * precompute a table to make this calculation in reasonable time) @@ -279,7 +279,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p unsigned int backlog) { /* - * NOTE: p->qavg is fixed point number with point at Wlog. + * NOTE: v->qavg is fixed point number with point at Wlog. * The formula below is equvalent to floating point * version: * @@ -390,7 +390,7 @@ static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v) if (red_is_idling(v)) qavg = red_calc_qavg_from_idle_time(p, v); - /* p->qavg is fixed point number with point at Wlog */ + /* v->qavg is fixed point number with point at Wlog */ qavg >>= p->Wlog; if (qavg > p->target_max && p->max_P <= MAX_P_MAX) diff --git a/include/net/sock.h b/include/net/sock.h index a6ba1f8..188532e 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -246,6 +246,7 @@ struct cg_proto; * @sk_user_data: RPC layer private data * @sk_sndmsg_page: cached page for sendmsg * @sk_sndmsg_off: cached offset for sendmsg + * @sk_peek_off: current peek_offset value * @sk_send_head: front of stuff to transmit * @sk_security: used by security modules * @sk_mark: generic packet mark diff --git a/mm/memcontrol.c b/mm/memcontrol.c index b868def..31ab9c3 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2476,10 +2476,10 @@ struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page) static void __mem_cgroup_commit_charge(struct mem_cgroup *memcg, struct page *page, unsigned int nr_pages, - struct page_cgroup *pc, enum charge_type ctype, bool lrucare) { + struct page_cgroup *pc = lookup_page_cgroup(page); struct zone *uninitialized_var(zone); bool was_on_lru = false; bool anon; @@ -2716,7 +2716,6 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, { struct mem_cgroup *memcg = NULL; unsigned int nr_pages = 1; - struct page_cgroup *pc; bool oom = true; int ret; @@ -2730,11 +2729,10 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm, oom = false; } - pc = lookup_page_cgroup(page); ret = __mem_cgroup_try_charge(mm, gfp_mask, nr_pages, &memcg, oom); if (ret == -ENOMEM) return ret; - __mem_cgroup_commit_charge(memcg, page, nr_pages, pc, ctype, false); + __mem_cgroup_commit_charge(memcg, page, nr_pages, ctype, false); return 0; } @@ -2831,16 +2829,13 @@ static void __mem_cgroup_commit_charge_swapin(struct page *page, struct mem_cgroup *memcg, enum charge_type ctype) { - struct page_cgroup *pc; - if (mem_cgroup_disabled()) return; if (!memcg) return; cgroup_exclude_rmdir(&memcg->css); - pc = lookup_page_cgroup(page); - __mem_cgroup_commit_charge(memcg, page, 1, pc, ctype, true); + __mem_cgroup_commit_charge(memcg, page, 1, ctype, true); /* * Now swap is on-memory. This means this page may be * counted both as mem and swap....double count. @@ -3298,14 +3293,13 @@ int mem_cgroup_prepare_migration(struct page *page, * page. In the case new page is migrated but not remapped, new page's * mapcount will be finally 0 and we call uncharge in end_migration(). */ - pc = lookup_page_cgroup(newpage); if (PageAnon(page)) ctype = MEM_CGROUP_CHARGE_TYPE_MAPPED; else if (page_is_file_cache(page)) ctype = MEM_CGROUP_CHARGE_TYPE_CACHE; else ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM; - __mem_cgroup_commit_charge(memcg, newpage, 1, pc, ctype, false); + __mem_cgroup_commit_charge(memcg, newpage, 1, ctype, false); return ret; } @@ -3392,8 +3386,7 @@ void mem_cgroup_replace_page_cache(struct page *oldpage, * the newpage may be on LRU(or pagevec for LRU) already. We lock * LRU while we overwrite pc->mem_cgroup. */ - pc = lookup_page_cgroup(newpage); - __mem_cgroup_commit_charge(memcg, newpage, 1, pc, type, true); + __mem_cgroup_commit_charge(memcg, newpage, 1, type, true); } #ifdef CONFIG_DEBUG_VM diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 24f0fc1..e53bb8a 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -298,13 +298,19 @@ void * __init __alloc_bootmem_node(pg_data_t *pgdat, unsigned long size, if (WARN_ON_ONCE(slab_is_available())) return kzalloc_node(size, GFP_NOWAIT, pgdat->node_id); +again: ptr = __alloc_memory_core_early(pgdat->node_id, size, align, goal, -1ULL); if (ptr) return ptr; - return __alloc_memory_core_early(MAX_NUMNODES, size, align, - goal, -1ULL); + ptr = __alloc_memory_core_early(MAX_NUMNODES, size, align, + goal, -1ULL); + if (!ptr && goal) { + goal = 0; + goto again; + } + return ptr; } void * __init __alloc_bootmem_node_high(pg_data_t *pgdat, unsigned long size, diff --git a/mm/swap_state.c b/mm/swap_state.c index 9d3dd37..4c5ff7f 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -26,7 +26,7 @@ */ static const struct address_space_operations swap_aops = { .writepage = swap_writepage, - .set_page_dirty = __set_page_dirty_nobuffers, + .set_page_dirty = __set_page_dirty_no_writeback, .migratepage = migrate_page, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 0906c19..9d9a6a3 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -2011,16 +2011,17 @@ static void __exit ax25_exit(void) proc_net_remove(&init_net, "ax25_route"); proc_net_remove(&init_net, "ax25"); proc_net_remove(&init_net, "ax25_calls"); - ax25_rt_free(); - ax25_uid_free(); - ax25_dev_free(); - ax25_unregister_sysctl(); unregister_netdevice_notifier(&ax25_dev_notifier); + ax25_unregister_sysctl(); dev_remove_pack(&ax25_packet_type); sock_unregister(PF_AX25); proto_unregister(&ax25_proto); + + ax25_rt_free(); + ax25_uid_free(); + ax25_dev_free(); } module_exit(ax25_exit); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 20618dd..d09340e 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -103,6 +103,7 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) skb->protocol = htons(ETH_P_IPV6); break; default: + kfree_skb(skb); priv->netdev->stats.rx_errors++; return -EINVAL; } @@ -220,14 +221,16 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev) if (skb->len > priv->netdev->mtu) { pr_warn("Size of skb exceeded MTU\n"); + kfree_skb(skb); dev->stats.tx_errors++; - return -ENOSPC; + return NETDEV_TX_OK; } if (!priv->flowenabled) { pr_debug("dropping packets flow off\n"); + kfree_skb(skb); dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; + return NETDEV_TX_OK; } if (priv->conn_req.protocol == CAIFPROTO_DATAGRAM_LOOP) @@ -242,7 +245,7 @@ static int chnl_net_start_xmit(struct sk_buff *skb, struct net_device *dev) result = priv->chnl.dn->transmit(priv->chnl.dn, pkt); if (result) { dev->stats.tx_dropped++; - return result; + return NETDEV_TX_OK; } /* Update statistics. */ diff --git a/net/core/dev.c b/net/core/dev.c index c25d453..9bb8f87 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1409,14 +1409,34 @@ EXPORT_SYMBOL(register_netdevice_notifier); * register_netdevice_notifier(). The notifier is unlinked into the * kernel structures and may then be reused. A negative errno code * is returned on a failure. + * + * After unregistering unregister and down device events are synthesized + * for all devices on the device list to the removed notifier to remove + * the need for special case cleanup code. */ int unregister_netdevice_notifier(struct notifier_block *nb) { + struct net_device *dev; + struct net *net; int err; rtnl_lock(); err = raw_notifier_chain_unregister(&netdev_chain, nb); + if (err) + goto unlock; + + for_each_net(net) { + for_each_netdev(net, dev) { + if (dev->flags & IFF_UP) { + nb->notifier_call(nb, NETDEV_GOING_DOWN, dev); + nb->notifier_call(nb, NETDEV_DOWN, dev); + } + nb->notifier_call(nb, NETDEV_UNREGISTER, dev); + nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev); + } + } +unlock: rtnl_unlock(); return err; } diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index 7f36b38..5c3c81a 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -150,6 +150,7 @@ static void trace_drop_common(struct sk_buff *skb, void *location) for (i = 0; i < msg->entries; i++) { if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { msg->points[i].count++; + atomic_inc(&data->dm_hit_count); goto out; } } diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 0e950fd..31a5ae5 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -83,21 +83,29 @@ assign: static int ops_init(const struct pernet_operations *ops, struct net *net) { - int err; + int err = -ENOMEM; + void *data = NULL; + if (ops->id && ops->size) { - void *data = kzalloc(ops->size, GFP_KERNEL); + data = kzalloc(ops->size, GFP_KERNEL); if (!data) - return -ENOMEM; + goto out; err = net_assign_generic(net, *ops->id, data); - if (err) { - kfree(data); - return err; - } + if (err) + goto cleanup; } + err = 0; if (ops->init) - return ops->init(net); - return 0; + err = ops->init(net); + if (!err) + return 0; + +cleanup: + kfree(data); + +out: + return err; } static void ops_free(const struct pernet_operations *ops, struct net *net) @@ -448,12 +456,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops) static int __register_pernet_operations(struct list_head *list, struct pernet_operations *ops) { - int err = 0; - err = ops_init(ops, &init_net); - if (err) - ops_free(ops, &init_net); - return err; - + return ops_init(ops, &init_net); } static void __unregister_pernet_operations(struct pernet_operations *ops) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9944c1d..3ff36406 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -335,6 +335,7 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb) incr = __tcp_grow_window(sk, skb); if (incr) { + incr = max_t(int, incr, 2 * skb->len); tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr, tp->window_clamp); inet_csk(sk)->icsk_ack.quick |= 1; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 376b2cf..7ac6423 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1096,6 +1096,7 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) eat = min_t(int, len, skb_headlen(skb)); if (eat) { __skb_pull(skb, eat); + skb->avail_size -= eat; len -= eat; if (!len) return; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6a3bb60..7d5cb97 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -803,8 +803,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) ip6_del_rt(rt); rt = NULL; } else if (!(rt->rt6i_flags & RTF_EXPIRES)) { - rt->dst.expires = expires; - rt->rt6i_flags |= RTF_EXPIRES; + rt6_set_expires(rt, expires); } } dst_release(&rt->dst); @@ -1887,11 +1886,9 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) rt = NULL; } else if (addrconf_finite_timeout(rt_expires)) { /* not infinity */ - rt->dst.expires = jiffies + rt_expires; - rt->rt6i_flags |= RTF_EXPIRES; + rt6_set_expires(rt, jiffies + rt_expires); } else { - rt->rt6i_flags &= ~RTF_EXPIRES; - rt->dst.expires = 0; + rt6_clean_expires(rt); } } else if (valid_lft) { clock_t expires = 0; diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 5b27fbc..9371743 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -673,11 +673,10 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, &rt->rt6i_gateway)) { if (!(iter->rt6i_flags & RTF_EXPIRES)) return -EEXIST; - iter->dst.expires = rt->dst.expires; - if (!(rt->rt6i_flags & RTF_EXPIRES)) { - iter->rt6i_flags &= ~RTF_EXPIRES; - iter->dst.expires = 0; - } + if (!(rt->rt6i_flags & RTF_EXPIRES)) + rt6_clean_expires(iter); + else + rt6_set_expires(iter, rt->dst.expires); return -EEXIST; } } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 3dcdb81..176b469 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -1264,8 +1264,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) } if (rt) - rt->dst.expires = jiffies + (HZ * lifetime); - + rt6_set_expires(rt, jiffies + (HZ * lifetime)); if (ra_msg->icmph.icmp6_hop_limit) { in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; if (rt) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 3992e26..bc4888d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -62,7 +62,7 @@ #include <linux/sysctl.h> #endif -static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, +static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, const struct in6_addr *dest); static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static unsigned int ip6_default_advmss(const struct dst_entry *dst); @@ -285,6 +285,10 @@ static void ip6_dst_destroy(struct dst_entry *dst) rt->rt6i_idev = NULL; in6_dev_put(idev); } + + if (!(rt->rt6i_flags & RTF_EXPIRES) && dst->from) + dst_release(dst->from); + if (peer) { rt->rt6i_peer = NULL; inet_putpeer(peer); @@ -329,8 +333,17 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, static __inline__ int rt6_check_expired(const struct rt6_info *rt) { - return (rt->rt6i_flags & RTF_EXPIRES) && - time_after(jiffies, rt->dst.expires); + struct rt6_info *ort = NULL; + + if (rt->rt6i_flags & RTF_EXPIRES) { + if (time_after(jiffies, rt->dst.expires)) + return 1; + } else if (rt->dst.from) { + ort = (struct rt6_info *) rt->dst.from; + return (ort->rt6i_flags & RTF_EXPIRES) && + time_after(jiffies, ort->dst.expires); + } + return 0; } static inline int rt6_need_strict(const struct in6_addr *daddr) @@ -620,12 +633,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref); if (rt) { - if (!addrconf_finite_timeout(lifetime)) { - rt->rt6i_flags &= ~RTF_EXPIRES; - } else { - rt->dst.expires = jiffies + HZ * lifetime; - rt->rt6i_flags |= RTF_EXPIRES; - } + if (!addrconf_finite_timeout(lifetime)) + rt6_clean_expires(rt); + else + rt6_set_expires(rt, jiffies + HZ * lifetime); + dst_release(&rt->dst); } return 0; @@ -730,7 +742,7 @@ int ip6_ins_rt(struct rt6_info *rt) return __ip6_ins_rt(rt, &info); } -static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, +static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, const struct in6_addr *saddr) { @@ -954,10 +966,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori rt->rt6i_idev = ort->rt6i_idev; if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); - rt->dst.expires = 0; rt->rt6i_gateway = ort->rt6i_gateway; - rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; + rt->rt6i_flags = ort->rt6i_flags; + rt6_clean_expires(rt); rt->rt6i_metric = 0; memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key)); @@ -1019,10 +1031,9 @@ static void ip6_link_failure(struct sk_buff *skb) rt = (struct rt6_info *) skb_dst(skb); if (rt) { - if (rt->rt6i_flags & RTF_CACHE) { - dst_set_expires(&rt->dst, 0); - rt->rt6i_flags |= RTF_EXPIRES; - } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) + if (rt->rt6i_flags & RTF_CACHE) + rt6_update_expires(rt, 0); + else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) rt->rt6i_node->fn_sernum = -1; } } @@ -1289,9 +1300,12 @@ int ip6_route_add(struct fib6_config *cfg) } rt->dst.obsolete = -1; - rt->dst.expires = (cfg->fc_flags & RTF_EXPIRES) ? - jiffies + clock_t_to_jiffies(cfg->fc_expires) : - 0; + + if (cfg->fc_flags & RTF_EXPIRES) + rt6_set_expires(rt, jiffies + + clock_t_to_jiffies(cfg->fc_expires)); + else + rt6_clean_expires(rt); if (cfg->fc_protocol == RTPROT_UNSPEC) cfg->fc_protocol = RTPROT_BOOT; @@ -1736,8 +1750,8 @@ again: features |= RTAX_FEATURE_ALLFRAG; dst_metric_set(&rt->dst, RTAX_FEATURES, features); } - dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); - rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; + rt6_update_expires(rt, net->ipv6.sysctl.ip6_rt_mtu_expires); + rt->rt6i_flags |= RTF_MODIFIED; goto out; } @@ -1765,9 +1779,8 @@ again: * which is 10 mins. After 10 mins the decreased pmtu is expired * and detecting PMTU increase will be automatically happened. */ - dst_set_expires(&nrt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); - nrt->rt6i_flags |= RTF_DYNAMIC|RTF_EXPIRES; - + rt6_update_expires(nrt, net->ipv6.sysctl.ip6_rt_mtu_expires); + nrt->rt6i_flags |= RTF_DYNAMIC; ip6_ins_rt(nrt); } out: @@ -1799,7 +1812,7 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad * Misc support functions */ -static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, +static struct rt6_info *ip6_rt_copy(struct rt6_info *ort, const struct in6_addr *dest) { struct net *net = dev_net(ort->dst.dev); @@ -1819,10 +1832,14 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, if (rt->rt6i_idev) in6_dev_hold(rt->rt6i_idev); rt->dst.lastuse = jiffies; - rt->dst.expires = 0; rt->rt6i_gateway = ort->rt6i_gateway; - rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; + rt->rt6i_flags = ort->rt6i_flags; + if ((ort->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF)) == + (RTF_DEFAULT | RTF_ADDRCONF)) + rt6_set_from(rt, ort); + else + rt6_clean_expires(rt); rt->rt6i_metric = 0; #ifdef CONFIG_IPV6_SUBTREES diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 86cfe60..98256cf 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1383,6 +1383,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, tcp_mtup_init(newsk); tcp_sync_mss(newsk, dst_mtu(dst)); newtp->advmss = dst_metric_advmss(dst); + if (tcp_sk(sk)->rx_opt.user_mss && + tcp_sk(sk)->rx_opt.user_mss < newtp->advmss) + newtp->advmss = tcp_sk(sk)->rx_opt.user_mss; + tcp_initialize_rcv_mss(newsk); if (tcp_rsk(req)->snt_synack) tcp_valid_rtt_meas(newsk, diff --git a/net/key/af_key.c b/net/key/af_key.c index 11dbb22..7e5d927 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3480,7 +3480,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, /* Addresses to be used by KM for negotiation, if ext is available */ if (k != NULL && (set_sadb_kmaddress(skb, k) < 0)) - return -EINVAL; + goto err; /* selector src */ set_sadb_address(skb, sasize_sel, SADB_EXT_ADDRESS_SRC, sel); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 55670ec..585d93e 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -232,7 +232,7 @@ static void l2tp_ip_close(struct sock *sk, long timeout) { write_lock_bh(&l2tp_ip_lock); hlist_del_init(&sk->sk_bind_node); - hlist_del_init(&sk->sk_node); + sk_del_node_init(sk); write_unlock_bh(&l2tp_ip_lock); sk_common_release(sk); } @@ -271,7 +271,8 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST) goto out; - inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr; + if (addr->l2tp_addr.s_addr) + inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr; if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST) inet->inet_saddr = 0; /* Use device */ sk_dst_reset(sk); diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 33fd8d9..cef7c29 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -457,8 +457,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, * fall back to HT20 if we don't use or use * the other extension channel */ - if ((channel_type == NL80211_CHAN_HT40MINUS || - channel_type == NL80211_CHAN_HT40PLUS) && + if (!(channel_type == NL80211_CHAN_HT40MINUS || + channel_type == NL80211_CHAN_HT40PLUS) || channel_type != sdata->u.ibss.channel_type) sta_ht_cap_new.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index bcfe8c7..d64e285 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -103,7 +103,7 @@ static void ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_rate *rate, - int rtap_len) + int rtap_len, bool has_fcs) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_radiotap_header *rthdr; @@ -134,7 +134,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, } /* IEEE80211_RADIOTAP_FLAGS */ - if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) + if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)) *pos |= IEEE80211_RADIOTAP_F_FCS; if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) *pos |= IEEE80211_RADIOTAP_F_BADFCS; @@ -294,7 +294,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, } /* prepend radiotap information */ - ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); + ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, + true); skb_reset_mac_header(skb); skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2571,7 +2572,8 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, goto out_free_skb; /* prepend radiotap information */ - ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom); + ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, + false); skb_set_mac_header(skb, 0); skb->ip_summed = CHECKSUM_UNNECESSARY; diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 9b9a85e..bf5cf69 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -331,23 +331,6 @@ static int __net_init phonet_init_net(struct net *net) static void __net_exit phonet_exit_net(struct net *net) { - struct phonet_net *pnn = phonet_pernet(net); - struct net_device *dev; - unsigned i; - - rtnl_lock(); - for_each_netdev(net, dev) - phonet_device_destroy(dev); - - for (i = 0; i < 64; i++) { - dev = pnn->routes.table[i]; - if (dev) { - rtm_phonet_notify(RTM_DELROUTE, dev, i); - dev_put(dev); - } - } - rtnl_unlock(); - proc_net_remove(net, "phonet"); } @@ -361,7 +344,7 @@ static struct pernet_operations phonet_net_ops = { /* Initialize Phonet devices list */ int __init phonet_device_init(void) { - int err = register_pernet_device(&phonet_net_ops); + int err = register_pernet_subsys(&phonet_net_ops); if (err) return err; @@ -377,7 +360,7 @@ void phonet_device_exit(void) { rtnl_unregister_all(PF_PHONET); unregister_netdevice_notifier(&phonet_device_notifier); - unregister_pernet_device(&phonet_net_ops); + unregister_pernet_subsys(&phonet_net_ops); proc_net_remove(&init_net, "pnresource"); } diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 0b15236..8179494 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -565,11 +565,8 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) opt.packets = q->packetsin; opt.bytesin = q->bytesin; - if (gred_wred_mode(table)) { - q->vars.qidlestart = - table->tab[table->def]->vars.qidlestart; - q->vars.qavg = table->tab[table->def]->vars.qavg; - } + if (gred_wred_mode(table)) + gred_load_wred_set(table, q); opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg); diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 8adfc88..3d6498a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -75,20 +75,21 @@ static struct pernet_operations sunrpc_net_ops = { static int __init init_sunrpc(void) { - int err = register_rpc_pipefs(); + int err = rpc_init_mempool(); if (err) goto out; - err = rpc_init_mempool(); - if (err) - goto out2; err = rpcauth_init_module(); if (err) - goto out3; + goto out2; cache_initialize(); err = register_pernet_subsys(&sunrpc_net_ops); if (err) + goto out3; + + err = register_rpc_pipefs(); + if (err) goto out4; #ifdef RPC_DEBUG rpc_register_sysctl(); @@ -98,11 +99,11 @@ init_sunrpc(void) return 0; out4: - rpcauth_remove_module(); + unregister_pernet_subsys(&sunrpc_net_ops); out3: - rpc_destroy_mempool(); + rpcauth_remove_module(); out2: - unregister_rpc_pipefs(); + rpc_destroy_mempool(); out: return err; } diff --git a/net/wireless/util.c b/net/wireless/util.c index 1b7a08df..957f2562 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -989,7 +989,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { - if (!(limits[j].types & iftype)) + if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) goto cont; diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 8e730cc..44ddaa5 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1100,6 +1100,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) return; + /* We're looking for an object */ + if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) + return; + /* All our symbols are of form <prefix>__mod_XXX_device_table. */ name = strstr(symname, "__mod_"); if (!name) |