diff options
227 files changed, 3442 insertions, 1689 deletions
diff --git a/.gitignore b/.gitignore index 9c0d650385be..d24ad506e799 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ series # cscope files cscope.* +ncscope.* *.orig *~ diff --git a/Documentation/ABI/testing/sysfs-class-bdi b/Documentation/ABI/testing/sysfs-class-bdi index 5ac1e01bbd48..5f500977b42f 100644 --- a/Documentation/ABI/testing/sysfs-class-bdi +++ b/Documentation/ABI/testing/sysfs-class-bdi @@ -14,6 +14,10 @@ MAJOR:MINOR non-block filesystems which provide their own BDI, such as NFS and FUSE. +MAJOR:MINOR-fuseblk + + Value of st_dev on fuseblk filesystems. + default The default backing dev, used for non-block device backed diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 77c42f40be5d..2510763295d0 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -703,6 +703,31 @@ </sect1> </chapter> +<chapter id="trylock-functions"> + <title>The trylock Functions</title> + <para> + There are functions that try to acquire a lock only once and immediately + return a value telling about success or failure to acquire the lock. + They can be used if you need no access to the data protected with the lock + when some other thread is holding the lock. You should acquire the lock + later if you then need access to the data protected with the lock. + </para> + + <para> + <function>spin_trylock()</function> does not spin but returns non-zero if + it acquires the spinlock on the first try or 0 if not. This function can + be used in all contexts like <function>spin_lock</function>: you must have + disabled the contexts that might interrupt you and acquire the spin lock. + </para> + + <para> + <function>mutex_trylock()</function> does not suspend your task + but returns non-zero if it could lock the mutex on the first try + or 0 if not. This function cannot be safely used in hardware or software + interrupt contexts despite not sleeping. + </para> +</chapter> + <chapter id="Examples"> <title>Common Examples</title> <para> diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt index 6a9c55bd556b..dcec0564d040 100644 --- a/Documentation/cpu-freq/governors.txt +++ b/Documentation/cpu-freq/governors.txt @@ -129,14 +129,6 @@ to its default value of '80' it means that between the checking intervals the CPU needs to be on average more than 80% in use to then decide that the CPU frequency needs to be increased. -sampling_down_factor: this parameter controls the rate that the CPU -makes a decision on when to decrease the frequency. When set to its -default value of '5' it means that at 1/5 the sampling_rate the kernel -makes a decision to lower the frequency. Five "lower rate" decisions -have to be made in a row before the CPU frequency is actually lower. -If set to '1' then the frequency decreases as quickly as it increases, -if set to '2' it decreases at half the rate of the increase. - ignore_nice_load: this parameter takes a value of '0' or '1'. When set to '0' (its default), all processes are counted towards the 'cpu utilisation' value. When set to '1', the processes that are diff --git a/Documentation/hwmon/ibmaem b/Documentation/hwmon/ibmaem new file mode 100644 index 000000000000..2fefaf582a43 --- /dev/null +++ b/Documentation/hwmon/ibmaem @@ -0,0 +1,37 @@ +Kernel driver ibmaem +====================== + +Supported systems: + * Any recent IBM System X server with Active Energy Manager support. + This includes the x3350, x3550, x3650, x3655, x3755, x3850 M2, + x3950 M2, and certain HS2x/LS2x/QS2x blades. The IPMI host interface + driver ("ipmi-si") needs to be loaded for this driver to do anything. + Prefix: 'ibmaem' + Datasheet: Not available + +Author: Darrick J. Wong + +Description +----------- + +This driver implements sensor reading support for the energy and power +meters available on various IBM System X hardware through the BMC. All +sensor banks will be exported as platform devices; this driver can talk +to both v1 and v2 interfaces. This driver is completely separate from the +older ibmpex driver. + +The v1 AEM interface has a simple set of features to monitor energy use. +There is a register that displays an estimate of raw energy consumption +since the last BMC reset, and a power sensor that returns average power +use over a configurable interval. + +The v2 AEM interface is a bit more sophisticated, being able to present +a wider range of energy and power use registers, the power cap as +set by the AEM software, and temperature sensors. + +Special Features +---------------- + +The "power_cap" value displays the current system power cap, as set by +the Active Energy Manager software. Setting the power cap from the host +is not currently supported. diff --git a/MAINTAINERS b/MAINTAINERS index b42dcfcbee44..0a6d2ca03cea 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1240,6 +1240,20 @@ L: video4linux-list@redhat.com W: http://linuxtv.org S: Maintained +CXGB3 ETHERNET DRIVER (CXGB3) +P: Divy Le Ray +M: divy@chelsio.com +L: netdev@vger.kernel.org +W: http://www.chelsio.com +S: Supported + +CXGB3 IWARP RNIC DRIVER (IW_CXGB3) +P: Steve Wise +M: swise@chelsio.com +L: general@lists.openfabrics.org +W: http://www.openfabrics.org +S: Supported + CYBERPRO FB DRIVER P: Russell King M: rmk@arm.linux.org.uk @@ -4361,6 +4375,14 @@ M: gregkh@suse.de L: linux-kernel@vger.kernel.org S: Maintained +UTIL-LINUX-NG PACKAGE +P: Karel Zak +M: kzak@redhat.com +L: util-linux-ng@vger.kernel.org +W: http://kernel.org/~kzak/util-linux-ng/ +T: git://git.kernel.org/pub/scm/utils/util-linux-ng/util-linux-ng.git +S: Maintained + VFAT/FAT/MSDOS FILESYSTEM: P: OGAWA Hirofumi M: hirofumi@mail.parknet.co.jp diff --git a/arch/arm/mach-at91/at91x40.c b/arch/arm/mach-at91/at91x40.c index 1de121fc55f4..f44647738ee4 100644 --- a/arch/arm/mach-at91/at91x40.c +++ b/arch/arm/mach-at91/at91x40.c @@ -16,16 +16,32 @@ #include <asm/mach/arch.h> #include <asm/arch/at91x40.h> #include <asm/arch/at91_st.h> +#include <asm/arch/timex.h> #include "generic.h" /* - * This is used in the gpio code, stub locally. + * Export the clock functions for the AT91X40. Some external code common + * to all AT91 family parts relys on this, like the gpio and serial support. */ int clk_enable(struct clk *clk) { return 0; } +void clk_disable(struct clk *clk) +{ +} + +unsigned long clk_get_rate(struct clk *clk) +{ + return AT91X40_MASTER_CLOCK; +} + +struct clk *clk_get(struct device *dev, const char *id) +{ + return NULL; +} + void __init at91x40_initialize(unsigned long main_clock) { at91_extern_irq = (1 << AT91X40_ID_IRQ0) | (1 << AT91X40_ID_IRQ1) diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 92d79fb39311..62e653a3ea1a 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -369,7 +369,8 @@ static int impd1_probe(struct lm_device *dev) lm_set_drvdata(dev, impd1); - printk("IM-PD1 found at 0x%08lx\n", dev->resource.start); + printk("IM-PD1 found at 0x%08lx\n", + (unsigned long)dev->resource.start); for (i = 0; i < ARRAY_SIZE(impd1->vcos); i++) { impd1->vcos[i].owner = THIS_MODULE, diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index d55fa4e9bb43..c07f497000ca 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c @@ -405,7 +405,6 @@ v3_pci_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) addr, fsr, pc, instr, __raw_readl(SC_LBFADDR), __raw_readl(SC_LBFCODE) & 255, v3_readb(V3_LB_ISTAT)); printk(KERN_DEBUG "%s", buf); - printascii(buf); #endif v3_writeb(V3_LB_ISTAT, 0); @@ -447,6 +446,7 @@ static irqreturn_t v3_irq(int dummy, void *devid) unsigned long pc = instruction_pointer(regs); unsigned long instr = *(unsigned long *)pc; char buf[128]; + extern void printascii(const char *); sprintf(buf, "V3 int %d: pc=0x%08lx [%08lx] LBFADDR=%08x LBFCODE=%02x " "ISTAT=%02x\n", IRQ_AP_V3INT, pc, instr, diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c index a0b16a7e8a04..a4d20127a60e 100644 --- a/arch/arm/mach-omap1/board-palmte.c +++ b/arch/arm/mach-omap1/board-palmte.c @@ -24,7 +24,6 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/spi/spi.h> -#include <linux/spi/tsc2102.h> #include <linux/interrupt.h> #include <linux/apm-emulation.h> @@ -315,14 +314,6 @@ static void palmte_get_power_status(struct apm_power_info *info, int *battery) #define palmte_get_power_status NULL #endif -static struct tsc2102_config palmte_tsc2102_config = { - .use_internal = 0, - .monitor = TSC_BAT1 | TSC_AUX | TSC_TEMP, - .temp_at25c = { 2200, 2615 }, - .apm_report = palmte_get_power_status, - .alsa_config = &palmte_alsa_config, -}; - static struct omap_board_config_kernel palmte_config[] __initdata = { { OMAP_TAG_USB, &palmte_usb_config }, { OMAP_TAG_MMC, &palmte_mmc_config }, @@ -336,7 +327,6 @@ static struct spi_board_info palmte_spi_info[] __initdata = { .bus_num = 2, /* uWire (officially) */ .chip_select = 0, /* As opposed to 3 */ .irq = OMAP_GPIO_IRQ(PALMTE_PINTDAV_GPIO), - .platform_data = &palmte_tsc2102_config, .max_speed_hz = 8000000, }, }; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index dace3820f1ee..e7d0fcd9b43f 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -38,7 +38,6 @@ #include <asm/arch/pxa-regs.h> #include <asm/arch/pxa2xx-regs.h> #include <asm/arch/pxa2xx-gpio.h> -#include <asm/arch/pxa27x-udc.h> #include <asm/arch/irda.h> #include <asm/arch/mmc.h> #include <asm/arch/ohci.h> diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index 661a2358ac22..27f63d5d3a7b 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -374,7 +374,7 @@ static struct resource bast_dm9k_resource[] = { [2] = { .start = IRQ_DM9000, .end = IRQ_DM9000, - .flags = IORESOURCE_IRQ, + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, } }; diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index c56423373ff3..4c4b5c4207c4 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c @@ -263,7 +263,7 @@ static struct resource vr1000_dm9k0_resource[] = { [2] = { .start = IRQ_VR1000_DM9000A, .end = IRQ_VR1000_DM9000A, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, } }; @@ -282,7 +282,7 @@ static struct resource vr1000_dm9k1_resource[] = { [2] = { .start = IRQ_VR1000_DM9000N, .end = IRQ_VR1000_DM9000N, - .flags = IORESOURCE_IRQ + .flags = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH, } }; diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c index 6496eb645cee..2f772a3965c4 100644 --- a/arch/arm/mach-sa1100/collie.c +++ b/arch/arm/mach-sa1100/collie.c @@ -225,26 +225,28 @@ static void __init collie_init(void) int ret = 0; /* cpu initialize */ - GAFR = ( GPIO_SSP_TXD | \ - GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK | GPIO_TIC_ACK | \ - GPIO_32_768kHz ); - - GPDR = ( GPIO_LDD8 | GPIO_LDD9 | GPIO_LDD10 | GPIO_LDD11 | GPIO_LDD12 | \ - GPIO_LDD13 | GPIO_LDD14 | GPIO_LDD15 | GPIO_SSP_TXD | \ - GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SDLC_SCLK | \ - GPIO_SDLC_AAF | GPIO_UART_SCLK1 | GPIO_32_768kHz ); - GPLR = GPIO_GPIO18; - - // PPC pin setting - PPDR = ( PPC_LDD0 | PPC_LDD1 | PPC_LDD2 | PPC_LDD3 | PPC_LDD4 | PPC_LDD5 | \ - PPC_LDD6 | PPC_LDD7 | PPC_L_PCLK | PPC_L_LCLK | PPC_L_FCLK | PPC_L_BIAS | \ - PPC_TXD1 | PPC_TXD2 | PPC_RXD2 | PPC_TXD3 | PPC_TXD4 | PPC_SCLK | PPC_SFRM ); - - PSDR = ( PPC_RXD1 | PPC_RXD2 | PPC_RXD3 | PPC_RXD4 ); - - GAFR |= GPIO_32_768kHz; - GPDR |= GPIO_32_768kHz; - TUCR = TUCR_32_768kHz; + GAFR = GPIO_SSP_TXD | GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SSP_CLK | + GPIO_MCP_CLK | GPIO_32_768kHz; + + GPDR = GPIO_LDD8 | GPIO_LDD9 | GPIO_LDD10 | GPIO_LDD11 | GPIO_LDD12 | + GPIO_LDD13 | GPIO_LDD14 | GPIO_LDD15 | GPIO_SSP_TXD | + GPIO_SSP_SCLK | GPIO_SSP_SFRM | GPIO_SDLC_SCLK | + COLLIE_GPIO_UCB1x00_RESET | COLLIE_GPIO_nMIC_ON | + COLLIE_GPIO_nREMOCON_ON | GPIO_32_768kHz; + + PPDR = PPC_LDD0 | PPC_LDD1 | PPC_LDD2 | PPC_LDD3 | PPC_LDD4 | PPC_LDD5 | + PPC_LDD6 | PPC_LDD7 | PPC_L_PCLK | PPC_L_LCLK | PPC_L_FCLK | PPC_L_BIAS | + PPC_TXD1 | PPC_TXD2 | PPC_TXD3 | PPC_TXD4 | PPC_SCLK | PPC_SFRM; + + PWER = COLLIE_GPIO_AC_IN | COLLIE_GPIO_CO | COLLIE_GPIO_ON_KEY | + COLLIE_GPIO_WAKEUP | COLLIE_GPIO_nREMOCON_INT | PWER_RTC; + + PGSR = COLLIE_GPIO_nREMOCON_ON; + + PSDR = PPC_RXD1 | PPC_RXD2 | PPC_RXD3 | PPC_RXD4; + + PCFR = PCFR_OPDE; + platform_scoop_config = &collie_pcmcia_config; diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 2946c193a7d6..2db5580048d8 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -21,6 +21,7 @@ #include <linux/clk.h> #include <linux/mutex.h> #include <linux/platform_device.h> +#include <linux/cpufreq.h> #include <asm/io.h> diff --git a/arch/arm/plat-s3c24xx/s3c244x.c b/arch/arm/plat-s3c24xx/s3c244x.c index f197bb3a2366..2f01af5f64c4 100644 --- a/arch/arm/plat-s3c24xx/s3c244x.c +++ b/arch/arm/plat-s3c24xx/s3c244x.c @@ -65,6 +65,7 @@ void __init s3c244x_map_io(struct map_desc *mach_desc, int size) /* rename any peripherals used differing from the s3c2410 */ + s3c_device_sdi.name = "s3c2440-sdi"; s3c_device_i2c.name = "s3c2440-i2c"; s3c_device_nand.name = "s3c2440-nand"; s3c_device_usbgadget.name = "s3c2440-usbgadget"; diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c index b841ecfd5d5a..9af7740f32fb 100644 --- a/arch/frv/mm/init.c +++ b/arch/frv/mm/init.c @@ -26,6 +26,7 @@ #include <linux/types.h> #include <linux/bootmem.h> #include <linux/highmem.h> +#include <linux/module.h> #include <asm/setup.h> #include <asm/segment.h> @@ -56,7 +57,9 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); */ static unsigned long empty_bad_page_table; static unsigned long empty_bad_page; + unsigned long empty_zero_page; +EXPORT_SYMBOL(empty_zero_page); /*****************************************************************************/ /* diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index 8e24fc1821e8..31729a9387df 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh @@ -20,7 +20,7 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush _end enter_prom memcpy memset reloc_offset __secondary_hold __secondary_hold_acknowledge __secondary_hold_spinloop __start strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 -reloc_got2" +reloc_got2 kernstart_addr" NM="$1" OBJ="$2" diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 80d1babb230d..e0ff59f21135 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -402,7 +402,7 @@ void __set_fixmap (enum fixed_addresses idx, phys_addr_t phys, pgprot_t flags) return; } - map_page(address, phys, flags); + map_page(address, phys, pgprot_val(flags)); fixmaps++; } diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index 5b3fb2b321ab..3a58ffabccd9 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -317,6 +317,9 @@ static int __init ps3_mm_add_memory(void) return result; } + lmb_add(start_addr, map.r1.size); + lmb_analyze(); + result = online_pages(start_pfn, nr_pages); if (result) diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8619f2a3f1f6..7680001676a6 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -1331,6 +1331,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) unsigned long flags; u32 reg; + if (!mpic) + return; + spin_lock_irqsave(&mpic_lock, flags); if (is_ipi) { reg = mpic_ipi_read(src - mpic->ipi_vecs[0]) & @@ -1346,23 +1349,6 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) spin_unlock_irqrestore(&mpic_lock, flags); } -unsigned int mpic_irq_get_priority(unsigned int irq) -{ - unsigned int is_ipi; - struct mpic *mpic = mpic_find(irq, &is_ipi); - unsigned int src = mpic_irq_to_hw(irq); - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&mpic_lock, flags); - if (is_ipi) - reg = mpic_ipi_read(src = mpic->ipi_vecs[0]); - else - reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); - spin_unlock_irqrestore(&mpic_lock, flags); - return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; -} - void mpic_setup_this_cpu(void) { #ifdef CONFIG_SMP diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 0a0c05fc3a33..2084f81a76e1 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c @@ -657,20 +657,39 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, struct task_struct *p, struct pt_regs *regs) { struct thread_info *t = task_thread_info(p); + struct sparc_stackf *parent_sf; + unsigned long child_stack_sz; char *child_trap_frame; + int kernel_thread; - /* Calculate offset to stack_frame & pt_regs */ - child_trap_frame = task_stack_page(p) + (THREAD_SIZE - (TRACEREG_SZ+STACKFRAME_SZ)); - memcpy(child_trap_frame, (((struct sparc_stackf *)regs)-1), (TRACEREG_SZ+STACKFRAME_SZ)); + kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0; + parent_sf = ((struct sparc_stackf *) regs) - 1; - t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | + /* Calculate offset to stack_frame & pt_regs */ + child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) + + (kernel_thread ? STACKFRAME_SZ : 0)); + child_trap_frame = (task_stack_page(p) + + (THREAD_SIZE - child_stack_sz)); + memcpy(child_trap_frame, parent_sf, child_stack_sz); + + t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) | + (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) | (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT); t->new_child = 1; t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS; - t->kregs = (struct pt_regs *)(child_trap_frame+sizeof(struct sparc_stackf)); + t->kregs = (struct pt_regs *) (child_trap_frame + + sizeof(struct sparc_stackf)); t->fpsaved[0] = 0; - if (regs->tstate & TSTATE_PRIV) { + if (kernel_thread) { + struct sparc_stackf *child_sf = (struct sparc_stackf *) + (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ)); + + /* Zero terminate the stack backtrace. */ + child_sf->fp = NULL; + t->kregs->u_regs[UREG_FP] = + ((unsigned long) child_sf) - STACK_BIAS; + /* Special case, if we are spawning a kernel thread from * a userspace task (via KMOD, NFS, or similar) we must * disable performance counters in the child because the @@ -681,12 +700,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp, t->pcr_reg = 0; t->flags &= ~_TIF_PERFCTR; } - t->kregs->u_regs[UREG_FP] = t->ksp; t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT); - flush_register_windows(); - memcpy((void *)(t->ksp + STACK_BIAS), - (void *)(regs->u_regs[UREG_FP] + STACK_BIAS), - sizeof(struct sparc_stackf)); t->kregs->u_regs[UREG_G6] = (unsigned long) t; t->kregs->u_regs[UREG_G4] = (unsigned long) t->task; } else { diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 3afacbb5781d..c6fc695fe1fe 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -363,6 +363,7 @@ kern_rtt: rdpr %canrestore, %g1 brz,pn %g1, kern_rtt_fill nop kern_rtt_restore: + stw %g0, [%sp + PTREGS_OFF + PT_V9_MAGIC] restore retry diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c index 01b52f561af4..c73ce3f4197e 100644 --- a/arch/sparc64/kernel/stacktrace.c +++ b/arch/sparc64/kernel/stacktrace.c @@ -19,7 +19,7 @@ void save_stack_trace(struct stack_trace *trace) fp = ksp + STACK_BIAS; thread_base = (unsigned long) tp; do { - struct reg_window *rw; + struct sparc_stackf *sf; struct pt_regs *regs; unsigned long pc; @@ -28,15 +28,17 @@ void save_stack_trace(struct stack_trace *trace) fp >= (thread_base + THREAD_SIZE)) break; - rw = (struct reg_window *) fp; - regs = (struct pt_regs *) (rw + 1); + sf = (struct sparc_stackf *) fp; + regs = (struct pt_regs *) (sf + 1); if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) { + if (!(regs->tstate & TSTATE_PRIV)) + break; pc = regs->tpc; fp = regs->u_regs[UREG_I6] + STACK_BIAS; } else { - pc = rw->ins[7]; - fp = rw->ins[6] + STACK_BIAS; + pc = sf->callers_pc; + fp = (unsigned long)sf->fp + STACK_BIAS; } if (trace->skip > 0) diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index d9b8d46707d1..369749262653 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c @@ -2116,7 +2116,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) printk("\n"); #endif do { - struct reg_window *rw; + struct sparc_stackf *sf; struct pt_regs *regs; unsigned long pc; @@ -2124,15 +2124,17 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp) if (fp < (thread_base + sizeof(struct thread_info)) || fp >= (thread_base + THREAD_SIZE)) break; - rw = (struct reg_window *)fp; - regs = (struct pt_regs *) (rw + 1); + sf = (struct sparc_stackf *) fp; + regs = (struct pt_regs *) (sf + 1); if ((regs->magic & ~0x1ff) == PT_REGS_MAGIC) { + if (!(regs->tstate & TSTATE_PRIV)) + break; pc = regs->tpc; fp = regs->u_regs[UREG_I6] + STACK_BIAS; } else { - pc = rw->ins[7]; - fp = rw->ins[6] + STACK_BIAS; + pc = sf->callers_pc; + fp = (unsigned long)sf->fp + STACK_BIAS; } printk(" [%016lx] ", pc); diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fe361ae7ef2f..dcbec34154cf 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -26,17 +26,10 @@ config X86 select HAVE_KVM if ((X86_32 && !X86_VOYAGER && !X86_VISWS && !X86_NUMAQ) || X86_64) select HAVE_ARCH_KGDB if !X86_VOYAGER -config DEFCONFIG_LIST +config ARCH_DEFCONFIG string - depends on X86_32 - option defconfig_list - default "arch/x86/configs/i386_defconfig" - -config DEFCONFIG_LIST - string - depends on X86_64 - option defconfig_list - default "arch/x86/configs/x86_64_defconfig" + default "arch/x86/configs/i386_defconfig" if X86_32 + default "arch/x86/configs/x86_64_defconfig" if X86_64 config GENERIC_LOCKBREAK diff --git a/arch/x86/boot/printf.c b/arch/x86/boot/printf.c index c1d00c0274c4..50e47cdbdddd 100644 --- a/arch/x86/boot/printf.c +++ b/arch/x86/boot/printf.c @@ -56,7 +56,7 @@ static char *number(char *str, long num, int base, int size, int precision, if (type & LEFT) type &= ~ZEROPAD; if (base < 2 || base > 36) - return 0; + return NULL; c = (type & ZEROPAD) ? '0' : ' '; sign = 0; if (type & SIGN) { diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 5910020c3f24..0633cfd0dc29 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c @@ -534,7 +534,7 @@ int setup_profiling_timer(unsigned int multiplier) */ void clear_local_APIC(void) { - int maxlvt = lapic_get_maxlvt(); + int maxlvt; u32 v; /* APIC hasn't been mapped yet */ diff --git a/arch/x86/kernel/cpu/cpufreq/longrun.c b/arch/x86/kernel/cpu/cpufreq/longrun.c index af4a867a097c..777a7ff075de 100644 --- a/arch/x86/kernel/cpu/cpufreq/longrun.c +++ b/arch/x86/kernel/cpu/cpufreq/longrun.c @@ -245,7 +245,7 @@ static unsigned int __init longrun_determine_freqs(unsigned int *low_freq, if ((ecx > 95) || (ecx == 0) || (eax < ebx)) return -EIO; - edx = (eax - ebx) / (100 - ecx); + edx = ((eax - ebx) * 100) / (100 - ecx); *low_freq = edx * 1000; /* back to kHz */ dprintk("low frequency is %u kHz\n", *low_freq); diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c index 46d4034d9f37..206791eb46e3 100644 --- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c @@ -1127,12 +1127,23 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) * an UP version, and is deprecated by AMD. */ if (num_online_cpus() != 1) { - printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n"); +#ifndef CONFIG_ACPI_PROCESSOR + printk(KERN_ERR PFX "ACPI Processor support is required " + "for SMP systems but is absent. Please load the " + "ACPI Processor module before starting this " + "driver.\n"); +#else + printk(KERN_ERR PFX "Your BIOS does not provide ACPI " + "_PSS objects in a way that Linux understands. " + "Please report this to the Linux ACPI maintainers" + " and complain to your BIOS vendor.\n"); +#endif kfree(data); return -ENODEV; } if (pol->cpu != 0) { - printk(KERN_ERR PFX "No _PSS objects for CPU other than CPU0\n"); + printk(KERN_ERR PFX "No ACPI _PSS objects for CPU other than " + "CPU0. Complain to your BIOS vendor.\n"); kfree(data); return -ENODEV; } diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index 4bc1be5d5472..08a30986d472 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -53,7 +53,7 @@ static cycle_t kvm_clock_read(void); * have elapsed since the hypervisor wrote the data. So we try to account for * that with system time */ -unsigned long kvm_get_wallclock(void) +static unsigned long kvm_get_wallclock(void) { u32 wc_sec, wc_nsec; u64 delta; @@ -86,7 +86,7 @@ unsigned long kvm_get_wallclock(void) return ts.tv_sec + 1; } -int kvm_set_wallclock(unsigned long now) +static int kvm_set_wallclock(unsigned long now) { return 0; } diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index e4790728b224..068759db63dd 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c @@ -14,7 +14,7 @@ #include "mach_timer.h" -static int tsc_enabled; +static int tsc_disabled; /* * On some systems the TSC frequency does not @@ -28,8 +28,8 @@ EXPORT_SYMBOL_GPL(tsc_khz); static int __init tsc_setup(char *str) { printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, " - "cannot disable TSC completely.\n"); - mark_tsc_unstable("user disabled TSC"); + "cannot disable TSC completely.\n"); + tsc_disabled = 1; return 1; } #else @@ -120,7 +120,7 @@ unsigned long long native_sched_clock(void) * very important for it to be as fast as the platform * can achive it. ) */ - if (unlikely(!tsc_enabled && !tsc_unstable)) + if (unlikely(tsc_disabled)) /* No locking but a rare wrong value is not a big deal: */ return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ); @@ -322,7 +322,6 @@ void mark_tsc_unstable(char *reason) { if (!tsc_unstable) { tsc_unstable = 1; - tsc_enabled = 0; printk("Marking TSC unstable due to: %s.\n", reason); /* Can be called before registration */ if (clocksource_tsc.mult) @@ -336,7 +335,7 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable); static int __init dmi_mark_tsc_unstable(const struct dmi_system_id *d) { printk(KERN_NOTICE "%s detected: marking TSC unstable.\n", - d->ident); + d->ident); tsc_unstable = 1; return 0; } @@ -403,14 +402,22 @@ void __init tsc_init(void) { int cpu; - if (!cpu_has_tsc) + if (!cpu_has_tsc || tsc_disabled) { + /* Disable the TSC in case of !cpu_has_tsc */ + tsc_disabled = 1; return; + } cpu_khz = calculate_cpu_khz(); tsc_khz = cpu_khz; if (!cpu_khz) { mark_tsc_unstable("could not calculate TSC khz"); + /* + * We need to disable the TSC completely in this case + * to prevent sched_clock() from using it. + */ + tsc_disabled = 1; return; } @@ -441,8 +448,6 @@ void __init tsc_init(void) if (check_tsc_unstable()) { clocksource_tsc.rating = 0; clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS; - } else - tsc_enabled = 1; - + } clocksource_register(&clocksource_tsc); } diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index fcc16e58609e..1784b8077a12 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c @@ -227,14 +227,14 @@ void __init tsc_calibrate(void) /* hpet or pmtimer available ? */ if (!hpet && !pm1 && !pm2) { printk(KERN_INFO "TSC calibrated against PIT\n"); - return; + goto out; } /* Check, whether the sampling was disturbed by an SMI */ if (tsc1 == ULONG_MAX || tsc2 == ULONG_MAX) { printk(KERN_WARNING "TSC calibration disturbed by SMI, " "using PIT calibration result\n"); - return; + goto out; } tsc2 = (tsc2 - tsc1) * 1000000L; @@ -255,6 +255,7 @@ void __init tsc_calibrate(void) tsc_khz = tsc2 / tsc1; +out: for_each_possible_cpu(cpu) set_cyc2ns_scale(tsc_khz, cpu); } diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 36c5406b1813..7246b60afb96 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -1996,7 +1996,7 @@ static struct shrinker mmu_shrinker = { .seeks = DEFAULT_SEEKS * 10, }; -void mmu_destroy_caches(void) +static void mmu_destroy_caches(void) { if (pte_chain_cache) kmem_cache_destroy(pte_chain_cache); diff --git a/arch/x86/vdso/vclock_gettime.c b/arch/x86/vdso/vclock_gettime.c index 23476c2ebfc4..efa2ba7c6005 100644 --- a/arch/x86/vdso/vclock_gettime.c +++ b/arch/x86/vdso/vclock_gettime.c @@ -106,9 +106,9 @@ int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) do_realtime((struct timespec *)tv); tv->tv_usec /= 1000; if (unlikely(tz != NULL)) { - /* This relies on gcc inlining the memcpy. We'll notice - if it ever fails to do so. */ - memcpy(tz, >od->sys_tz, sizeof(struct timezone)); + /* Avoid memcpy. Some old compilers fail to inline it */ + tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest; + tz->tz_dsttime = gtod->sys_tz.tz_dsttime; } return 0; } diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 126766d43aea..3525ef523a74 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -60,7 +60,7 @@ xmaddr_t arbitrary_virt_to_machine(unsigned long address) { unsigned int level; pte_t *pte = lookup_address(address, &level); - unsigned offset = address & PAGE_MASK; + unsigned offset = address & ~PAGE_MASK; BUG_ON(pte == NULL); diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c index e48a3ea03117..2509809a36cf 100644 --- a/drivers/acpi/dispatcher/dsmethod.c +++ b/drivers/acpi/dispatcher/dsmethod.c @@ -565,7 +565,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, acpi_os_release_mutex(method_desc->method. mutex->mutex.os_mutex); - method_desc->method.mutex->mutex.thread_id = 0; + method_desc->method.mutex->mutex.thread_id = NULL; } } diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c index c873ab40cd0e..a8bf3d713e28 100644 --- a/drivers/acpi/executer/exmutex.c +++ b/drivers/acpi/executer/exmutex.c @@ -326,7 +326,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc) /* Clear mutex info */ - obj_desc->mutex.thread_id = 0; + obj_desc->mutex.thread_id = NULL; return_ACPI_STATUS(status); } @@ -463,7 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) /* Mark mutex unowned */ obj_desc->mutex.owner_thread = NULL; - obj_desc->mutex.thread_id = 0; + obj_desc->mutex.thread_id = NULL; /* Update Thread sync_level (Last mutex is the important one) */ diff --git a/drivers/block/brd.c b/drivers/block/brd.c index a196ef7f147f..680cdfc00b90 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -447,6 +447,7 @@ static struct brd_device *brd_alloc(int i) disk->fops = &brd_fops; disk->private_data = brd; disk->queue = brd->brd_queue; + disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "ram%d", i); set_capacity(disk, rd_size * 2); diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index ebfe038d859e..f1c8feb5510b 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -3,7 +3,7 @@ * Authors: Dave Boutcher <boutcher@us.ibm.com> * Ryan Arnold <ryanarn@us.ibm.com> * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell <sfr@au1.ibm.com> + * Stephen Rothwell * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 5245a4a0ba74..9d0dfe6e0d63 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -6,7 +6,7 @@ * Authors: Dave Boutcher <boutcher@us.ibm.com> * Ryan Arnold <ryanarn@us.ibm.com> * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell <sfr@au1.ibm.com> + * Stephen Rothwell * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 9a32169e88fb..af211a0ef179 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -34,8 +34,6 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state) struct drm_minor *drm_minor = to_drm_minor(dev); struct drm_device *drm_dev = drm_minor->dev; - printk(KERN_ERR "%s\n", __func__); - if (drm_dev->driver->suspend) return drm_dev->driver->suspend(drm_dev, state); diff --git a/drivers/char/ip2/Makefile b/drivers/char/ip2/Makefile index 6bfe2543ddc2..939618f62fe1 100644 --- a/drivers/char/ip2/Makefile +++ b/drivers/char/ip2/Makefile @@ -2,7 +2,7 @@ # Makefile for the Computone IntelliPort Plus Driver # -obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o +obj-$(CONFIG_COMPUTONE) += ip2.o -ip2-objs := ip2base.o +ip2-objs := ip2base.o ip2main.o diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 70957acaa960..c12cf8fc4be0 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -346,27 +346,6 @@ have_requested_irq( char irq ) } /******************************************************************************/ -/* Function: init_module() */ -/* Parameters: None */ -/* Returns: Success (0) */ -/* */ -/* Description: */ -/* This is a required entry point for an installable module. It simply calls */ -/* the driver initialisation function and returns what it returns. */ -/******************************************************************************/ -#ifdef MODULE -static int __init -ip2_init_module(void) -{ -#ifdef IP2DEBUG_INIT - printk (KERN_DEBUG "Loading module ...\n" ); -#endif - return 0; -} -module_init(ip2_init_module); -#endif /* MODULE */ - -/******************************************************************************/ /* Function: cleanup_module() */ /* Parameters: None */ /* Returns: Nothing */ @@ -779,8 +758,6 @@ out: return err; } -EXPORT_SYMBOL(ip2_loadmain); - /******************************************************************************/ /* Function: ip2_init_board() */ /* Parameters: Index of board in configuration structure */ diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 3d3e1c2b310f..65fb848e1cce 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -7,7 +7,7 @@ * Authors: Dave Boutcher <boutcher@us.ibm.com> * Ryan Arnold <ryanarn@us.ibm.com> * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell <sfr@au1.ibm.com> + * Stephen Rothwell * * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation * diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 58aad63831f4..c39ddaff5e8f 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -6,7 +6,7 @@ * Authors: Dave Boutcher <boutcher@us.ibm.com> * Ryan Arnold <ryanarn@us.ibm.com> * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell <sfr@au1.ibm.com> + * Stephen Rothwell * * (C) Copyright 2000-2004 IBM Corporation * diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index ae6cd60d5c14..b64c6bc445e3 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -2,6 +2,11 @@ * linux/drivers/cpufreq/freq_table.c * * Copyright (C) 2002 - 2003 Dominik Brodowski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * */ #include <linux/kernel.h> diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 065732ddf40c..d49361bfe670 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -20,7 +20,6 @@ #include <linux/of_platform.h> #include <linux/of_device.h> -#include <asm/mpc85xx.h> #include "edac_module.h" #include "edac_core.h" #include "mpc85xx_edac.h" @@ -43,8 +42,6 @@ static u32 orig_pci_err_en; static u32 orig_l2_err_disable; static u32 orig_hid1; -static const char *mpc85xx_ctl_name = "MPC85xx"; - /************************ MC SYSFS parts ***********************************/ static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci, diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 7f138c6195ff..beaf6b3a37dc 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -127,7 +127,7 @@ int __init gpiochip_reserve(int start, int ngpio) unsigned long flags; int i; - if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio)) + if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1)) return -EINVAL; spin_lock_irqsave(&gpio_lock, flags); @@ -170,7 +170,7 @@ int gpiochip_add(struct gpio_chip *chip) unsigned id; int base = chip->base; - if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio)) + if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1)) && base >= 0) { status = -EINVAL; goto fail; @@ -207,7 +207,7 @@ fail: /* failures here can mean systems won't boot... */ if (status) pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n", - chip->base, chip->base + chip->ngpio, + chip->base, chip->base + chip->ngpio - 1, chip->label ? : "generic"); return status; } diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c index 7fb5b9d009d4..7f92fdd5f0e2 100644 --- a/drivers/gpio/mcp23s08.c +++ b/drivers/gpio/mcp23s08.c @@ -168,7 +168,7 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip) { struct mcp23s08 *mcp; char bank; - unsigned t; + int t; unsigned mask; mcp = container_of(chip, struct mcp23s08, chip); diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index 93f916720b13..7e40e8a55edf 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c @@ -30,6 +30,7 @@ static const struct i2c_device_id pca953x_id[] = { { "pca9537", 4, }, { "pca9538", 8, }, { "pca9539", 16, }, + { "pca9554", 8, }, { "pca9555", 16, }, { "pca9557", 8, }, /* REVISIT several pca955x parts should work here too */ diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 4dc76bc45c9d..00ff53348491 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -330,6 +330,20 @@ config SENSORS_CORETEMP sensor inside your CPU. Supported all are all known variants of Intel Core family. +config SENSORS_IBMAEM + tristate "IBM Active Energy Manager temperature/power sensors and control" + select IPMI_SI + depends on IPMI_HANDLER + help + If you say yes here you get support for the temperature and + power sensors and capping hardware in various IBM System X + servers that support Active Energy Manager. This includes + the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2, + and certain HS2x/LS2x/QS2x blades. + + This driver can also be built as a module. If so, the module + will be called ibmaem. + config SENSORS_IBMPEX tristate "IBM PowerExecutive temperature/power sensors" select IPMI_SI diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3bdb05a5cbd7..d098677e08de 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o +obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o obj-$(CONFIG_SENSORS_IT87) += it87.o obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c index bab5fd2e4dfd..88e89653daaf 100644 --- a/drivers/hwmon/hdaps.c +++ b/drivers/hwmon/hdaps.c @@ -515,6 +515,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = { HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"), + HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"), HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"), HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"), HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"), diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c index 6ac5c6f53585..f9e2ed621f7b 100644 --- a/drivers/hwmon/i5k_amb.c +++ b/drivers/hwmon/i5k_amb.c @@ -111,6 +111,7 @@ struct i5k_amb_data { void __iomem *amb_mmio; struct i5k_device_attribute *attrs; unsigned int num_attrs; + unsigned long chipset_id; }; static ssize_t show_name(struct device *dev, struct device_attribute *devattr, @@ -382,7 +383,8 @@ err: return res; } -static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data) +static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data, + unsigned long devid) { struct pci_dev *pcidev; u32 val32; @@ -390,7 +392,7 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data) /* Find AMB register memory space */ pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_5000_ERR, + devid, NULL); if (!pcidev) return -ENODEV; @@ -409,6 +411,8 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data) goto out; } + data->chipset_id = devid; + res = 0; out: pci_dev_put(pcidev); @@ -441,10 +445,30 @@ out: return res; } +static unsigned long i5k_channel_pci_id(struct i5k_amb_data *data, + unsigned long channel) +{ + switch (data->chipset_id) { + case PCI_DEVICE_ID_INTEL_5000_ERR: + return PCI_DEVICE_ID_INTEL_5000_FBD0 + channel; + case PCI_DEVICE_ID_INTEL_5400_ERR: + return PCI_DEVICE_ID_INTEL_5400_FBD0 + channel; + default: + BUG(); + } +} + +static unsigned long chipset_ids[] = { + PCI_DEVICE_ID_INTEL_5000_ERR, + PCI_DEVICE_ID_INTEL_5400_ERR, + 0 +}; + static int __devinit i5k_amb_probe(struct platform_device *pdev) { struct i5k_amb_data *data; struct resource *reso; + int i; int res = -ENODEV; data = kzalloc(sizeof(*data), GFP_KERNEL); @@ -452,19 +476,24 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev) return -ENOMEM; /* Figure out where the AMB registers live */ - res = i5k_find_amb_registers(data); + i = 0; + do { + res = i5k_find_amb_registers(data, chipset_ids[i]); + i++; + } while (res && chipset_ids[i]); + if (res) goto err; /* Copy the DIMM presence map for the first two channels */ res = i5k_channel_probe(&data->amb_present[0], - PCI_DEVICE_ID_INTEL_5000_FBD0); + i5k_channel_pci_id(data, 0)); if (res) goto err; /* Copy the DIMM presence map for the optional second two channels */ i5k_channel_probe(&data->amb_present[2], - PCI_DEVICE_ID_INTEL_5000_FBD1); + i5k_channel_pci_id(data, 1)); /* Set up resource regions */ reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME); diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c new file mode 100644 index 000000000000..5c006c9a4311 --- /dev/null +++ b/drivers/hwmon/ibmaem.c @@ -0,0 +1,1111 @@ +/* + * A hwmon driver for the IBM Active Energy Manager temperature/power sensors + * and capping functionality. + * Copyright (C) 2008 IBM + * + * Author: Darrick J. Wong <djwong@us.ibm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/ipmi.h> +#include <linux/module.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/jiffies.h> +#include <linux/mutex.h> +#include <linux/kdev_t.h> +#include <linux/spinlock.h> +#include <linux/idr.h> +#include <linux/sched.h> +#include <linux/platform_device.h> +#include <linux/math64.h> +#include <linux/time.h> + +#define REFRESH_INTERVAL (HZ) +#define IPMI_TIMEOUT (30 * HZ) +#define DRVNAME "aem" + +#define AEM_NETFN 0x2E + +#define AEM_FIND_FW_CMD 0x80 +#define AEM_ELEMENT_CMD 0x81 +#define AEM_FW_INSTANCE_CMD 0x82 + +#define AEM_READ_ELEMENT_CFG 0x80 +#define AEM_READ_BUFFER 0x81 +#define AEM_READ_REGISTER 0x82 +#define AEM_WRITE_REGISTER 0x83 +#define AEM_SET_REG_MASK 0x84 +#define AEM_CLEAR_REG_MASK 0x85 +#define AEM_READ_ELEMENT_CFG2 0x86 + +#define AEM_CONTROL_ELEMENT 0 +#define AEM_ENERGY_ELEMENT 1 +#define AEM_CLOCK_ELEMENT 4 +#define AEM_POWER_CAP_ELEMENT 7 +#define AEM_EXHAUST_ELEMENT 9 +#define AEM_POWER_ELEMENT 10 + +#define AEM_MODULE_TYPE_ID 0x0001 + +#define AEM2_NUM_ENERGY_REGS 2 +#define AEM2_NUM_PCAP_REGS 6 +#define AEM2_NUM_TEMP_REGS 2 +#define AEM2_NUM_SENSORS 14 + +#define AEM1_NUM_ENERGY_REGS 1 +#define AEM1_NUM_SENSORS 3 + +/* AEM 2.x has more energy registers */ +#define AEM_NUM_ENERGY_REGS AEM2_NUM_ENERGY_REGS +/* AEM 2.x needs more sensor files */ +#define AEM_NUM_SENSORS AEM2_NUM_SENSORS + +#define POWER_CAP 0 +#define POWER_CAP_MAX_HOTPLUG 1 +#define POWER_CAP_MAX 2 +#define POWER_CAP_MIN_WARNING 3 +#define POWER_CAP_MIN 4 +#define POWER_AUX 5 + +#define AEM_DEFAULT_POWER_INTERVAL 1000 +#define AEM_MIN_POWER_INTERVAL 200 +#define UJ_PER_MJ 1000L + +static DEFINE_IDR(aem_idr); +static DEFINE_SPINLOCK(aem_idr_lock); + +static struct device_driver aem_driver = { + .name = DRVNAME, + .bus = &platform_bus_type, +}; + +struct aem_ipmi_data { + struct completion read_complete; + struct ipmi_addr address; + ipmi_user_t user; + int interface; + + struct kernel_ipmi_msg tx_message; + long tx_msgid; + + void *rx_msg_data; + unsigned short rx_msg_len; + unsigned char rx_result; + int rx_recv_type; + + struct device *bmc_device; +}; + +struct aem_ro_sensor_template { + char *label; + ssize_t (*show)(struct device *dev, + struct device_attribute *devattr, + char *buf); + int index; +}; + +struct aem_rw_sensor_template { + char *label; + ssize_t (*show)(struct device *dev, + struct device_attribute *devattr, + char *buf); + ssize_t (*set)(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count); + int index; +}; + +struct aem_data { + struct list_head list; + + struct device *hwmon_dev; + struct platform_device *pdev; + struct mutex lock; + char valid; + unsigned long last_updated; /* In jiffies */ + u8 ver_major; + u8 ver_minor; + u8 module_handle; + int id; + struct aem_ipmi_data ipmi; + + /* Function to update sensors */ + void (*update)(struct aem_data *data); + + /* + * AEM 1.x sensors: + * Available sensors: + * Energy meter + * Power meter + * + * AEM 2.x sensors: + * Two energy meters + * Two power meters + * Two temperature sensors + * Six power cap registers + */ + + /* sysfs attrs */ + struct sensor_device_attribute sensors[AEM_NUM_SENSORS]; + + /* energy use in mJ */ + u64 energy[AEM_NUM_ENERGY_REGS]; + + /* power sampling interval in ms */ + unsigned long power_period[AEM_NUM_ENERGY_REGS]; + + /* Everything past here is for AEM2 only */ + + /* power caps in dW */ + u16 pcap[AEM2_NUM_PCAP_REGS]; + + /* exhaust temperature in C */ + u8 temp[AEM2_NUM_TEMP_REGS]; +}; + +/* Data structures returned by the AEM firmware */ +struct aem_iana_id { + u8 bytes[3]; +}; +static struct aem_iana_id system_x_id = { + .bytes = {0x4D, 0x4F, 0x00} +}; + +/* These are used to find AEM1 instances */ +struct aem_find_firmware_req { + struct aem_iana_id id; + u8 rsvd; + u16 index; + u16 module_type_id; +} __packed; + +struct aem_find_firmware_resp { + struct aem_iana_id id; + u8 num_instances; +} __packed; + +/* These are used to find AEM2 instances */ +struct aem_find_instance_req { + struct aem_iana_id id; + u8 instance_number; + u16 module_type_id; +} __packed; + +struct aem_find_instance_resp { + struct aem_iana_id id; + u8 num_instances; + u8 major; + u8 minor; + u8 module_handle; + u16 record_id; +} __packed; + +/* These are used to query sensors */ +struct aem_read_sensor_req { + struct aem_iana_id id; + u8 module_handle; + u8 element; + u8 subcommand; + u8 reg; + u8 rx_buf_size; +} __packed; + +struct aem_read_sensor_resp { + struct aem_iana_id id; + u8 bytes[0]; +} __packed; + +/* Data structures to talk to the IPMI layer */ +struct aem_driver_data { + struct list_head aem_devices; + struct ipmi_smi_watcher bmc_events; + struct ipmi_user_hndl ipmi_hndlrs; +}; + +static void aem_register_bmc(int iface, struct device *dev); +static void aem_bmc_gone(int iface); +static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); + +static void aem_remove_sensors(struct aem_data *data); +static int aem_init_aem1(struct aem_ipmi_data *probe); +static int aem_init_aem2(struct aem_ipmi_data *probe); +static int aem1_find_sensors(struct aem_data *data); +static int aem2_find_sensors(struct aem_data *data); +static void update_aem1_sensors(struct aem_data *data); +static void update_aem2_sensors(struct aem_data *data); + +static struct aem_driver_data driver_data = { + .aem_devices = LIST_HEAD_INIT(driver_data.aem_devices), + .bmc_events = { + .owner = THIS_MODULE, + .new_smi = aem_register_bmc, + .smi_gone = aem_bmc_gone, + }, + .ipmi_hndlrs = { + .ipmi_recv_hndl = aem_msg_handler, + }, +}; + +/* Functions to talk to the IPMI layer */ + +/* Initialize IPMI address, message buffers and user data */ +static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface, + struct device *bmc) +{ + int err; + + init_completion(&data->read_complete); + data->bmc_device = bmc; + + /* Initialize IPMI address */ + data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; + data->address.channel = IPMI_BMC_CHANNEL; + data->address.data[0] = 0; + data->interface = iface; + + /* Initialize message buffers */ + data->tx_msgid = 0; + data->tx_message.netfn = AEM_NETFN; + + /* Create IPMI messaging interface user */ + err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, + data, &data->user); + if (err < 0) { + dev_err(bmc, "Unable to register user with IPMI " + "interface %d\n", data->interface); + return -EACCES; + } + + return 0; +} + +/* Send an IPMI command */ +static int aem_send_message(struct aem_ipmi_data *data) +{ + int err; + + err = ipmi_validate_addr(&data->address, sizeof(data->address)); + if (err) + goto out; + + data->tx_msgid++; + err = ipmi_request_settime(data->user, &data->address, data->tx_msgid, + &data->tx_message, data, 0, 0, 0); + if (err) + goto out1; + + return 0; +out1: + dev_err(data->bmc_device, "request_settime=%x\n", err); + return err; +out: + dev_err(data->bmc_device, "validate_addr=%x\n", err); + return err; +} + +/* Dispatch IPMI messages to callers */ +static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) +{ + unsigned short rx_len; + struct aem_ipmi_data *data = user_msg_data; + + if (msg->msgid != data->tx_msgid) { + dev_err(data->bmc_device, "Mismatch between received msgid " + "(%02x) and transmitted msgid (%02x)!\n", + (int)msg->msgid, + (int)data->tx_msgid); + ipmi_free_recv_msg(msg); + return; + } + + data->rx_recv_type = msg->recv_type; + if (msg->msg.data_len > 0) + data->rx_result = msg->msg.data[0]; + else + data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; + + if (msg->msg.data_len > 1) { + rx_len = msg->msg.data_len - 1; + if (data->rx_msg_len < rx_len) + rx_len = data->rx_msg_len; + data->rx_msg_len = rx_len; + memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len); + } else + data->rx_msg_len = 0; + + ipmi_free_recv_msg(msg); + complete(&data->read_complete); +} + +/* ID functions */ + +/* Obtain an id */ +static int aem_idr_get(int *id) +{ + int i, err; + +again: + if (unlikely(!idr_pre_get(&aem_idr, GFP_KERNEL))) + return -ENOMEM; + + spin_lock(&aem_idr_lock); + err = idr_get_new(&aem_idr, NULL, &i); + spin_unlock(&aem_idr_lock); + + if (unlikely(err == -EAGAIN)) + goto again; + else if (unlikely(err)) + return err; + + *id = i & MAX_ID_MASK; + return 0; +} + +/* Release an object ID */ +static void aem_idr_put(int id) +{ + spin_lock(&aem_idr_lock); + idr_remove(&aem_idr, id); + spin_unlock(&aem_idr_lock); +} + +/* Sensor support functions */ + +/* Read a sensor value */ +static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, + void *buf, size_t size) +{ + int rs_size, res; + struct aem_read_sensor_req rs_req; + struct aem_read_sensor_resp *rs_resp; + struct aem_ipmi_data *ipmi = &data->ipmi; + + /* AEM registers are 1, 2, 4 or 8 bytes */ + switch (size) { + case 1: + case 2: + case 4: + case 8: + break; + default: + return -EINVAL; + } + + rs_req.id = system_x_id; + rs_req.module_handle = data->module_handle; + rs_req.element = elt; + rs_req.subcommand = AEM_READ_REGISTER; + rs_req.reg = reg; + rs_req.rx_buf_size = size; + + ipmi->tx_message.cmd = AEM_ELEMENT_CMD; + ipmi->tx_message.data = (char *)&rs_req; + ipmi->tx_message.data_len = sizeof(rs_req); + + rs_size = sizeof(*rs_resp) + size; + rs_resp = kzalloc(rs_size, GFP_KERNEL); + if (!rs_resp) + return -ENOMEM; + + ipmi->rx_msg_data = rs_resp; + ipmi->rx_msg_len = rs_size; + + aem_send_message(ipmi); + + res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); + if (!res) + return -ETIMEDOUT; + + if (ipmi->rx_result || ipmi->rx_msg_len != rs_size || + memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) { + kfree(rs_resp); + return -ENOENT; + } + + switch (size) { + case 1: { + u8 *x = buf; + *x = rs_resp->bytes[0]; + break; + } + case 2: { + u16 *x = buf; + *x = be16_to_cpup((u16 *)rs_resp->bytes); + break; + } + case 4: { + u32 *x = buf; + *x = be32_to_cpup((u32 *)rs_resp->bytes); + break; + } + case 8: { + u64 *x = buf; + *x = be64_to_cpup((u64 *)rs_resp->bytes); + break; + } + } + + return 0; +} + +/* Update AEM energy registers */ +static void update_aem_energy(struct aem_data *data) +{ + aem_read_sensor(data, AEM_ENERGY_ELEMENT, 0, &data->energy[0], 8); + if (data->ver_major < 2) + return; + aem_read_sensor(data, AEM_ENERGY_ELEMENT, 1, &data->energy[1], 8); +} + +/* Update all AEM1 sensors */ +static void update_aem1_sensors(struct aem_data *data) +{ + mutex_lock(&data->lock); + if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && + data->valid) + goto out; + + update_aem_energy(data); +out: + mutex_unlock(&data->lock); +} + +/* Update all AEM2 sensors */ +static void update_aem2_sensors(struct aem_data *data) +{ + int i; + + mutex_lock(&data->lock); + if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && + data->valid) + goto out; + + update_aem_energy(data); + aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 0, &data->temp[0], 1); + aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 1, &data->temp[1], 1); + + for (i = POWER_CAP; i <= POWER_AUX; i++) + aem_read_sensor(data, AEM_POWER_CAP_ELEMENT, i, + &data->pcap[i], 2); +out: + mutex_unlock(&data->lock); +} + +/* Delete an AEM instance */ +static void aem_delete(struct aem_data *data) +{ + list_del(&data->list); + aem_remove_sensors(data); + hwmon_device_unregister(data->hwmon_dev); + ipmi_destroy_user(data->ipmi.user); + dev_set_drvdata(&data->pdev->dev, NULL); + platform_device_unregister(data->pdev); + aem_idr_put(data->id); + kfree(data); +} + +/* Probe functions for AEM1 devices */ + +/* Retrieve version and module handle for an AEM1 instance */ +static int aem_find_aem1_count(struct aem_ipmi_data *data) +{ + int res; + struct aem_find_firmware_req ff_req; + struct aem_find_firmware_resp ff_resp; + + ff_req.id = system_x_id; + ff_req.index = 0; + ff_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID); + + data->tx_message.cmd = AEM_FIND_FW_CMD; + data->tx_message.data = (char *)&ff_req; + data->tx_message.data_len = sizeof(ff_req); + + data->rx_msg_data = &ff_resp; + data->rx_msg_len = sizeof(ff_resp); + + aem_send_message(data); + + res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT); + if (!res) + return -ETIMEDOUT; + + if (data->rx_result || data->rx_msg_len != sizeof(ff_resp) || + memcmp(&ff_resp.id, &system_x_id, sizeof(system_x_id))) + return -ENOENT; + + return ff_resp.num_instances; +} + +/* Find and initialize one AEM1 instance */ +static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) +{ + struct aem_data *data; + int i; + int res = -ENOMEM; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return res; + mutex_init(&data->lock); + + /* Copy instance data */ + data->ver_major = 1; + data->ver_minor = 0; + data->module_handle = module_handle; + for (i = 0; i < AEM1_NUM_ENERGY_REGS; i++) + data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL; + + /* Create sub-device for this fw instance */ + if (aem_idr_get(&data->id)) + goto id_err; + + data->pdev = platform_device_alloc(DRVNAME, data->id); + if (!data->pdev) + goto dev_err; + data->pdev->dev.driver = &aem_driver; + + res = platform_device_add(data->pdev); + if (res) + goto ipmi_err; + + dev_set_drvdata(&data->pdev->dev, data); + + /* Set up IPMI interface */ + if (aem_init_ipmi_data(&data->ipmi, probe->interface, + probe->bmc_device)) + goto ipmi_err; + + /* Register with hwmon */ + data->hwmon_dev = hwmon_device_register(&data->pdev->dev); + + if (IS_ERR(data->hwmon_dev)) { + dev_err(&data->pdev->dev, "Unable to register hwmon " + "device for IPMI interface %d\n", + probe->interface); + goto hwmon_reg_err; + } + + data->update = update_aem1_sensors; + + /* Find sensors */ + if (aem1_find_sensors(data)) + goto sensor_err; + + /* Add to our list of AEM devices */ + list_add_tail(&data->list, &driver_data.aem_devices); + + dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n", + data->ver_major, data->ver_minor, + data->module_handle); + return 0; + +sensor_err: + hwmon_device_unregister(data->hwmon_dev); +hwmon_reg_err: + ipmi_destroy_user(data->ipmi.user); +ipmi_err: + dev_set_drvdata(&data->pdev->dev, NULL); + platform_device_unregister(data->pdev); +dev_err: + aem_idr_put(data->id); +id_err: + kfree(data); + + return res; +} + +/* Find and initialize all AEM1 instances */ +static int aem_init_aem1(struct aem_ipmi_data *probe) +{ + int num, i, err; + + num = aem_find_aem1_count(probe); + for (i = 0; i < num; i++) { + err = aem_init_aem1_inst(probe, i); + if (err) { + dev_err(probe->bmc_device, + "Error %d initializing AEM1 0x%X\n", + err, i); + return err; + } + } + + return 0; +} + +/* Probe functions for AEM2 devices */ + +/* Retrieve version and module handle for an AEM2 instance */ +static int aem_find_aem2(struct aem_ipmi_data *data, + struct aem_find_instance_resp *fi_resp, + int instance_num) +{ + int res; + struct aem_find_instance_req fi_req; + + fi_req.id = system_x_id; + fi_req.instance_number = instance_num; + fi_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID); + + data->tx_message.cmd = AEM_FW_INSTANCE_CMD; + data->tx_message.data = (char *)&fi_req; + data->tx_message.data_len = sizeof(fi_req); + + data->rx_msg_data = fi_resp; + data->rx_msg_len = sizeof(*fi_resp); + + aem_send_message(data); + + res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT); + if (!res) + return -ETIMEDOUT; + + if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) || + memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id))) + return -ENOENT; + + return 0; +} + +/* Find and initialize one AEM2 instance */ +static int aem_init_aem2_inst(struct aem_ipmi_data *probe, + struct aem_find_instance_resp *fi_resp) +{ + struct aem_data *data; + int i; + int res = -ENOMEM; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return res; + mutex_init(&data->lock); + + /* Copy instance data */ + data->ver_major = fi_resp->major; + data->ver_minor = fi_resp->minor; + data->module_handle = fi_resp->module_handle; + for (i = 0; i < AEM2_NUM_ENERGY_REGS; i++) + data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL; + + /* Create sub-device for this fw instance */ + if (aem_idr_get(&data->id)) + goto id_err; + + data->pdev = platform_device_alloc(DRVNAME, data->id); + if (!data->pdev) + goto dev_err; + data->pdev->dev.driver = &aem_driver; + + res = platform_device_add(data->pdev); + if (res) + goto ipmi_err; + + dev_set_drvdata(&data->pdev->dev, data); + + /* Set up IPMI interface */ + if (aem_init_ipmi_data(&data->ipmi, probe->interface, + probe->bmc_device)) + goto ipmi_err; + + /* Register with hwmon */ + data->hwmon_dev = hwmon_device_register(&data->pdev->dev); + + if (IS_ERR(data->hwmon_dev)) { + dev_err(&data->pdev->dev, "Unable to register hwmon " + "device for IPMI interface %d\n", + probe->interface); + goto hwmon_reg_err; + } + + data->update = update_aem2_sensors; + + /* Find sensors */ + if (aem2_find_sensors(data)) + goto sensor_err; + + /* Add to our list of AEM devices */ + list_add_tail(&data->list, &driver_data.aem_devices); + + dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n", + data->ver_major, data->ver_minor, + data->module_handle); + return 0; + +sensor_err: + hwmon_device_unregister(data->hwmon_dev); +hwmon_reg_err: + ipmi_destroy_user(data->ipmi.user); +ipmi_err: + dev_set_drvdata(&data->pdev->dev, NULL); + platform_device_unregister(data->pdev); +dev_err: + aem_idr_put(data->id); +id_err: + kfree(data); + + return res; +} + +/* Find and initialize all AEM2 instances */ +static int aem_init_aem2(struct aem_ipmi_data *probe) +{ + struct aem_find_instance_resp fi_resp; + int err; + int i = 0; + + while (!aem_find_aem2(probe, &fi_resp, i)) { + if (fi_resp.major != 2) { + dev_err(probe->bmc_device, "Unknown AEM v%d; please " + "report this to the maintainer.\n", + fi_resp.major); + i++; + continue; + } + err = aem_init_aem2_inst(probe, &fi_resp); + if (err) { + dev_err(probe->bmc_device, + "Error %d initializing AEM2 0x%X\n", + err, fi_resp.module_handle); + return err; + } + i++; + } + + return 0; +} + +/* Probe a BMC for AEM firmware instances */ +static void aem_register_bmc(int iface, struct device *dev) +{ + struct aem_ipmi_data probe; + + if (aem_init_ipmi_data(&probe, iface, dev)) + return; + + /* Ignore probe errors; they won't cause problems */ + aem_init_aem1(&probe); + aem_init_aem2(&probe); + + ipmi_destroy_user(probe.user); +} + +/* Handle BMC deletion */ +static void aem_bmc_gone(int iface) +{ + struct aem_data *p1, *next1; + + list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) + if (p1->ipmi.interface == iface) + aem_delete(p1); +} + +/* sysfs support functions */ + +/* AEM device name */ +static ssize_t show_name(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct aem_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major); +} +static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); + +/* AEM device version */ +static ssize_t show_version(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct aem_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor); +} +static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, 0); + +/* Display power use */ +static ssize_t aem_show_power(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *data = dev_get_drvdata(dev); + u64 before, after, delta, time; + signed long leftover; + struct timespec b, a; + + mutex_lock(&data->lock); + update_aem_energy(data); + getnstimeofday(&b); + before = data->energy[attr->index]; + + leftover = schedule_timeout_interruptible( + msecs_to_jiffies(data->power_period[attr->index]) + ); + if (leftover) { + mutex_unlock(&data->lock); + return 0; + } + + update_aem_energy(data); + getnstimeofday(&a); + after = data->energy[attr->index]; + mutex_unlock(&data->lock); + + time = timespec_to_ns(&a) - timespec_to_ns(&b); + delta = (after - before) * UJ_PER_MJ; + + return sprintf(buf, "%llu\n", + (unsigned long long)div64_u64(delta * NSEC_PER_SEC, time)); +} + +/* Display energy use */ +static ssize_t aem_show_energy(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *a = dev_get_drvdata(dev); + a->update(a); + + return sprintf(buf, "%llu\n", + (unsigned long long)a->energy[attr->index] * 1000); +} + +/* Display power interval registers */ +static ssize_t aem_show_power_period(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *a = dev_get_drvdata(dev); + a->update(a); + + return sprintf(buf, "%lu\n", a->power_period[attr->index]); +} + +/* Set power interval registers */ +static ssize_t aem_set_power_period(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *a = dev_get_drvdata(dev); + unsigned long temp; + int res; + + res = strict_strtoul(buf, 10, &temp); + if (res) + return res; + + if (temp < AEM_MIN_POWER_INTERVAL) + return -EINVAL; + + mutex_lock(&a->lock); + a->power_period[attr->index] = temp; + mutex_unlock(&a->lock); + + return count; +} + +/* Discover sensors on an AEM device */ +static int aem_register_sensors(struct aem_data *data, + struct aem_ro_sensor_template *ro, + struct aem_rw_sensor_template *rw) +{ + struct device *dev = &data->pdev->dev; + struct sensor_device_attribute *sensors = data->sensors; + int err; + + /* Set up read-only sensors */ + while (ro->label) { + sensors->dev_attr.attr.name = ro->label; + sensors->dev_attr.attr.mode = S_IRUGO; + sensors->dev_attr.show = ro->show; + sensors->index = ro->index; + + err = device_create_file(dev, &sensors->dev_attr); + if (err) { + sensors->dev_attr.attr.name = NULL; + goto error; + } + sensors++; + ro++; + } + + /* Set up read-write sensors */ + while (rw->label) { + sensors->dev_attr.attr.name = rw->label; + sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; + sensors->dev_attr.show = rw->show; + sensors->dev_attr.store = rw->set; + sensors->index = rw->index; + + err = device_create_file(dev, &sensors->dev_attr); + if (err) { + sensors->dev_attr.attr.name = NULL; + goto error; + } + sensors++; + rw++; + } + + err = device_create_file(dev, &sensor_dev_attr_name.dev_attr); + if (err) + goto error; + err = device_create_file(dev, &sensor_dev_attr_version.dev_attr); + return err; + +error: + aem_remove_sensors(data); + return err; +} + +/* sysfs support functions for AEM2 sensors */ + +/* Display temperature use */ +static ssize_t aem2_show_temp(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *a = dev_get_drvdata(dev); + a->update(a); + + return sprintf(buf, "%u\n", a->temp[attr->index] * 1000); +} + +/* Display power-capping registers */ +static ssize_t aem2_show_pcap_value(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + struct aem_data *a = dev_get_drvdata(dev); + a->update(a); + + return sprintf(buf, "%u\n", a->pcap[attr->index] * 100000); +} + +/* Remove sensors attached to an AEM device */ +static void aem_remove_sensors(struct aem_data *data) +{ + int i; + + for (i = 0; i < AEM_NUM_SENSORS; i++) { + if (!data->sensors[i].dev_attr.attr.name) + continue; + device_remove_file(&data->pdev->dev, + &data->sensors[i].dev_attr); + } + + device_remove_file(&data->pdev->dev, + &sensor_dev_attr_name.dev_attr); + device_remove_file(&data->pdev->dev, + &sensor_dev_attr_version.dev_attr); +} + +/* Sensor probe functions */ + +/* Description of AEM1 sensors */ +static struct aem_ro_sensor_template aem1_ro_sensors[] = { +{"energy1_input", aem_show_energy, 0}, +{"power1_average", aem_show_power, 0}, +{NULL, NULL, 0}, +}; + +static struct aem_rw_sensor_template aem1_rw_sensors[] = { +{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0}, +{NULL, NULL, NULL, 0}, +}; + +/* Description of AEM2 sensors */ +static struct aem_ro_sensor_template aem2_ro_sensors[] = { +{"energy1_input", aem_show_energy, 0}, +{"energy2_input", aem_show_energy, 1}, +{"power1_average", aem_show_power, 0}, +{"power2_average", aem_show_power, 1}, +{"temp1_input", aem2_show_temp, 0}, +{"temp2_input", aem2_show_temp, 1}, + +{"power4_average", aem2_show_pcap_value, POWER_CAP_MAX_HOTPLUG}, +{"power5_average", aem2_show_pcap_value, POWER_CAP_MAX}, +{"power6_average", aem2_show_pcap_value, POWER_CAP_MIN_WARNING}, +{"power7_average", aem2_show_pcap_value, POWER_CAP_MIN}, + +{"power3_average", aem2_show_pcap_value, POWER_AUX}, +{"power_cap", aem2_show_pcap_value, POWER_CAP}, +{NULL, NULL, 0}, +}; + +static struct aem_rw_sensor_template aem2_rw_sensors[] = { +{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0}, +{"power2_average_interval", aem_show_power_period, aem_set_power_period, 1}, +{NULL, NULL, NULL, 0}, +}; + +/* Set up AEM1 sensor attrs */ +static int aem1_find_sensors(struct aem_data *data) +{ + return aem_register_sensors(data, aem1_ro_sensors, aem1_rw_sensors); +} + +/* Set up AEM2 sensor attrs */ +static int aem2_find_sensors(struct aem_data *data) +{ + return aem_register_sensors(data, aem2_ro_sensors, aem2_rw_sensors); +} + +/* Module init/exit routines */ + +static int __init aem_init(void) +{ + int res; + + res = driver_register(&aem_driver); + if (res) { + printk(KERN_ERR "Can't register aem driver\n"); + return res; + } + + res = ipmi_smi_watcher_register(&driver_data.bmc_events); + if (res) + goto ipmi_reg_err; + return 0; + +ipmi_reg_err: + driver_unregister(&aem_driver); + return res; + +} + +static void __exit aem_exit(void) +{ + struct aem_data *p1, *next1; + + ipmi_smi_watcher_unregister(&driver_data.bmc_events); + driver_unregister(&aem_driver); + list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) + aem_delete(p1); +} + +MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>"); +MODULE_DESCRIPTION("IBM Active Energy Manager power/temp sensor driver"); +MODULE_LICENSE("GPL"); + +module_init(aem_init); +module_exit(aem_exit); diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index fbe16d5250a4..1adf2efd3cb3 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -747,7 +747,9 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv, break; case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED: kmem_cache_free(ib_mad_cache, mad_priv); - break; + kfree(local); + ret = 1; + goto out; case IB_MAD_RESULT_SUCCESS: /* Treat like an incoming receive MAD */ port_priv = ib_get_mad_port(mad_agent_priv->agent.device, diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c index 79dbe5beae52..992613799228 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_qp.c +++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c @@ -229,7 +229,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, struct ib_send_wr **bad_wr) { int err = 0; - u8 t3_wr_flit_cnt; + u8 uninitialized_var(t3_wr_flit_cnt); enum t3_wr_opcode t3_wr_opcode = 0; enum t3_wr_flags t3_wr_flags; struct iwch_qp *qhp; diff --git a/drivers/infiniband/hw/ipath/ipath_sdma.c b/drivers/infiniband/hw/ipath/ipath_sdma.c index 3697449c1ba4..0a8c1b8091a2 100644 --- a/drivers/infiniband/hw/ipath/ipath_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_sdma.c @@ -345,7 +345,7 @@ resched: * state change */ if (jiffies > dd->ipath_sdma_abort_jiffies) { - ipath_dbg("looping with status 0x%016llx\n", + ipath_dbg("looping with status 0x%08lx\n", dd->ipath_sdma_status); dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ; } @@ -615,7 +615,7 @@ void ipath_restart_sdma(struct ipath_devdata *dd) } spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags); if (!needed) { - ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n", + ipath_dbg("invalid attempt to restart SDMA, status 0x%08lx\n", dd->ipath_sdma_status); goto bail; } diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c index 7fd18e833907..0596ec16fcbd 100644 --- a/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/drivers/infiniband/hw/ipath/ipath_uc.c @@ -407,12 +407,11 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, dev->n_pkt_drops++; goto done; } - /* XXX Need to free SGEs */ + wc.opcode = IB_WC_RECV; last_imm: ipath_copy_sge(&qp->r_sge, data, tlen); wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; - wc.opcode = IB_WC_RECV; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; wc.slid = qp->remote_ah_attr.dlid; @@ -514,6 +513,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, goto done; } wc.byte_len = qp->r_len; + wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; goto last_imm; case OP(RDMA_WRITE_LAST): diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 8e02ecfec188..a80df22deae8 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -333,6 +333,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) + send_wqe_overhead(type, qp->flags); + if (s > dev->dev->caps.max_sq_desc_sz) + return -EINVAL; + /* * Hermon supports shrinking WQEs, such that a single work * request can include multiple units of 1 << wqe_shift. This @@ -372,9 +375,6 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, qp->sq.wqe_shift = ilog2(roundup_pow_of_two(s)); for (;;) { - if (1 << qp->sq.wqe_shift > dev->dev->caps.max_sq_desc_sz) - return -EINVAL; - qp->sq_max_wqes_per_wr = DIV_ROUND_UP(s, 1U << qp->sq.wqe_shift); /* @@ -395,7 +395,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, ++qp->sq.wqe_shift; } - qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) - + qp->sq.max_gs = (min(dev->dev->caps.max_sq_desc_sz, + (qp->sq_max_wqes_per_wr << qp->sq.wqe_shift)) - send_wqe_overhead(type, qp->flags)) / sizeof (struct mlx4_wqe_data_seg); @@ -411,7 +412,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, cap->max_send_wr = qp->sq.max_post = (qp->sq.wqe_cnt - qp->sq_spare_wqes) / qp->sq_max_wqes_per_wr; - cap->max_send_sge = qp->sq.max_gs; + cap->max_send_sge = min(qp->sq.max_gs, + min(dev->dev->caps.max_sq_sg, + dev->dev->caps.max_rq_sg)); /* We don't support inline sends for kernel QPs (yet) */ cap->max_inline_data = 0; @@ -1457,7 +1460,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, unsigned ind; int uninitialized_var(stamp); int uninitialized_var(size); - unsigned seglen; + unsigned uninitialized_var(seglen); int i; spin_lock_irqsave(&qp->sq.lock, flags); diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 9ebadd6e0cfb..200cf13fc9bb 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -45,6 +45,7 @@ #include "mthca_cmd.h" #include "mthca_profile.h" #include "mthca_memfree.h" +#include "mthca_wqe.h" MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver"); @@ -200,7 +201,18 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim) mdev->limits.gid_table_len = dev_lim->max_gids; mdev->limits.pkey_table_len = dev_lim->max_pkeys; mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay; - mdev->limits.max_sg = dev_lim->max_sg; + /* + * Need to allow for worst case send WQE overhead and check + * whether max_desc_sz imposes a lower limit than max_sg; UD + * send has the biggest overhead. + */ + mdev->limits.max_sg = min_t(int, dev_lim->max_sg, + (dev_lim->max_desc_sz - + sizeof (struct mthca_next_seg) - + (mthca_is_memfree(mdev) ? + sizeof (struct mthca_arbel_ud_seg) : + sizeof (struct mthca_tavor_ud_seg))) / + sizeof (struct mthca_data_seg)); mdev->limits.max_wqes = dev_lim->max_qp_sz; mdev->limits.max_qp_init_rdma = dev_lim->max_requester_per_qp; mdev->limits.reserved_qps = dev_lim->reserved_qps; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index d00a2c174aee..3f663fb852c1 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -194,7 +194,13 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, /* Set the cached Q_Key before we attach if it's the broadcast group */ if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid))) { + spin_lock_irq(&priv->lock); + if (!priv->broadcast) { + spin_unlock_irq(&priv->lock); + return -EAGAIN; + } priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); + spin_unlock_irq(&priv->lock); priv->tx_wr.wr.ud.remote_qkey = priv->qkey; } diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index d3999a8e9f88..53f6ad1235db 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -462,11 +462,11 @@ static int hycapi_read_proc(char *page, char **start, off_t off, default: s = "???"; break; } len += sprintf(page+len, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != 0) + if ((s = cinfo->version[VER_DRIVER]) != NULL) len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != 0) + if ((s = cinfo->version[VER_CARDTYPE]) != NULL) len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != 0) + if ((s = cinfo->version[VER_SERIAL]) != NULL) len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c14dacdacfac..b26927ce889c 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -203,17 +203,6 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) * bitmap file handling - read and write the bitmap file and its superblock */ -/* copy the pathname of a file to a buffer */ -char *file_path(struct file *file, char *buf, int count) -{ - if (!buf) - return NULL; - - buf = d_path(&file->f_path, buf, count); - - return IS_ERR(buf) ? NULL : buf; -} - /* * basic page I/O operations */ @@ -721,11 +710,13 @@ static void bitmap_file_kick(struct bitmap *bitmap) if (bitmap->file) { path = kmalloc(PAGE_SIZE, GFP_KERNEL); if (path) - ptr = file_path(bitmap->file, path, PAGE_SIZE); + ptr = d_path(&bitmap->file->f_path, path, + PAGE_SIZE); + printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n", - bmname(bitmap), ptr ? ptr : ""); + bmname(bitmap), IS_ERR(ptr) ? "" : ptr); kfree(path); } else diff --git a/drivers/md/md.c b/drivers/md/md.c index 83eb78b00137..51c19f86ff99 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -74,6 +74,8 @@ static DEFINE_SPINLOCK(pers_lock); static void md_print_devices(void); +static DECLARE_WAIT_QUEUE_HEAD(resync_wait); + #define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); } /* @@ -3013,6 +3015,36 @@ degraded_show(mddev_t *mddev, char *page) static struct md_sysfs_entry md_degraded = __ATTR_RO(degraded); static ssize_t +sync_force_parallel_show(mddev_t *mddev, char *page) +{ + return sprintf(page, "%d\n", mddev->parallel_resync); +} + +static ssize_t +sync_force_parallel_store(mddev_t *mddev, const char *buf, size_t len) +{ + long n; + + if (strict_strtol(buf, 10, &n)) + return -EINVAL; + + if (n != 0 && n != 1) + return -EINVAL; + + mddev->parallel_resync = n; + + if (mddev->sync_thread) + wake_up(&resync_wait); + + return len; +} + +/* force parallel resync, even with shared block devices */ +static struct md_sysfs_entry md_sync_force_parallel = +__ATTR(sync_force_parallel, S_IRUGO|S_IWUSR, + sync_force_parallel_show, sync_force_parallel_store); + +static ssize_t sync_speed_show(mddev_t *mddev, char *page) { unsigned long resync, dt, db; @@ -3187,6 +3219,7 @@ static struct attribute *md_redundancy_attrs[] = { &md_sync_min.attr, &md_sync_max.attr, &md_sync_speed.attr, + &md_sync_force_parallel.attr, &md_sync_completed.attr, &md_max_sync.attr, &md_suspend_lo.attr, @@ -3691,6 +3724,8 @@ static int do_md_stop(mddev_t * mddev, int mode) module_put(mddev->pers->owner); mddev->pers = NULL; + /* tell userspace to handle 'inactive' */ + sysfs_notify(&mddev->kobj, NULL, "array_state"); set_capacity(disk, 0); mddev->changed = 1; @@ -3987,8 +4022,8 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg) if (!buf) goto out; - ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname)); - if (!ptr) + ptr = d_path(&mddev->bitmap->file->f_path, buf, sizeof(file->pathname)); + if (IS_ERR(ptr)) goto out; strcpy(file->pathname, ptr); @@ -5399,7 +5434,7 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok) atomic_sub(blocks, &mddev->recovery_active); wake_up(&mddev->recovery_wait); if (!ok) { - set_bit(MD_RECOVERY_ERR, &mddev->recovery); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_wakeup_thread(mddev->thread); // stop recovery, signal do_sync .... } @@ -5435,8 +5470,11 @@ void md_write_start(mddev_t *mddev, struct bio *bi) md_wakeup_thread(mddev->thread); } spin_unlock_irq(&mddev->write_lock); + sysfs_notify(&mddev->kobj, NULL, "array_state"); } - wait_event(mddev->sb_wait, mddev->flags==0); + wait_event(mddev->sb_wait, + !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && + !test_bit(MD_CHANGE_PENDING, &mddev->flags)); } void md_write_end(mddev_t *mddev) @@ -5471,13 +5509,17 @@ void md_allow_write(mddev_t *mddev) mddev->safemode = 1; spin_unlock_irq(&mddev->write_lock); md_update_sb(mddev, 0); + + sysfs_notify(&mddev->kobj, NULL, "array_state"); + /* wait for the dirty state to be recorded in the metadata */ + wait_event(mddev->sb_wait, + !test_bit(MD_CHANGE_CLEAN, &mddev->flags) && + !test_bit(MD_CHANGE_PENDING, &mddev->flags)); } else spin_unlock_irq(&mddev->write_lock); } EXPORT_SYMBOL_GPL(md_allow_write); -static DECLARE_WAIT_QUEUE_HEAD(resync_wait); - #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) void md_do_sync(mddev_t *mddev) @@ -5541,8 +5583,9 @@ void md_do_sync(mddev_t *mddev) for_each_mddev(mddev2, tmp) { if (mddev2 == mddev) continue; - if (mddev2->curr_resync && - match_mddev_units(mddev,mddev2)) { + if (!mddev->parallel_resync + && mddev2->curr_resync + && match_mddev_units(mddev, mddev2)) { DEFINE_WAIT(wq); if (mddev < mddev2 && mddev->curr_resync == 2) { /* arbitrarily yield */ @@ -5647,7 +5690,7 @@ void md_do_sync(mddev_t *mddev) sectors = mddev->pers->sync_request(mddev, j, &skipped, currspeed < speed_min(mddev)); if (sectors == 0) { - set_bit(MD_RECOVERY_ERR, &mddev->recovery); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto out; } @@ -5670,8 +5713,7 @@ void md_do_sync(mddev_t *mddev) last_check = io_sectors; - if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) || - test_bit(MD_RECOVERY_ERR, &mddev->recovery)) + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) break; repeat: @@ -5725,8 +5767,7 @@ void md_do_sync(mddev_t *mddev) /* tell personality that we are finished */ mddev->pers->sync_request(mddev, max_sectors, &skipped, 1); - if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && - !test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && + if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && mddev->curr_resync > 2) { if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { @@ -5795,7 +5836,10 @@ static int remove_and_add_spares(mddev_t *mddev) } if (mddev->degraded) { - rdev_for_each(rdev, rtmp, mddev) + rdev_for_each(rdev, rtmp, mddev) { + if (rdev->raid_disk >= 0 && + !test_bit(In_sync, &rdev->flags)) + spares++; if (rdev->raid_disk < 0 && !test_bit(Faulty, &rdev->flags)) { rdev->recovery_offset = 0; @@ -5813,6 +5857,7 @@ static int remove_and_add_spares(mddev_t *mddev) } else break; } + } } return spares; } @@ -5826,7 +5871,7 @@ static int remove_and_add_spares(mddev_t *mddev) * to do that as needed. * When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in * "->recovery" and create a thread at ->sync_thread. - * When the thread finishes it sets MD_RECOVERY_DONE (and might set MD_RECOVERY_ERR) + * When the thread finishes it sets MD_RECOVERY_DONE * and wakeups up this thread which will reap the thread and finish up. * This thread also removes any faulty devices (with nr_pending == 0). * @@ -5901,8 +5946,7 @@ void md_check_recovery(mddev_t *mddev) /* resync has finished, collect result */ md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; - if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && - !test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { /* success...*/ /* activate any spares */ mddev->pers->spare_active(mddev); @@ -5926,7 +5970,6 @@ void md_check_recovery(mddev_t *mddev) * might be left set */ clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); - clear_bit(MD_RECOVERY_ERR, &mddev->recovery); clear_bit(MD_RECOVERY_INTR, &mddev->recovery); clear_bit(MD_RECOVERY_DONE, &mddev->recovery); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 4f4d1f383842..e968116e0de9 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -327,7 +327,8 @@ static int multipath_remove_disk(mddev_t *mddev, int number) if (rdev) { if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { - printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number); + printk(KERN_ERR "hot-remove-disk, slot %d is identified" + " but is still operational!\n", number); err = -EBUSY; goto abort; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index ac409b7d83f5..c610b947218a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -773,7 +773,7 @@ static int make_request(struct request_queue *q, struct bio * bio) r1bio_t *r1_bio; struct bio *read_bio; int i, targets = 0, disks; - struct bitmap *bitmap = mddev->bitmap; + struct bitmap *bitmap; unsigned long flags; struct bio_list bl; struct page **behind_pages = NULL; @@ -802,6 +802,8 @@ static int make_request(struct request_queue *q, struct bio * bio) wait_barrier(conf); + bitmap = mddev->bitmap; + disk_stat_inc(mddev->gendisk, ios[rw]); disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); @@ -1025,7 +1027,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) /* * if recovery is running, make sure it aborts. */ - set_bit(MD_RECOVERY_ERR, &mddev->recovery); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); } else set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); @@ -1146,6 +1148,14 @@ static int raid1_remove_disk(mddev_t *mddev, int number) err = -EBUSY; goto abort; } + /* Only remove non-faulty devices is recovery + * is not possible. + */ + if (!test_bit(Faulty, &rdev->flags) && + mddev->degraded < conf->raid_disks) { + err = -EBUSY; + goto abort; + } p->rdev = NULL; synchronize_rcu(); if (atomic_read(&rdev->nr_pending)) { @@ -1282,6 +1292,7 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) rdev_dec_pending(conf->mirrors[i].rdev, mddev); } else { /* fixup the bio for reuse */ + int size; sbio->bi_vcnt = vcnt; sbio->bi_size = r1_bio->sectors << 9; sbio->bi_idx = 0; @@ -1295,10 +1306,20 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) sbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; sbio->bi_bdev = conf->mirrors[i].rdev->bdev; - for (j = 0; j < vcnt ; j++) - memcpy(page_address(sbio->bi_io_vec[j].bv_page), + size = sbio->bi_size; + for (j = 0; j < vcnt ; j++) { + struct bio_vec *bi; + bi = &sbio->bi_io_vec[j]; + bi->bv_offset = 0; + if (size > PAGE_SIZE) + bi->bv_len = PAGE_SIZE; + else + bi->bv_len = size; + size -= PAGE_SIZE; + memcpy(page_address(bi->bv_page), page_address(pbio->bi_io_vec[j].bv_page), PAGE_SIZE); + } } } diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 8536ede1e712..1de17da34a95 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1020,7 +1020,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) /* * if recovery is running, make sure it aborts. */ - set_bit(MD_RECOVERY_ERR, &mddev->recovery); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); } set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); @@ -1171,6 +1171,14 @@ static int raid10_remove_disk(mddev_t *mddev, int number) err = -EBUSY; goto abort; } + /* Only remove faulty devices in recovery + * is not possible. + */ + if (!test_bit(Faulty, &rdev->flags) && + enough(conf)) { + err = -EBUSY; + goto abort; + } p->rdev = NULL; synchronize_rcu(); if (atomic_read(&rdev->nr_pending)) { @@ -1237,6 +1245,7 @@ static void end_sync_write(struct bio *bio, int error) if (!uptodate) md_error(mddev, conf->mirrors[d].rdev); + update_head_pos(i, r10_bio); while (atomic_dec_and_test(&r10_bio->remaining)) { @@ -1844,7 +1853,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i if (rb2) atomic_dec(&rb2->remaining); r10_bio = rb2; - if (!test_and_set_bit(MD_RECOVERY_ERR, &mddev->recovery)) + if (!test_and_set_bit(MD_RECOVERY_INTR, + &mddev->recovery)) printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n", mdname(mddev)); break; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 93fde48c0f42..425958a76b84 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -94,6 +94,8 @@ #define __inline__ #endif +#define printk_rl(args...) ((void) (printk_ratelimit() && printk(args))) + #if !RAID6_USE_EMPTY_ZERO_PAGE /* In .bss so it's zeroed */ const char raid6_empty_zero_page[PAGE_SIZE] __attribute__((aligned(256))); @@ -1143,10 +1145,12 @@ static void raid5_end_read_request(struct bio * bi, int error) set_bit(R5_UPTODATE, &sh->dev[i].flags); if (test_bit(R5_ReadError, &sh->dev[i].flags)) { rdev = conf->disks[i].rdev; - printk(KERN_INFO "raid5:%s: read error corrected (%lu sectors at %llu on %s)\n", - mdname(conf->mddev), STRIPE_SECTORS, - (unsigned long long)(sh->sector + rdev->data_offset), - bdevname(rdev->bdev, b)); + printk_rl(KERN_INFO "raid5:%s: read error corrected" + " (%lu sectors at %llu on %s)\n", + mdname(conf->mddev), STRIPE_SECTORS, + (unsigned long long)(sh->sector + + rdev->data_offset), + bdevname(rdev->bdev, b)); clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); } @@ -1160,16 +1164,22 @@ static void raid5_end_read_request(struct bio * bi, int error) clear_bit(R5_UPTODATE, &sh->dev[i].flags); atomic_inc(&rdev->read_errors); if (conf->mddev->degraded) - printk(KERN_WARNING "raid5:%s: read error not correctable (sector %llu on %s).\n", - mdname(conf->mddev), - (unsigned long long)(sh->sector + rdev->data_offset), - bdn); + printk_rl(KERN_WARNING + "raid5:%s: read error not correctable " + "(sector %llu on %s).\n", + mdname(conf->mddev), + (unsigned long long)(sh->sector + + rdev->data_offset), + bdn); else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) /* Oh, no!!! */ - printk(KERN_WARNING "raid5:%s: read error NOT corrected!! (sector %llu on %s).\n", - mdname(conf->mddev), - (unsigned long long)(sh->sector + rdev->data_offset), - bdn); + printk_rl(KERN_WARNING + "raid5:%s: read error NOT corrected!! " + "(sector %llu on %s).\n", + mdname(conf->mddev), + (unsigned long long)(sh->sector + + rdev->data_offset), + bdn); else if (atomic_read(&rdev->read_errors) > conf->max_nr_stripes) printk(KERN_WARNING @@ -1258,7 +1268,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) /* * if recovery was running, make sure it aborts. */ - set_bit(MD_RECOVERY_ERR, &mddev->recovery); + set_bit(MD_RECOVERY_INTR, &mddev->recovery); } set_bit(Faulty, &rdev->flags); printk (KERN_ALERT @@ -4564,6 +4574,14 @@ static int raid5_remove_disk(mddev_t *mddev, int number) err = -EBUSY; goto abort; } + /* Only remove non-faulty devices if recovery + * isn't possible. + */ + if (!test_bit(Faulty, &rdev->flags) && + mddev->degraded <= conf->max_degraded) { + err = -EBUSY; + goto abort; + } p->rdev = NULL; synchronize_rcu(); if (atomic_read(&rdev->nr_pending)) { diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index 87d8795823d7..b9d097c9f6bb 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -1062,7 +1062,6 @@ el3_rx(struct net_device *dev) struct sk_buff *skb; skb = dev_alloc_skb(pkt_len+5); - dev->stats.rx_bytes += pkt_len; if (el3_debug > 4) printk("Receiving packet size %d status %4.4x.\n", pkt_len, rx_status); @@ -1077,6 +1076,7 @@ el3_rx(struct net_device *dev) skb->protocol = eth_type_trans(skb,dev); netif_rx(skb); dev->last_rx = jiffies; + dev->stats.rx_bytes += pkt_len; dev->stats.rx_packets++; continue; } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 3634b5fd7919..7023d77bf380 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -1239,12 +1239,7 @@ static int au1000_rx(struct net_device *dev) */ static irqreturn_t au1000_interrupt(int irq, void *dev_id) { - struct net_device *dev = (struct net_device *) dev_id; - - if (dev == NULL) { - printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name); - return IRQ_RETVAL(1); - } + struct net_device *dev = dev_id; /* Handle RX interrupts first to minimize chance of overrun */ diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 89c0018132ec..41443435ab1c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -22,7 +22,6 @@ #include <linux/crc32.h> #include <linux/device.h> #include <linux/spinlock.h> -#include <linux/ethtool.h> #include <linux/mii.h> #include <linux/phy.h> #include <linux/netdevice.h> diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 93e13636f8dd..83768df27806 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -142,8 +142,8 @@ #define DRV_MODULE_NAME "cassini" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5" -#define DRV_MODULE_RELDATE "4 Jan 2008" +#define DRV_MODULE_VERSION "1.6" +#define DRV_MODULE_RELDATE "21 May 2008" #define CAS_DEF_MSG_ENABLE \ (NETIF_MSG_DRV | \ @@ -2136,9 +2136,12 @@ end_copy_pkt: if (addr) cas_page_unmap(addr); } - skb->csum = csum_unfold(~csum); - skb->ip_summed = CHECKSUM_COMPLETE; skb->protocol = eth_type_trans(skb, cp->dev); + if (skb->protocol == htons(ETH_P_IP)) { + skb->csum = csum_unfold(~csum); + skb->ip_summed = CHECKSUM_COMPLETE; + } else + skb->ip_summed = CHECKSUM_NONE; return len; } diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 2b5740b3d182..7f3f62e1b113 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -38,6 +38,7 @@ #include <linux/platform_device.h> #include <linux/dma-mapping.h> #include <asm/gpio.h> +#include <asm/atomic.h> MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); @@ -187,6 +188,7 @@ struct cpmac_desc { #define CPMAC_EOQ 0x1000 struct sk_buff *skb; struct cpmac_desc *next; + struct cpmac_desc *prev; dma_addr_t mapping; dma_addr_t data_mapping; }; @@ -208,6 +210,7 @@ struct cpmac_priv { struct work_struct reset_work; struct platform_device *pdev; struct napi_struct napi; + atomic_t reset_pending; }; static irqreturn_t cpmac_irq(int, void *); @@ -241,6 +244,16 @@ static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc) printk("\n"); } +static void cpmac_dump_all_desc(struct net_device *dev) +{ + struct cpmac_priv *priv = netdev_priv(dev); + struct cpmac_desc *dump = priv->rx_head; + do { + cpmac_dump_desc(dev, dump); + dump = dump->next; + } while (dump != priv->rx_head); +} + static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) { int i; @@ -412,21 +425,42 @@ static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv, static int cpmac_poll(struct napi_struct *napi, int budget) { struct sk_buff *skb; - struct cpmac_desc *desc; - int received = 0; + struct cpmac_desc *desc, *restart; struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi); + int received = 0, processed = 0; spin_lock(&priv->rx_lock); if (unlikely(!priv->rx_head)) { if (netif_msg_rx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: rx: polling, but no queue\n", priv->dev->name); + spin_unlock(&priv->rx_lock); netif_rx_complete(priv->dev, napi); return 0; } desc = priv->rx_head; + restart = NULL; while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) { + processed++; + + if ((desc->dataflags & CPMAC_EOQ) != 0) { + /* The last update to eoq->hw_next didn't happen + * soon enough, and the receiver stopped here. + *Remember this descriptor so we can restart + * the receiver after freeing some space. + */ + if (unlikely(restart)) { + if (netif_msg_rx_err(priv)) + printk(KERN_ERR "%s: poll found a" + " duplicate EOQ: %p and %p\n", + priv->dev->name, restart, desc); + goto fatal_error; + } + + restart = desc->next; + } + skb = cpmac_rx_one(priv, desc); if (likely(skb)) { netif_receive_skb(skb); @@ -435,19 +469,90 @@ static int cpmac_poll(struct napi_struct *napi, int budget) desc = desc->next; } + if (desc != priv->rx_head) { + /* We freed some buffers, but not the whole ring, + * add what we did free to the rx list */ + desc->prev->hw_next = (u32)0; + priv->rx_head->prev->hw_next = priv->rx_head->mapping; + } + + /* Optimization: If we did not actually process an EOQ (perhaps because + * of quota limits), check to see if the tail of the queue has EOQ set. + * We should immediately restart in that case so that the receiver can + * restart and run in parallel with more packet processing. + * This lets us handle slightly larger bursts before running + * out of ring space (assuming dev->weight < ring_size) */ + + if (!restart && + (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ)) + == CPMAC_EOQ && + (priv->rx_head->dataflags & CPMAC_OWN) != 0) { + /* reset EOQ so the poll loop (above) doesn't try to + * restart this when it eventually gets to this descriptor. + */ + priv->rx_head->prev->dataflags &= ~CPMAC_EOQ; + restart = priv->rx_head; + } + + if (restart) { + priv->dev->stats.rx_errors++; + priv->dev->stats.rx_fifo_errors++; + if (netif_msg_rx_err(priv) && net_ratelimit()) + printk(KERN_WARNING "%s: rx dma ring overrun\n", + priv->dev->name); + + if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) { + if (netif_msg_drv(priv)) + printk(KERN_ERR "%s: cpmac_poll is trying to " + "restart rx from a descriptor that's " + "not free: %p\n", + priv->dev->name, restart); + goto fatal_error; + } + + cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping); + } + priv->rx_head = desc; spin_unlock(&priv->rx_lock); if (unlikely(netif_msg_rx_status(priv))) printk(KERN_DEBUG "%s: poll processed %d packets\n", priv->dev->name, received); - if (desc->dataflags & CPMAC_OWN) { + if (processed == 0) { + /* we ran out of packets to read, + * revert to interrupt-driven mode */ netif_rx_complete(priv->dev, napi); - cpmac_write(priv->regs, CPMAC_RX_PTR(0), (u32)desc->mapping); cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); return 0; } return 1; + +fatal_error: + /* Something went horribly wrong. + * Reset hardware to try to recover rather than wedging. */ + + if (netif_msg_drv(priv)) { + printk(KERN_ERR "%s: cpmac_poll is confused. " + "Resetting hardware\n", priv->dev->name); + cpmac_dump_all_desc(priv->dev); + printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n", + priv->dev->name, + cpmac_read(priv->regs, CPMAC_RX_PTR(0)), + cpmac_read(priv->regs, CPMAC_RX_ACK(0))); + } + + spin_unlock(&priv->rx_lock); + netif_rx_complete(priv->dev, napi); + netif_stop_queue(priv->dev); + napi_disable(&priv->napi); + + atomic_inc(&priv->reset_pending); + cpmac_hw_stop(priv->dev); + if (!schedule_work(&priv->reset_work)) + atomic_dec(&priv->reset_pending); + return 0; + } static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -456,6 +561,9 @@ static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) struct cpmac_desc *desc; struct cpmac_priv *priv = netdev_priv(dev); + if (unlikely(atomic_read(&priv->reset_pending))) + return NETDEV_TX_BUSY; + if (unlikely(skb_padto(skb, ETH_ZLEN))) return NETDEV_TX_OK; @@ -621,8 +729,10 @@ static void cpmac_clear_rx(struct net_device *dev) desc->dataflags = CPMAC_OWN; dev->stats.rx_dropped++; } + desc->hw_next = desc->next->mapping; desc = desc->next; } + priv->rx_head->prev->hw_next = 0; } static void cpmac_clear_tx(struct net_device *dev) @@ -635,14 +745,14 @@ static void cpmac_clear_tx(struct net_device *dev) priv->desc_ring[i].dataflags = 0; if (priv->desc_ring[i].skb) { dev_kfree_skb_any(priv->desc_ring[i].skb); - if (netif_subqueue_stopped(dev, i)) - netif_wake_subqueue(dev, i); + priv->desc_ring[i].skb = NULL; } } } static void cpmac_hw_error(struct work_struct *work) { + int i; struct cpmac_priv *priv = container_of(work, struct cpmac_priv, reset_work); @@ -651,8 +761,48 @@ static void cpmac_hw_error(struct work_struct *work) spin_unlock(&priv->rx_lock); cpmac_clear_tx(priv->dev); cpmac_hw_start(priv->dev); - napi_enable(&priv->napi); - netif_start_queue(priv->dev); + barrier(); + atomic_dec(&priv->reset_pending); + + for (i = 0; i < CPMAC_QUEUES; i++) + netif_wake_subqueue(priv->dev, i); + netif_wake_queue(priv->dev); + cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); +} + +static void cpmac_check_status(struct net_device *dev) +{ + struct cpmac_priv *priv = netdev_priv(dev); + + u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS); + int rx_channel = (macstatus >> 8) & 7; + int rx_code = (macstatus >> 12) & 15; + int tx_channel = (macstatus >> 16) & 7; + int tx_code = (macstatus >> 20) & 15; + + if (rx_code || tx_code) { + if (netif_msg_drv(priv) && net_ratelimit()) { + /* Can't find any documentation on what these + *error codes actually are. So just log them and hope.. + */ + if (rx_code) + printk(KERN_WARNING "%s: host error %d on rx " + "channel %d (macstatus %08x), resetting\n", + dev->name, rx_code, rx_channel, macstatus); + if (tx_code) + printk(KERN_WARNING "%s: host error %d on tx " + "channel %d (macstatus %08x), resetting\n", + dev->name, tx_code, tx_channel, macstatus); + } + + netif_stop_queue(dev); + cpmac_hw_stop(dev); + if (schedule_work(&priv->reset_work)) + atomic_inc(&priv->reset_pending); + if (unlikely(netif_msg_hw(priv))) + cpmac_dump_regs(dev); + } + cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); } static irqreturn_t cpmac_irq(int irq, void *dev_id) @@ -683,49 +833,32 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id) cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); - if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) { - if (netif_msg_drv(priv) && net_ratelimit()) - printk(KERN_ERR "%s: hw error, resetting...\n", - dev->name); - netif_stop_queue(dev); - napi_disable(&priv->napi); - cpmac_hw_stop(dev); - schedule_work(&priv->reset_work); - if (unlikely(netif_msg_hw(priv))) - cpmac_dump_regs(dev); - } + if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) + cpmac_check_status(dev); return IRQ_HANDLED; } static void cpmac_tx_timeout(struct net_device *dev) { - struct cpmac_priv *priv = netdev_priv(dev); int i; + struct cpmac_priv *priv = netdev_priv(dev); spin_lock(&priv->lock); dev->stats.tx_errors++; spin_unlock(&priv->lock); if (netif_msg_tx_err(priv) && net_ratelimit()) printk(KERN_WARNING "%s: transmit timeout\n", dev->name); - /* - * FIXME: waking up random queue is not the best thing to - * do... on the other hand why we got here at all? - */ -#ifdef CONFIG_NETDEVICES_MULTIQUEUE + + atomic_inc(&priv->reset_pending); + barrier(); + cpmac_clear_tx(dev); + barrier(); + atomic_dec(&priv->reset_pending); + + netif_wake_queue(priv->dev); for (i = 0; i < CPMAC_QUEUES; i++) - if (priv->desc_ring[i].skb) { - priv->desc_ring[i].dataflags = 0; - dev_kfree_skb_any(priv->desc_ring[i].skb); - netif_wake_subqueue(dev, i); - break; - } -#else - priv->desc_ring[0].dataflags = 0; - if (priv->desc_ring[0].skb) - dev_kfree_skb_any(priv->desc_ring[0].skb); - netif_wake_queue(dev); -#endif + netif_wake_subqueue(dev, i); } static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) @@ -901,9 +1034,12 @@ static int cpmac_open(struct net_device *dev) desc->buflen = CPMAC_SKB_SIZE; desc->dataflags = CPMAC_OWN; desc->next = &priv->rx_head[(i + 1) % priv->ring_size]; + desc->next->prev = desc; desc->hw_next = (u32)desc->next->mapping; } + priv->rx_head->prev->hw_next = (u32)0; + if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, dev->name, dev))) { if (netif_msg_drv(priv)) @@ -912,6 +1048,7 @@ static int cpmac_open(struct net_device *dev) goto fail_irq; } + atomic_set(&priv->reset_pending, 0); INIT_WORK(&priv->reset_work, cpmac_hw_error); cpmac_hw_start(dev); @@ -1007,21 +1144,10 @@ static int __devinit cpmac_probe(struct platform_device *pdev) if (phy_id == PHY_MAX_ADDR) { if (external_switch || dumb_switch) { - struct fixed_phy_status status = {}; - - /* - * FIXME: this should be in the platform code! - * Since there is not platform code at all (that is, - * no mainline users of that driver), place it here - * for now. - */ - phy_id = 0; - status.link = 1; - status.duplex = 1; - status.speed = 100; - fixed_phy_add(PHY_POLL, phy_id, &status); + mdio_bus_id = 0; /* fixed phys bus */ + phy_id = pdev->id; } else { - printk(KERN_ERR "cpmac: no PHY present\n"); + dev_err(&pdev->dev, "no PHY present\n"); return -ENODEV; } } @@ -1064,10 +1190,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - snprintf(priv->phy_name, BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id); - - priv->phy = phy_connect(dev, priv->phy_name, &cpmac_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + priv->phy = phy_connect(dev, cpmac_mii.phy_map[phy_id]->dev.bus_id, + &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phy)) { if (netif_msg_drv(priv)) printk(KERN_ERR "%s: Could not attach to PHY\n", diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index d45bcd2660af..864295e081b6 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -903,7 +903,7 @@ dm9000_stop(struct net_device *ndev) if (netif_msg_ifdown(db)) dev_dbg(db->dev, "shutting down %s\n", ndev->name); - cancel_delayed_work(&db->phy_poll); + cancel_delayed_work_sync(&db->phy_poll); netif_stop_queue(ndev); netif_carrier_off(ndev); diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 8cbb40f3a506..cab1835173cd 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -4201,8 +4201,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, struct e1000_adapter *adapter; struct e1000_hw *hw; const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; - unsigned long mmio_start, mmio_len; - unsigned long flash_start, flash_len; + resource_size_t mmio_start, mmio_len; + resource_size_t flash_start, flash_len; static int cards_found; int i, err, pci_using_dac; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index d1b6d4e7495d..287a61918739 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -2213,8 +2213,6 @@ static void ehea_vlan_rx_register(struct net_device *dev, goto out; } - memset(cb1->vlan_filter, 0, sizeof(cb1->vlan_filter)); - hret = ehea_h_modify_ehea_port(adapter->handle, port->logical_port_id, H_PORT_CB1, H_PORT_CB1_ALL, cb1); if (hret != H_SUCCESS) @@ -3178,11 +3176,12 @@ out_err: static void ehea_shutdown_single_port(struct ehea_port *port) { + struct ehea_adapter *adapter = port->adapter; unregister_netdev(port->netdev); ehea_unregister_port(port); kfree(port->mc_list); free_netdev(port->netdev); - port->adapter->active_ports--; + adapter->active_ports--; } static int ehea_setup_ports(struct ehea_adapter *adapter) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 35f66d4a4595..9eca97fb0a54 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5823,6 +5823,7 @@ static int nv_resume(struct pci_dev *pdev) writel(txreg, base + NvRegTransmitPoll); rc = nv_open(dev); + nv_set_multicast(dev); out: return rc; } diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 67b4b0728fce..a5baaf59ff66 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -1093,7 +1093,7 @@ err: if (registered) unregister_netdev(ndev); - if (fep != NULL) { + if (fep && fep->ops) { (*fep->ops->free_bd)(ndev); (*fep->ops->cleanup_data)(ndev); } diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c index f90515935833..45ae9d1191d7 100644 --- a/drivers/net/hamradio/scc.c +++ b/drivers/net/hamradio/scc.c @@ -1340,9 +1340,10 @@ static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, uns case PARAM_RTS: if ( !(scc->wreg[R5] & RTS) ) { - if (arg != TX_OFF) + if (arg != TX_OFF) { scc_key_trx(scc, TX_ON); scc_start_tx_timer(scc, t_txdelay, scc->kiss.txdelay); + } } else { if (arg == TX_OFF) { diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c91b12ea26ad..36be6efc6398 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -631,7 +631,7 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) return status; } -int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp) +static int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp) { struct myri10ge_cmd cmd; int status; diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index 8f328a03847b..a550c9bd126f 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -391,7 +391,9 @@ static int fmvj18x_config(struct pcmcia_device *link) cardtype = CONTEC; break; case MANFID_FUJITSU: - if (link->card_id == PRODID_FUJITSU_MBH10302) + if (link->conf.ConfigBase == 0x0fe0) + cardtype = MBH10302; + else if (link->card_id == PRODID_FUJITSU_MBH10302) /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), but these are MBH10304 based card. */ cardtype = MBH10304; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index d041f831a18d..f6c4698ce738 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -1461,22 +1461,25 @@ static void set_multicast_list(struct net_device *dev) { unsigned int ioaddr = dev->base_addr; + unsigned value; SelectPage(0x42); + value = GetByte(XIRCREG42_SWC1) & 0xC0; + if (dev->flags & IFF_PROMISC) { /* snoop */ - PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */ + PutByte(XIRCREG42_SWC1, value | 0x06); /* set MPE and PME */ } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) { - PutByte(XIRCREG42_SWC1, 0x02); /* set MPE */ + PutByte(XIRCREG42_SWC1, value | 0x02); /* set MPE */ } else if (dev->mc_count) { /* the chip can filter 9 addresses perfectly */ - PutByte(XIRCREG42_SWC1, 0x01); + PutByte(XIRCREG42_SWC1, value | 0x01); SelectPage(0x40); PutByte(XIRCREG40_CMD0, Offline); set_addresses(dev); SelectPage(0x40); PutByte(XIRCREG40_CMD0, EnableRecv | Online); } else { /* standard usage */ - PutByte(XIRCREG42_SWC1, 0x00); + PutByte(XIRCREG42_SWC1, value | 0x00); } SelectPage(0); } @@ -1722,6 +1725,7 @@ do_reset(struct net_device *dev, int full) /* enable receiver and put the mac online */ if (full) { + set_multicast_list(dev); SelectPage(0x40); PutByte(XIRCREG40_CMD0, EnableRecv | Online); } diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index a1c454dbc164..1c89b97f4e09 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c @@ -325,7 +325,7 @@ static int pcnet32_get_regs_len(struct net_device *dev); static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *ptr); static void pcnet32_purge_tx_ring(struct net_device *dev); -static int pcnet32_alloc_ring(struct net_device *dev, char *name); +static int pcnet32_alloc_ring(struct net_device *dev, const char *name); static void pcnet32_free_ring(struct net_device *dev); static void pcnet32_check_media(struct net_device *dev, int verbose); @@ -1983,7 +1983,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) } /* if any allocation fails, caller must also call pcnet32_free_ring */ -static int pcnet32_alloc_ring(struct net_device *dev, char *name) +static int pcnet32_alloc_ring(struct net_device *dev, const char *name) { struct pcnet32_private *lp = netdev_priv(dev); diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 6bf9e76b0a00..6eb2d31d1e34 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -5,7 +5,7 @@ menuconfig PHYLIB tristate "PHY Device support and infrastructure" depends on !S390 - depends on NET_ETHERNET && (BROKEN || !S390) + depends on NET_ETHERNET help Ethernet controllers are usually attached to PHY devices. This option provides infrastructure for diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index ac3c01d28fdf..16a0e7de5888 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -207,6 +207,7 @@ int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id) return 0; } +EXPORT_SYMBOL(get_phy_id); /** * get_phy_device - reads the specified PHY device and returns its @phy_device struct diff --git a/drivers/net/s2io-regs.h b/drivers/net/s2io-regs.h index 2109508c047a..f8274f8941ea 100644 --- a/drivers/net/s2io-regs.h +++ b/drivers/net/s2io-regs.h @@ -250,7 +250,7 @@ struct XENA_dev_config { u64 tx_mat0_n[0x8]; #define TX_MAT_SET(fifo, msi) vBIT(msi, (8 * fifo), 8) - u8 unused_1[0x8]; + u64 xmsi_mask_reg; u64 stat_byte_cnt; #define STAT_BC(n) vBIT(n,4,12) diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 523478ebfd69..a20693e09ae8 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -86,7 +86,7 @@ #include "s2io.h" #include "s2io-regs.h" -#define DRV_VERSION "2.0.26.23" +#define DRV_VERSION "2.0.26.24" /* S2io Driver name & version. */ static char s2io_driver_name[] = "Neterion"; @@ -1113,9 +1113,10 @@ static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev) struct pci_dev *tdev = NULL; while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) { if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) { - if (tdev->bus == s2io_pdev->bus->parent) + if (tdev->bus == s2io_pdev->bus->parent) { pci_dev_put(tdev); return 1; + } } } return 0; @@ -1219,15 +1220,33 @@ static int init_tti(struct s2io_nic *nic, int link) TTI_DATA1_MEM_TX_URNG_B(0x10) | TTI_DATA1_MEM_TX_URNG_C(0x30) | TTI_DATA1_MEM_TX_TIMER_AC_EN; - - if (use_continuous_tx_intrs && (link == LINK_UP)) - val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN; + if (i == 0) + if (use_continuous_tx_intrs && (link == LINK_UP)) + val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN; writeq(val64, &bar0->tti_data1_mem); - val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | - TTI_DATA2_MEM_TX_UFC_B(0x20) | - TTI_DATA2_MEM_TX_UFC_C(0x40) | - TTI_DATA2_MEM_TX_UFC_D(0x80); + if (nic->config.intr_type == MSI_X) { + val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | + TTI_DATA2_MEM_TX_UFC_B(0x100) | + TTI_DATA2_MEM_TX_UFC_C(0x200) | + TTI_DATA2_MEM_TX_UFC_D(0x300); + } else { + if ((nic->config.tx_steering_type == + TX_DEFAULT_STEERING) && + (config->tx_fifo_num > 1) && + (i >= nic->udp_fifo_idx) && + (i < (nic->udp_fifo_idx + + nic->total_udp_fifos))) + val64 = TTI_DATA2_MEM_TX_UFC_A(0x50) | + TTI_DATA2_MEM_TX_UFC_B(0x80) | + TTI_DATA2_MEM_TX_UFC_C(0x100) | + TTI_DATA2_MEM_TX_UFC_D(0x120); + else + val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) | + TTI_DATA2_MEM_TX_UFC_B(0x20) | + TTI_DATA2_MEM_TX_UFC_C(0x40) | + TTI_DATA2_MEM_TX_UFC_D(0x80); + } writeq(val64, &bar0->tti_data2_mem); @@ -2813,6 +2832,15 @@ static void free_rx_buffers(struct s2io_nic *sp) } } +static int s2io_chk_rx_buffers(struct ring_info *ring) +{ + if (fill_rx_buffers(ring) == -ENOMEM) { + DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name); + DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); + } + return 0; +} + /** * s2io_poll - Rx interrupt handler for NAPI support * @napi : pointer to the napi structure. @@ -2826,57 +2854,72 @@ static void free_rx_buffers(struct s2io_nic *sp) * 0 on success and 1 if there are No Rx packets to be processed. */ -static int s2io_poll(struct napi_struct *napi, int budget) +static int s2io_poll_msix(struct napi_struct *napi, int budget) { - struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi); - struct net_device *dev = nic->dev; - int pkt_cnt = 0, org_pkts_to_process; - struct mac_info *mac_control; + struct ring_info *ring = container_of(napi, struct ring_info, napi); + struct net_device *dev = ring->dev; struct config_param *config; + struct mac_info *mac_control; + int pkts_processed = 0; + u8 *addr = NULL, val8 = 0; + struct s2io_nic *nic = dev->priv; struct XENA_dev_config __iomem *bar0 = nic->bar0; - int i; + int budget_org = budget; - mac_control = &nic->mac_control; config = &nic->config; + mac_control = &nic->mac_control; - nic->pkts_to_process = budget; - org_pkts_to_process = nic->pkts_to_process; + if (unlikely(!is_s2io_card_up(nic))) + return 0; - writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); - readl(&bar0->rx_traffic_int); + pkts_processed = rx_intr_handler(ring, budget); + s2io_chk_rx_buffers(ring); - for (i = 0; i < config->rx_ring_num; i++) { - rx_intr_handler(&mac_control->rings[i]); - pkt_cnt = org_pkts_to_process - nic->pkts_to_process; - if (!nic->pkts_to_process) { - /* Quota for the current iteration has been met */ - goto no_rx; - } + if (pkts_processed < budget_org) { + netif_rx_complete(dev, napi); + /*Re Enable MSI-Rx Vector*/ + addr = (u8 *)&bar0->xmsi_mask_reg; + addr += 7 - ring->ring_no; + val8 = (ring->ring_no == 0) ? 0x3f : 0xbf; + writeb(val8, addr); + val8 = readb(addr); } + return pkts_processed; +} +static int s2io_poll_inta(struct napi_struct *napi, int budget) +{ + struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi); + struct ring_info *ring; + struct net_device *dev = nic->dev; + struct config_param *config; + struct mac_info *mac_control; + int pkts_processed = 0; + int ring_pkts_processed, i; + struct XENA_dev_config __iomem *bar0 = nic->bar0; + int budget_org = budget; - netif_rx_complete(dev, napi); + config = &nic->config; + mac_control = &nic->mac_control; - for (i = 0; i < config->rx_ring_num; i++) { - if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { - DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name); - DBG_PRINT(INFO_DBG, " in Rx Poll!!\n"); - break; - } - } - /* Re enable the Rx interrupts. */ - writeq(0x0, &bar0->rx_traffic_mask); - readl(&bar0->rx_traffic_mask); - return pkt_cnt; + if (unlikely(!is_s2io_card_up(nic))) + return 0; -no_rx: for (i = 0; i < config->rx_ring_num; i++) { - if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { - DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name); - DBG_PRINT(INFO_DBG, " in Rx Poll!!\n"); + ring = &mac_control->rings[i]; + ring_pkts_processed = rx_intr_handler(ring, budget); + s2io_chk_rx_buffers(ring); + pkts_processed += ring_pkts_processed; + budget -= ring_pkts_processed; + if (budget <= 0) break; - } } - return pkt_cnt; + if (pkts_processed < budget_org) { + netif_rx_complete(dev, napi); + /* Re enable the Rx interrupts for the ring */ + writeq(0, &bar0->rx_traffic_mask); + readl(&bar0->rx_traffic_mask); + } + return pkts_processed; } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -2918,7 +2961,7 @@ static void s2io_netpoll(struct net_device *dev) /* check for received packet and indicate up to network */ for (i = 0; i < config->rx_ring_num; i++) - rx_intr_handler(&mac_control->rings[i]); + rx_intr_handler(&mac_control->rings[i], 0); for (i = 0; i < config->rx_ring_num; i++) { if (fill_rx_buffers(&mac_control->rings[i]) == -ENOMEM) { @@ -2934,7 +2977,8 @@ static void s2io_netpoll(struct net_device *dev) /** * rx_intr_handler - Rx interrupt handler - * @nic: device private variable. + * @ring_info: per ring structure. + * @budget: budget for napi processing. * Description: * If the interrupt is because of a received frame or if the * receive ring contains fresh as yet un-processed frames,this function is @@ -2942,15 +2986,15 @@ static void s2io_netpoll(struct net_device *dev) * stopped and sends the skb to the OSM's Rx handler and then increments * the offset. * Return Value: - * NONE. + * No. of napi packets processed. */ -static void rx_intr_handler(struct ring_info *ring_data) +static int rx_intr_handler(struct ring_info *ring_data, int budget) { int get_block, put_block; struct rx_curr_get_info get_info, put_info; struct RxD_t *rxdp; struct sk_buff *skb; - int pkt_cnt = 0; + int pkt_cnt = 0, napi_pkts = 0; int i; struct RxD1* rxdp1; struct RxD3* rxdp3; @@ -2977,7 +3021,7 @@ static void rx_intr_handler(struct ring_info *ring_data) DBG_PRINT(ERR_DBG, "%s: The skb is ", ring_data->dev->name); DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); - return; + return 0; } if (ring_data->rxd_mode == RXD_MODE_1) { rxdp1 = (struct RxD1*)rxdp; @@ -3014,9 +3058,10 @@ static void rx_intr_handler(struct ring_info *ring_data) rxdp = ring_data->rx_blocks[get_block].block_virt_addr; } - if(ring_data->nic->config.napi){ - ring_data->nic->pkts_to_process -= 1; - if (!ring_data->nic->pkts_to_process) + if (ring_data->nic->config.napi) { + budget--; + napi_pkts++; + if (!budget) break; } pkt_cnt++; @@ -3034,6 +3079,7 @@ static void rx_intr_handler(struct ring_info *ring_data) } } } + return(napi_pkts); } /** @@ -3730,14 +3776,19 @@ static void restore_xmsi_data(struct s2io_nic *nic) { struct XENA_dev_config __iomem *bar0 = nic->bar0; u64 val64; - int i; + int i, msix_index; + + + if (nic->device_type == XFRAME_I_DEVICE) + return; for (i=0; i < MAX_REQUESTED_MSI_X; i++) { + msix_index = (i) ? ((i-1) * 8 + 1): 0; writeq(nic->msix_info[i].addr, &bar0->xmsi_address); writeq(nic->msix_info[i].data, &bar0->xmsi_data); - val64 = (s2BIT(7) | s2BIT(15) | vBIT(i, 26, 6)); + val64 = (s2BIT(7) | s2BIT(15) | vBIT(msix_index, 26, 6)); writeq(val64, &bar0->xmsi_access); - if (wait_for_msix_trans(nic, i)) { + if (wait_for_msix_trans(nic, msix_index)) { DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); continue; } @@ -3748,13 +3799,17 @@ static void store_xmsi_data(struct s2io_nic *nic) { struct XENA_dev_config __iomem *bar0 = nic->bar0; u64 val64, addr, data; - int i; + int i, msix_index; + + if (nic->device_type == XFRAME_I_DEVICE) + return; /* Store and display */ for (i=0; i < MAX_REQUESTED_MSI_X; i++) { - val64 = (s2BIT(15) | vBIT(i, 26, 6)); + msix_index = (i) ? ((i-1) * 8 + 1): 0; + val64 = (s2BIT(15) | vBIT(msix_index, 26, 6)); writeq(val64, &bar0->xmsi_access); - if (wait_for_msix_trans(nic, i)) { + if (wait_for_msix_trans(nic, msix_index)) { DBG_PRINT(ERR_DBG, "failed in %s\n", __FUNCTION__); continue; } @@ -3770,11 +3825,11 @@ static void store_xmsi_data(struct s2io_nic *nic) static int s2io_enable_msi_x(struct s2io_nic *nic) { struct XENA_dev_config __iomem *bar0 = nic->bar0; - u64 tx_mat, rx_mat; + u64 rx_mat; u16 msi_control; /* Temp variable */ int ret, i, j, msix_indx = 1; - nic->entries = kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct msix_entry), + nic->entries = kmalloc(nic->num_entries * sizeof(struct msix_entry), GFP_KERNEL); if (!nic->entries) { DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", \ @@ -3783,10 +3838,12 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) return -ENOMEM; } nic->mac_control.stats_info->sw_stat.mem_allocated - += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + += (nic->num_entries * sizeof(struct msix_entry)); + + memset(nic->entries, 0, nic->num_entries * sizeof(struct msix_entry)); nic->s2io_entries = - kcalloc(MAX_REQUESTED_MSI_X, sizeof(struct s2io_msix_entry), + kmalloc(nic->num_entries * sizeof(struct s2io_msix_entry), GFP_KERNEL); if (!nic->s2io_entries) { DBG_PRINT(INFO_DBG, "%s: Memory allocation failed\n", @@ -3794,60 +3851,52 @@ static int s2io_enable_msi_x(struct s2io_nic *nic) nic->mac_control.stats_info->sw_stat.mem_alloc_fail_cnt++; kfree(nic->entries); nic->mac_control.stats_info->sw_stat.mem_freed - += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + += (nic->num_entries * sizeof(struct msix_entry)); return -ENOMEM; } nic->mac_control.stats_info->sw_stat.mem_allocated - += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); - - for (i=0; i< MAX_REQUESTED_MSI_X; i++) { - nic->entries[i].entry = i; - nic->s2io_entries[i].entry = i; + += (nic->num_entries * sizeof(struct s2io_msix_entry)); + memset(nic->s2io_entries, 0, + nic->num_entries * sizeof(struct s2io_msix_entry)); + + nic->entries[0].entry = 0; + nic->s2io_entries[0].entry = 0; + nic->s2io_entries[0].in_use = MSIX_FLG; + nic->s2io_entries[0].type = MSIX_ALARM_TYPE; + nic->s2io_entries[0].arg = &nic->mac_control.fifos; + + for (i = 1; i < nic->num_entries; i++) { + nic->entries[i].entry = ((i - 1) * 8) + 1; + nic->s2io_entries[i].entry = ((i - 1) * 8) + 1; nic->s2io_entries[i].arg = NULL; nic->s2io_entries[i].in_use = 0; } - tx_mat = readq(&bar0->tx_mat0_n[0]); - for (i=0; i<nic->config.tx_fifo_num; i++, msix_indx++) { - tx_mat |= TX_MAT_SET(i, msix_indx); - nic->s2io_entries[msix_indx].arg = &nic->mac_control.fifos[i]; - nic->s2io_entries[msix_indx].type = MSIX_FIFO_TYPE; - nic->s2io_entries[msix_indx].in_use = MSIX_FLG; - } - writeq(tx_mat, &bar0->tx_mat0_n[0]); - rx_mat = readq(&bar0->rx_mat); - for (j = 0; j < nic->config.rx_ring_num; j++, msix_indx++) { + for (j = 0; j < nic->config.rx_ring_num; j++) { rx_mat |= RX_MAT_SET(j, msix_indx); - nic->s2io_entries[msix_indx].arg - = &nic->mac_control.rings[j]; - nic->s2io_entries[msix_indx].type = MSIX_RING_TYPE; - nic->s2io_entries[msix_indx].in_use = MSIX_FLG; + nic->s2io_entries[j+1].arg = &nic->mac_control.rings[j]; + nic->s2io_entries[j+1].type = MSIX_RING_TYPE; + nic->s2io_entries[j+1].in_use = MSIX_FLG; + msix_indx += 8; } writeq(rx_mat, &bar0->rx_mat); + readq(&bar0->rx_mat); - nic->avail_msix_vectors = 0; - ret = pci_enable_msix(nic->pdev, nic->entries, MAX_REQUESTED_MSI_X); + ret = pci_enable_msix(nic->pdev, nic->entries, nic->num_entries); /* We fail init if error or we get less vectors than min required */ - if (ret >= (nic->config.tx_fifo_num + nic->config.rx_ring_num + 1)) { - nic->avail_msix_vectors = ret; - ret = pci_enable_msix(nic->pdev, nic->entries, ret); - } if (ret) { DBG_PRINT(ERR_DBG, "%s: Enabling MSIX failed\n", nic->dev->name); kfree(nic->entries); nic->mac_control.stats_info->sw_stat.mem_freed - += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + += (nic->num_entries * sizeof(struct msix_entry)); kfree(nic->s2io_entries); nic->mac_control.stats_info->sw_stat.mem_freed - += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); + += (nic->num_entries * sizeof(struct s2io_msix_entry)); nic->entries = NULL; nic->s2io_entries = NULL; - nic->avail_msix_vectors = 0; return -ENOMEM; } - if (!nic->avail_msix_vectors) - nic->avail_msix_vectors = MAX_REQUESTED_MSI_X; /* * To enable MSI-X, MSI also needs to be enabled, due to a bug @@ -3919,7 +3968,7 @@ static void remove_msix_isr(struct s2io_nic *sp) int i; u16 msi_control; - for (i = 0; i < MAX_REQUESTED_MSI_X; i++) { + for (i = 0; i < sp->num_entries; i++) { if (sp->s2io_entries[i].in_use == MSIX_REGISTERED_SUCCESS) { int vector = sp->entries[i].vector; @@ -3975,29 +4024,6 @@ static int s2io_open(struct net_device *dev) netif_carrier_off(dev); sp->last_link_state = 0; - if (sp->config.intr_type == MSI_X) { - int ret = s2io_enable_msi_x(sp); - - if (!ret) { - ret = s2io_test_msi(sp); - /* rollback MSI-X, will re-enable during add_isr() */ - remove_msix_isr(sp); - } - if (ret) { - - DBG_PRINT(ERR_DBG, - "%s: MSI-X requested but failed to enable\n", - dev->name); - sp->config.intr_type = INTA; - } - } - - /* NAPI doesn't work well with MSI(X) */ - if (sp->config.intr_type != INTA) { - if(sp->config.napi) - sp->config.napi = 0; - } - /* Initialize H/W and enable interrupts */ err = s2io_card_up(sp); if (err) { @@ -4020,12 +4046,12 @@ hw_init_failed: if (sp->entries) { kfree(sp->entries); sp->mac_control.stats_info->sw_stat.mem_freed - += (MAX_REQUESTED_MSI_X * sizeof(struct msix_entry)); + += (sp->num_entries * sizeof(struct msix_entry)); } if (sp->s2io_entries) { kfree(sp->s2io_entries); sp->mac_control.stats_info->sw_stat.mem_freed - += (MAX_REQUESTED_MSI_X * sizeof(struct s2io_msix_entry)); + += (sp->num_entries * sizeof(struct s2io_msix_entry)); } } return err; @@ -4327,40 +4353,64 @@ s2io_alarm_handle(unsigned long data) mod_timer(&sp->alarm_timer, jiffies + HZ / 2); } -static int s2io_chk_rx_buffers(struct ring_info *ring) -{ - if (fill_rx_buffers(ring) == -ENOMEM) { - DBG_PRINT(INFO_DBG, "%s:Out of memory", ring->dev->name); - DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); - } - return 0; -} - static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id) { struct ring_info *ring = (struct ring_info *)dev_id; struct s2io_nic *sp = ring->nic; + struct XENA_dev_config __iomem *bar0 = sp->bar0; + struct net_device *dev = sp->dev; - if (!is_s2io_card_up(sp)) + if (unlikely(!is_s2io_card_up(sp))) return IRQ_HANDLED; - rx_intr_handler(ring); - s2io_chk_rx_buffers(ring); + if (sp->config.napi) { + u8 *addr = NULL, val8 = 0; + + addr = (u8 *)&bar0->xmsi_mask_reg; + addr += (7 - ring->ring_no); + val8 = (ring->ring_no == 0) ? 0x7f : 0xff; + writeb(val8, addr); + val8 = readb(addr); + netif_rx_schedule(dev, &ring->napi); + } else { + rx_intr_handler(ring, 0); + s2io_chk_rx_buffers(ring); + } return IRQ_HANDLED; } static irqreturn_t s2io_msix_fifo_handle(int irq, void *dev_id) { - struct fifo_info *fifo = (struct fifo_info *)dev_id; - struct s2io_nic *sp = fifo->nic; + int i; + struct fifo_info *fifos = (struct fifo_info *)dev_id; + struct s2io_nic *sp = fifos->nic; + struct XENA_dev_config __iomem *bar0 = sp->bar0; + struct config_param *config = &sp->config; + u64 reason; - if (!is_s2io_card_up(sp)) + if (unlikely(!is_s2io_card_up(sp))) + return IRQ_NONE; + + reason = readq(&bar0->general_int_status); + if (unlikely(reason == S2IO_MINUS_ONE)) + /* Nothing much can be done. Get out */ return IRQ_HANDLED; - tx_intr_handler(fifo); + writeq(S2IO_MINUS_ONE, &bar0->general_int_mask); + + if (reason & GEN_INTR_TXTRAFFIC) + writeq(S2IO_MINUS_ONE, &bar0->tx_traffic_int); + + for (i = 0; i < config->tx_fifo_num; i++) + tx_intr_handler(&fifos[i]); + + writeq(sp->general_int_mask, &bar0->general_int_mask); + readl(&bar0->general_int_status); + return IRQ_HANDLED; } + static void s2io_txpic_intr_handle(struct s2io_nic *sp) { struct XENA_dev_config __iomem *bar0 = sp->bar0; @@ -4762,14 +4812,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) if (config->napi) { if (reason & GEN_INTR_RXTRAFFIC) { - if (likely(netif_rx_schedule_prep(dev, - &sp->napi))) { - __netif_rx_schedule(dev, &sp->napi); - writeq(S2IO_MINUS_ONE, - &bar0->rx_traffic_mask); - } else - writeq(S2IO_MINUS_ONE, - &bar0->rx_traffic_int); + netif_rx_schedule(dev, &sp->napi); + writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); + writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); + readl(&bar0->rx_traffic_int); } } else { /* @@ -4781,7 +4827,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id) writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); for (i = 0; i < config->rx_ring_num; i++) - rx_intr_handler(&mac_control->rings[i]); + rx_intr_handler(&mac_control->rings[i], 0); } /* @@ -6984,62 +7030,62 @@ static int s2io_add_isr(struct s2io_nic * sp) /* After proper initialization of H/W, register ISR */ if (sp->config.intr_type == MSI_X) { - int i, msix_tx_cnt=0,msix_rx_cnt=0; - - for (i=1; (sp->s2io_entries[i].in_use == MSIX_FLG); i++) { - if (sp->s2io_entries[i].type == MSIX_FIFO_TYPE) { - sprintf(sp->desc[i], "%s:MSI-X-%d-TX", + int i, msix_rx_cnt = 0; + + for (i = 0; i < sp->num_entries; i++) { + if (sp->s2io_entries[i].in_use == MSIX_FLG) { + if (sp->s2io_entries[i].type == + MSIX_RING_TYPE) { + sprintf(sp->desc[i], "%s:MSI-X-%d-RX", + dev->name, i); + err = request_irq(sp->entries[i].vector, + s2io_msix_ring_handle, 0, + sp->desc[i], + sp->s2io_entries[i].arg); + } else if (sp->s2io_entries[i].type == + MSIX_ALARM_TYPE) { + sprintf(sp->desc[i], "%s:MSI-X-%d-TX", dev->name, i); - err = request_irq(sp->entries[i].vector, - s2io_msix_fifo_handle, 0, sp->desc[i], - sp->s2io_entries[i].arg); - /* If either data or addr is zero print it */ - if(!(sp->msix_info[i].addr && - sp->msix_info[i].data)) { - DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx " - "Data:0x%llx\n",sp->desc[i], - (unsigned long long) - sp->msix_info[i].addr, - (unsigned long long) - sp->msix_info[i].data); - } else { - msix_tx_cnt++; + err = request_irq(sp->entries[i].vector, + s2io_msix_fifo_handle, 0, + sp->desc[i], + sp->s2io_entries[i].arg); + } - } else { - sprintf(sp->desc[i], "%s:MSI-X-%d-RX", - dev->name, i); - err = request_irq(sp->entries[i].vector, - s2io_msix_ring_handle, 0, sp->desc[i], - sp->s2io_entries[i].arg); - /* If either data or addr is zero print it */ - if(!(sp->msix_info[i].addr && + /* if either data or addr is zero print it. */ + if (!(sp->msix_info[i].addr && sp->msix_info[i].data)) { - DBG_PRINT(ERR_DBG, "%s @ Addr:0x%llx " - "Data:0x%llx\n",sp->desc[i], + DBG_PRINT(ERR_DBG, + "%s @Addr:0x%llx Data:0x%llx\n", + sp->desc[i], (unsigned long long) sp->msix_info[i].addr, (unsigned long long) - sp->msix_info[i].data); - } else { + ntohl(sp->msix_info[i].data)); + } else msix_rx_cnt++; + if (err) { + remove_msix_isr(sp); + + DBG_PRINT(ERR_DBG, + "%s:MSI-X-%d registration " + "failed\n", dev->name, i); + + DBG_PRINT(ERR_DBG, + "%s: Defaulting to INTA\n", + dev->name); + sp->config.intr_type = INTA; + break; } + sp->s2io_entries[i].in_use = + MSIX_REGISTERED_SUCCESS; } - if (err) { - remove_msix_isr(sp); - DBG_PRINT(ERR_DBG,"%s:MSI-X-%d registration " - "failed\n", dev->name, i); - DBG_PRINT(ERR_DBG, "%s: defaulting to INTA\n", - dev->name); - sp->config.intr_type = INTA; - break; - } - sp->s2io_entries[i].in_use = MSIX_REGISTERED_SUCCESS; } if (!err) { - printk(KERN_INFO "MSI-X-TX %d entries enabled\n", - msix_tx_cnt); printk(KERN_INFO "MSI-X-RX %d entries enabled\n", - msix_rx_cnt); + --msix_rx_cnt); + DBG_PRINT(INFO_DBG, "MSI-X-TX entries enabled" + " through alarm vector\n"); } } if (sp->config.intr_type == INTA) { @@ -7080,8 +7126,15 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) clear_bit(__S2IO_STATE_CARD_UP, &sp->state); /* Disable napi */ - if (config->napi) - napi_disable(&sp->napi); + if (sp->config.napi) { + int off = 0; + if (config->intr_type == MSI_X) { + for (; off < sp->config.rx_ring_num; off++) + napi_disable(&sp->mac_control.rings[off].napi); + } + else + napi_disable(&sp->napi); + } /* disable Tx and Rx traffic on the NIC */ if (do_io) @@ -7173,8 +7226,15 @@ static int s2io_card_up(struct s2io_nic * sp) } /* Initialise napi */ - if (config->napi) - napi_enable(&sp->napi); + if (config->napi) { + int i; + if (config->intr_type == MSI_X) { + for (i = 0; i < sp->config.rx_ring_num; i++) + napi_enable(&sp->mac_control.rings[i].napi); + } else { + napi_enable(&sp->napi); + } + } /* Maintain the state prior to the open */ if (sp->promisc_flg) @@ -7217,7 +7277,7 @@ static int s2io_card_up(struct s2io_nic * sp) /* Enable select interrupts */ en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS); if (sp->config.intr_type != INTA) - en_dis_able_nic_intrs(sp, ENA_ALL_INTRS, DISABLE_INTRS); + en_dis_able_nic_intrs(sp, TX_TRAFFIC_INTR, ENABLE_INTRS); else { interruptible = TX_TRAFFIC_INTR | RX_TRAFFIC_INTR; interruptible |= TX_PIC_INTR; @@ -7615,9 +7675,6 @@ static int s2io_verify_parm(struct pci_dev *pdev, u8 *dev_intr_type, rx_ring_num = MAX_RX_RINGS; } - if (*dev_intr_type != INTA) - napi = 0; - if ((*dev_intr_type != INTA) && (*dev_intr_type != MSI_X)) { DBG_PRINT(ERR_DBG, "s2io: Wrong intr_type requested. " "Defaulting to INTA\n"); @@ -7918,8 +7975,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) * will use eth_mac_addr() for dev->set_mac_address * mac address will be set every time dev->open() is called */ - netif_napi_add(dev, &sp->napi, s2io_poll, 32); - #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = s2io_netpoll; #endif @@ -7963,6 +8018,32 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) } } + if (sp->config.intr_type == MSI_X) { + sp->num_entries = config->rx_ring_num + 1; + ret = s2io_enable_msi_x(sp); + + if (!ret) { + ret = s2io_test_msi(sp); + /* rollback MSI-X, will re-enable during add_isr() */ + remove_msix_isr(sp); + } + if (ret) { + + DBG_PRINT(ERR_DBG, + "%s: MSI-X requested but failed to enable\n", + dev->name); + sp->config.intr_type = INTA; + } + } + + if (config->intr_type == MSI_X) { + for (i = 0; i < config->rx_ring_num ; i++) + netif_napi_add(dev, &mac_control->rings[i].napi, + s2io_poll_msix, 64); + } else { + netif_napi_add(dev, &sp->napi, s2io_poll_inta, 64); + } + /* Not needed for Herc */ if (sp->device_type & XFRAME_I_DEVICE) { /* @@ -8013,6 +8094,11 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) /* store mac addresses from CAM to s2io_nic structure */ do_s2io_store_unicast_mc(sp); + /* Configure MSIX vector for number of rings configured plus one */ + if ((sp->device_type == XFRAME_II_DEVICE) && + (config->intr_type == MSI_X)) + sp->num_entries = config->rx_ring_num + 1; + /* Store the values of the MSIX table in the s2io_nic structure */ store_xmsi_data(sp); /* reset Nic and bring it to known state */ @@ -8078,8 +8164,14 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) break; } - if (napi) + switch (sp->config.napi) { + case 0: + DBG_PRINT(ERR_DBG, "%s: NAPI disabled\n", dev->name); + break; + case 1: DBG_PRINT(ERR_DBG, "%s: NAPI enabled\n", dev->name); + break; + } DBG_PRINT(ERR_DBG, "%s: Using %d Tx fifo(s)\n", dev->name, sp->config.tx_fifo_num); diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index 0709ebae9139..4706f7f9acb6 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h @@ -706,7 +706,7 @@ struct ring_info { /* per-ring buffer counter */ u32 rx_bufs_left; - #define MAX_LRO_SESSIONS 32 +#define MAX_LRO_SESSIONS 32 struct lro lro0_n[MAX_LRO_SESSIONS]; u8 lro; @@ -725,6 +725,11 @@ struct ring_info { /* copy of sp->pdev pointer */ struct pci_dev *pdev; + /* Per ring napi struct */ + struct napi_struct napi; + + unsigned long interrupt_count; + /* * Place holders for the virtual and physical addresses of * all the Rx Blocks @@ -841,7 +846,7 @@ struct usr_addr { * Structure to keep track of the MSI-X vectors and the corresponding * argument registered against each vector */ -#define MAX_REQUESTED_MSI_X 17 +#define MAX_REQUESTED_MSI_X 9 struct s2io_msix_entry { u16 vector; @@ -849,8 +854,8 @@ struct s2io_msix_entry void *arg; u8 type; -#define MSIX_FIFO_TYPE 1 -#define MSIX_RING_TYPE 2 +#define MSIX_ALARM_TYPE 1 +#define MSIX_RING_TYPE 2 u8 in_use; #define MSIX_REGISTERED_SUCCESS 0xAA @@ -877,7 +882,6 @@ struct s2io_nic { */ int pkts_to_process; struct net_device *dev; - struct napi_struct napi; struct mac_info mac_control; struct config_param config; struct pci_dev *pdev; @@ -948,6 +952,7 @@ struct s2io_nic { */ u8 other_fifo_idx; + struct napi_struct napi; /* after blink, the adapter must be restored with original * values. */ @@ -962,6 +967,7 @@ struct s2io_nic { unsigned long long start_time; struct vlan_group *vlgrp; #define MSIX_FLG 0xA5 + int num_entries; struct msix_entry *entries; int msi_detected; wait_queue_head_t msi_wait; @@ -982,6 +988,7 @@ struct s2io_nic { u16 lro_max_aggr_per_sess; volatile unsigned long state; u64 general_int_mask; + #define VPD_STRING_LEN 80 u8 product_name[VPD_STRING_LEN]; u8 serial_num[VPD_STRING_LEN]; @@ -1103,7 +1110,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev); static int init_shared_mem(struct s2io_nic *sp); static void free_shared_mem(struct s2io_nic *sp); static int init_nic(struct s2io_nic *nic); -static void rx_intr_handler(struct ring_info *ring_data); +static int rx_intr_handler(struct ring_info *ring_data, int budget); static void tx_intr_handler(struct fifo_info *fifo_data); static void s2io_handle_errors(void * dev_id); @@ -1114,7 +1121,8 @@ static void s2io_set_multicast(struct net_device *dev); static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp); static void s2io_link(struct s2io_nic * sp, int link); static void s2io_reset(struct s2io_nic * sp); -static int s2io_poll(struct napi_struct *napi, int budget); +static int s2io_poll_msix(struct napi_struct *napi, int budget); +static int s2io_poll_inta(struct napi_struct *napi, int budget); static void s2io_init_pci(struct s2io_nic * sp); static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr); static void s2io_alarm_handle(unsigned long data); diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 888b7dec9866..33bb18f810fb 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -179,8 +179,7 @@ enum sbmac_state { #define SBMAC_MAX_TXDESCR 256 #define SBMAC_MAX_RXDESCR 256 -#define ETHER_ALIGN 2 -#define ETHER_ADDR_LEN 6 +#define ETHER_ADDR_LEN 6 #define ENET_PACKET_SIZE 1518 /*#define ENET_PACKET_SIZE 9216 */ @@ -262,8 +261,6 @@ struct sbmac_softc { spinlock_t sbm_lock; /* spin lock */ int sbm_devflags; /* current device flags */ - int sbm_buffersize; - /* * Controller-specific things */ @@ -305,10 +302,11 @@ struct sbmac_softc { static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, int txrx, int maxdescr); static void sbdma_channel_start(struct sbmacdma *d, int rxtx); -static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *m); +static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, + struct sk_buff *m); static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m); static void sbdma_emptyring(struct sbmacdma *d); -static void sbdma_fillring(struct sbmacdma *d); +static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d); static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, int work_to_do, int poll); static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, @@ -777,16 +775,13 @@ static void sbdma_channel_stop(struct sbmacdma *d) d->sbdma_remptr = NULL; } -static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset) +static inline void sbdma_align_skb(struct sk_buff *skb, + unsigned int power2, unsigned int offset) { - unsigned long addr; - unsigned long newaddr; - - addr = (unsigned long) skb->data; - - newaddr = (addr + power2 - 1) & ~(power2 - 1); + unsigned char *addr = skb->data; + unsigned char *newaddr = PTR_ALIGN(addr, power2); - skb_reserve(skb,newaddr-addr+offset); + skb_reserve(skb, newaddr - addr + offset); } @@ -797,7 +792,8 @@ static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset) * this queues a buffer for inbound packets. * * Input parameters: - * d - DMA channel descriptor + * sc - softc structure + * d - DMA channel descriptor * sb - sk_buff to add, or NULL if we should allocate one * * Return value: @@ -806,8 +802,10 @@ static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset) ********************************************************************* */ -static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb) +static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, + struct sk_buff *sb) { + struct net_device *dev = sc->sbm_dev; struct sbdmadscr *dsc; struct sbdmadscr *nextdsc; struct sk_buff *sb_new = NULL; @@ -848,14 +846,16 @@ static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb) */ if (sb == NULL) { - sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN); + sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE + + SMP_CACHE_BYTES * 2 + + NET_IP_ALIGN); if (sb_new == NULL) { pr_info("%s: sk_buff allocation failed\n", d->sbdma_eth->sbm_dev->name); return -ENOBUFS; } - sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN); + sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN); } else { sb_new = sb; @@ -874,10 +874,10 @@ static int sbdma_add_rcvbuffer(struct sbmacdma *d, struct sk_buff *sb) * Do not interrupt per DMA transfer. */ dsc->dscr_a = virt_to_phys(sb_new->data) | - V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | 0; + V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0; #else dsc->dscr_a = virt_to_phys(sb_new->data) | - V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | + V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | M_DMA_DSCRA_INTERRUPT; #endif @@ -1032,18 +1032,19 @@ static void sbdma_emptyring(struct sbmacdma *d) * with sk_buffs * * Input parameters: - * d - DMA channel + * sc - softc structure + * d - DMA channel * * Return value: * nothing ********************************************************************* */ -static void sbdma_fillring(struct sbmacdma *d) +static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d) { int idx; - for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) { - if (sbdma_add_rcvbuffer(d,NULL) != 0) + for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) { + if (sbdma_add_rcvbuffer(sc, d, NULL) != 0) break; } } @@ -1159,10 +1160,11 @@ again: * packet and put it right back on the receive ring. */ - if (unlikely (sbdma_add_rcvbuffer(d,NULL) == - -ENOBUFS)) { + if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) == + -ENOBUFS)) { dev->stats.rx_dropped++; - sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */ + /* Re-add old buffer */ + sbdma_add_rcvbuffer(sc, d, sb); /* No point in continuing at the moment */ printk(KERN_ERR "dropped packet (1)\n"); d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); @@ -1212,7 +1214,7 @@ again: * put it back on the receive ring. */ dev->stats.rx_errors++; - sbdma_add_rcvbuffer(d,sb); + sbdma_add_rcvbuffer(sc, d, sb); } @@ -1570,7 +1572,7 @@ static void sbmac_channel_start(struct sbmac_softc *s) * Fill the receive ring */ - sbdma_fillring(&(s->sbm_rxdma)); + sbdma_fillring(s, &(s->sbm_rxdma)); /* * Turn on the rest of the bits in the enable register @@ -2312,13 +2314,6 @@ static int sbmac_init(struct platform_device *pldev, long long base) dev->dev_addr[i] = eaddr[i]; } - - /* - * Init packet size - */ - - sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN; - /* * Initialize context (get pointers to registers and stuff), then * allocate the memory for the descriptor tables. diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c index f64a860029b7..b4b63805ee8f 100644 --- a/drivers/net/sc92031.c +++ b/drivers/net/sc92031.c @@ -953,9 +953,6 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) unsigned entry; u32 tx_status; - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - if (unlikely(skb->len > TX_BUF_SIZE)) { dev->stats.tx_dropped++; goto out; @@ -975,6 +972,11 @@ static int sc92031_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_and_csum_dev(skb, priv->tx_bufs + entry * TX_BUF_SIZE); len = skb->len; + if (unlikely(len < ETH_ZLEN)) { + memset(priv->tx_bufs + entry * TX_BUF_SIZE + len, + 0, ETH_ZLEN - len); + len = ETH_ZLEN; + } wmb(); diff --git a/drivers/net/sfc/bitfield.h b/drivers/net/sfc/bitfield.h index 2806201644cc..2c79d27404e0 100644 --- a/drivers/net/sfc/bitfield.h +++ b/drivers/net/sfc/bitfield.h @@ -483,7 +483,7 @@ typedef union efx_oword { #endif #define EFX_SET_OWORD_FIELD_VER(efx, oword, field, value) do { \ - if (FALCON_REV(efx) >= FALCON_REV_B0) { \ + if (falcon_rev(efx) >= FALCON_REV_B0) { \ EFX_SET_OWORD_FIELD((oword), field##_B0, (value)); \ } else { \ EFX_SET_OWORD_FIELD((oword), field##_A1, (value)); \ @@ -491,7 +491,7 @@ typedef union efx_oword { } while (0) #define EFX_QWORD_FIELD_VER(efx, qword, field) \ - (FALCON_REV(efx) >= FALCON_REV_B0 ? \ + (falcon_rev(efx) >= FALCON_REV_B0 ? \ EFX_QWORD_FIELD((qword), field##_B0) : \ EFX_QWORD_FIELD((qword), field##_A1)) @@ -501,8 +501,5 @@ typedef union efx_oword { #define DMA_ADDR_T_WIDTH (8 * sizeof(dma_addr_t)) #define EFX_DMA_TYPE_WIDTH(width) \ (((width) < DMA_ADDR_T_WIDTH) ? (width) : DMA_ADDR_T_WIDTH) -#define EFX_DMA_MAX_MASK ((DMA_ADDR_T_WIDTH == 64) ? \ - ~((u64) 0) : ~((u32) 0)) -#define EFX_DMA_MASK(mask) ((mask) & EFX_DMA_MAX_MASK) #endif /* EFX_BITFIELD_H */ diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c index eecaa6d58584..7fc0328dc055 100644 --- a/drivers/net/sfc/boards.c +++ b/drivers/net/sfc/boards.c @@ -27,10 +27,8 @@ static void blink_led_timer(unsigned long context) struct efx_blinker *bl = &efx->board_info.blinker; efx->board_info.set_fault_led(efx, bl->state); bl->state = !bl->state; - if (bl->resubmit) { - bl->timer.expires = jiffies + BLINK_INTERVAL; - add_timer(&bl->timer); - } + if (bl->resubmit) + mod_timer(&bl->timer, jiffies + BLINK_INTERVAL); } static void board_blink(struct efx_nic *efx, int blink) @@ -44,8 +42,7 @@ static void board_blink(struct efx_nic *efx, int blink) blinker->state = 0; setup_timer(&blinker->timer, blink_led_timer, (unsigned long)efx); - blinker->timer.expires = jiffies + BLINK_INTERVAL; - add_timer(&blinker->timer); + mod_timer(&blinker->timer, jiffies + BLINK_INTERVAL); } else { blinker->resubmit = 0; if (blinker->timer.function) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 418f2e53a95b..449760642e31 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -199,11 +199,12 @@ static inline int efx_process_channel(struct efx_channel *channel, int rx_quota) */ static inline void efx_channel_processed(struct efx_channel *channel) { - /* Write to EVQ_RPTR_REG. If a new event arrived in a race - * with finishing processing, a new interrupt will be raised. - */ + /* The interrupt handler for this channel may set work_pending + * as soon as we acknowledge the events we've seen. Make sure + * it's cleared before then. */ channel->work_pending = 0; - smp_wmb(); /* Ensure channel updated before any new interrupt. */ + smp_wmb(); + falcon_eventq_read_ack(channel); } @@ -265,7 +266,7 @@ void efx_process_channel_now(struct efx_channel *channel) napi_disable(&channel->napi_str); /* Poll the channel */ - (void) efx_process_channel(channel, efx->type->evq_size); + efx_process_channel(channel, efx->type->evq_size); /* Ack the eventq. This may cause an interrupt to be generated * when they are reenabled */ @@ -317,26 +318,6 @@ static void efx_remove_eventq(struct efx_channel *channel) * *************************************************************************/ -/* Setup per-NIC RX buffer parameters. - * Calculate the rx buffer allocation parameters required to support - * the current MTU, including padding for header alignment and overruns. - */ -static void efx_calc_rx_buffer_params(struct efx_nic *efx) -{ - unsigned int order, len; - - len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + - EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + - efx->type->rx_buffer_padding); - - /* Calculate page-order */ - for (order = 0; ((1u << order) * PAGE_SIZE) < len; ++order) - ; - - efx->rx_buffer_len = len; - efx->rx_buffer_order = order; -} - static int efx_probe_channel(struct efx_channel *channel) { struct efx_tx_queue *tx_queue; @@ -387,7 +368,14 @@ static int efx_init_channels(struct efx_nic *efx) struct efx_channel *channel; int rc = 0; - efx_calc_rx_buffer_params(efx); + /* Calculate the rx buffer allocation parameters required to + * support the current MTU, including padding for header + * alignment and overruns. + */ + efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + + EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + + efx->type->rx_buffer_padding); + efx->rx_buffer_order = get_order(efx->rx_buffer_len); /* Initialise the channels */ efx_for_each_channel(channel, efx) { @@ -440,9 +428,12 @@ static void efx_start_channel(struct efx_channel *channel) netif_napi_add(channel->napi_dev, &channel->napi_str, efx_poll, napi_weight); + /* The interrupt handler for this channel may set work_pending + * as soon as we enable it. Make sure it's cleared before + * then. Similarly, make sure it sees the enabled flag set. */ channel->work_pending = 0; channel->enabled = 1; - smp_wmb(); /* ensure channel updated before first interrupt */ + smp_wmb(); napi_enable(&channel->napi_str); @@ -704,7 +695,7 @@ static void efx_stop_port(struct efx_nic *efx) mutex_unlock(&efx->mac_lock); /* Serialise against efx_set_multicast_list() */ - if (NET_DEV_REGISTERED(efx)) { + if (efx_dev_registered(efx)) { netif_tx_lock_bh(efx->net_dev); netif_tx_unlock_bh(efx->net_dev); } @@ -791,22 +782,23 @@ static int efx_init_io(struct efx_nic *efx) efx->membase = ioremap_nocache(efx->membase_phys, efx->type->mem_map_size); if (!efx->membase) { - EFX_ERR(efx, "could not map memory BAR %d at %lx+%x\n", - efx->type->mem_bar, efx->membase_phys, + EFX_ERR(efx, "could not map memory BAR %d at %llx+%x\n", + efx->type->mem_bar, + (unsigned long long)efx->membase_phys, efx->type->mem_map_size); rc = -ENOMEM; goto fail4; } - EFX_LOG(efx, "memory BAR %u at %lx+%x (virtual %p)\n", - efx->type->mem_bar, efx->membase_phys, efx->type->mem_map_size, - efx->membase); + EFX_LOG(efx, "memory BAR %u at %llx+%x (virtual %p)\n", + efx->type->mem_bar, (unsigned long long)efx->membase_phys, + efx->type->mem_map_size, efx->membase); return 0; fail4: release_mem_region(efx->membase_phys, efx->type->mem_map_size); fail3: - efx->membase_phys = 0UL; + efx->membase_phys = 0; fail2: pci_disable_device(efx->pci_dev); fail1: @@ -824,7 +816,7 @@ static void efx_fini_io(struct efx_nic *efx) if (efx->membase_phys) { pci_release_region(efx->pci_dev, efx->type->mem_bar); - efx->membase_phys = 0UL; + efx->membase_phys = 0; } pci_disable_device(efx->pci_dev); @@ -1043,7 +1035,7 @@ static void efx_start_all(struct efx_nic *efx) return; if ((efx->state != STATE_RUNNING) && (efx->state != STATE_INIT)) return; - if (NET_DEV_REGISTERED(efx) && !netif_running(efx->net_dev)) + if (efx_dev_registered(efx) && !netif_running(efx->net_dev)) return; /* Mark the port as enabled so port reconfigurations can start, then @@ -1073,9 +1065,8 @@ static void efx_flush_all(struct efx_nic *efx) cancel_delayed_work_sync(&efx->monitor_work); /* Ensure that all RX slow refills are complete. */ - efx_for_each_rx_queue(rx_queue, efx) { + efx_for_each_rx_queue(rx_queue, efx) cancel_delayed_work_sync(&rx_queue->work); - } /* Stop scheduled port reconfigurations */ cancel_work_sync(&efx->reconfigure_work); @@ -1101,9 +1092,10 @@ static void efx_stop_all(struct efx_nic *efx) falcon_disable_interrupts(efx); if (efx->legacy_irq) synchronize_irq(efx->legacy_irq); - efx_for_each_channel_with_interrupt(channel, efx) + efx_for_each_channel_with_interrupt(channel, efx) { if (channel->irq) synchronize_irq(channel->irq); + } /* Stop all NAPI processing and synchronous rx refills */ efx_for_each_channel(channel, efx) @@ -1125,7 +1117,7 @@ static void efx_stop_all(struct efx_nic *efx) /* Stop the kernel transmit interface late, so the watchdog * timer isn't ticking over the flush */ efx_stop_queue(efx); - if (NET_DEV_REGISTERED(efx)) { + if (efx_dev_registered(efx)) { netif_tx_lock_bh(efx->net_dev); netif_tx_unlock_bh(efx->net_dev); } @@ -1344,13 +1336,17 @@ static int efx_net_stop(struct net_device *net_dev) return 0; } -/* Context: process, dev_base_lock held, non-blocking. */ +/* Context: process, dev_base_lock or RTNL held, non-blocking. */ static struct net_device_stats *efx_net_stats(struct net_device *net_dev) { struct efx_nic *efx = net_dev->priv; struct efx_mac_stats *mac_stats = &efx->mac_stats; struct net_device_stats *stats = &net_dev->stats; + /* Update stats if possible, but do not wait if another thread + * is updating them (or resetting the NIC); slightly stale + * stats are acceptable. + */ if (!spin_trylock(&efx->stats_lock)) return stats; if (efx->state == STATE_RUNNING) { @@ -1494,7 +1490,7 @@ static void efx_set_multicast_list(struct net_device *net_dev) static int efx_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) { - struct net_device *net_dev = (struct net_device *)ptr; + struct net_device *net_dev = ptr; if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) { struct efx_nic *efx = net_dev->priv; @@ -1563,7 +1559,7 @@ static void efx_unregister_netdev(struct efx_nic *efx) efx_for_each_tx_queue(tx_queue, efx) efx_release_tx_buffers(tx_queue); - if (NET_DEV_REGISTERED(efx)) { + if (efx_dev_registered(efx)) { strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name)); unregister_netdev(efx->net_dev); } @@ -1688,7 +1684,7 @@ static int efx_reset(struct efx_nic *efx) if (method == RESET_TYPE_DISABLE) { /* Reinitialise the device anyway so the driver unload sequence * can talk to the external SRAM */ - (void) falcon_init_nic(efx); + falcon_init_nic(efx); rc = -EIO; goto fail4; } diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index b57cc68058c0..d3f749c72d41 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -116,17 +116,8 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); ************************************************************************** */ -/* DMA address mask (up to 46-bit, avoiding compiler warnings) - * - * Note that it is possible to have a platform with 64-bit longs and - * 32-bit DMA addresses, or vice versa. EFX_DMA_MASK takes care of the - * platform DMA mask. - */ -#if BITS_PER_LONG == 64 -#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffUL) -#else -#define FALCON_DMA_MASK EFX_DMA_MASK(0x00003fffffffffffULL) -#endif +/* DMA address mask */ +#define FALCON_DMA_MASK DMA_BIT_MASK(46) /* TX DMA length mask (13-bit) */ #define FALCON_TX_DMA_MASK (4096 - 1) @@ -145,7 +136,7 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); #define PCI_EXP_LNKSTA_LNK_WID_LBN 4 #define FALCON_IS_DUAL_FUNC(efx) \ - (FALCON_REV(efx) < FALCON_REV_B0) + (falcon_rev(efx) < FALCON_REV_B0) /************************************************************************** * @@ -465,7 +456,7 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue) TX_DESCQ_TYPE, 0, TX_NON_IP_DROP_DIS_B0, 1); - if (FALCON_REV(efx) >= FALCON_REV_B0) { + if (falcon_rev(efx) >= FALCON_REV_B0) { int csum = !(efx->net_dev->features & NETIF_F_IP_CSUM); EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_IP_CHKSM_DIS_B0, csum); EFX_SET_OWORD_FIELD(tx_desc_ptr, TX_TCP_CHKSM_DIS_B0, csum); @@ -474,7 +465,7 @@ int falcon_init_tx(struct efx_tx_queue *tx_queue) falcon_write_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base, tx_queue->queue); - if (FALCON_REV(efx) < FALCON_REV_B0) { + if (falcon_rev(efx) < FALCON_REV_B0) { efx_oword_t reg; BUG_ON(tx_queue->queue >= 128); /* HW limit */ @@ -635,7 +626,7 @@ int falcon_init_rx(struct efx_rx_queue *rx_queue) efx_oword_t rx_desc_ptr; struct efx_nic *efx = rx_queue->efx; int rc; - int is_b0 = FALCON_REV(efx) >= FALCON_REV_B0; + int is_b0 = falcon_rev(efx) >= FALCON_REV_B0; int iscsi_digest_en = is_b0; EFX_LOG(efx, "RX queue %d ring in special buffers %d-%d\n", @@ -822,10 +813,10 @@ static inline void falcon_handle_tx_event(struct efx_channel *channel, tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); tx_queue = &efx->tx_queue[tx_ev_q_label]; - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_lock(efx->net_dev); falcon_notify_tx_desc(tx_queue); - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_unlock(efx->net_dev); } else if (EFX_QWORD_FIELD(*event, TX_EV_PKT_ERR) && EFX_WORKAROUND_10727(efx)) { @@ -884,7 +875,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue, RX_EV_TCP_UDP_CHKSUM_ERR); rx_ev_eth_crc_err = EFX_QWORD_FIELD(*event, RX_EV_ETH_CRC_ERR); rx_ev_frm_trunc = EFX_QWORD_FIELD(*event, RX_EV_FRM_TRUNC); - rx_ev_drib_nib = ((FALCON_REV(efx) >= FALCON_REV_B0) ? + rx_ev_drib_nib = ((falcon_rev(efx) >= FALCON_REV_B0) ? 0 : EFX_QWORD_FIELD(*event, RX_EV_DRIB_NIB)); rx_ev_pause_frm = EFX_QWORD_FIELD(*event, RX_EV_PAUSE_FRM_ERR); @@ -1065,7 +1056,7 @@ static void falcon_handle_global_event(struct efx_channel *channel, EFX_QWORD_FIELD(*event, XG_PHY_INTR)) is_phy_event = 1; - if ((FALCON_REV(efx) >= FALCON_REV_B0) && + if ((falcon_rev(efx) >= FALCON_REV_B0) && EFX_OWORD_FIELD(*event, XG_MNT_INTR_B0)) is_phy_event = 1; @@ -1405,7 +1396,7 @@ static inline void falcon_irq_ack_a1(struct efx_nic *efx) static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx) { struct falcon_nic_data *nic_data = efx->nic_data; - efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr; + efx_oword_t *int_ker = efx->irq_status.addr; efx_oword_t fatal_intr; int error, mem_perr; static int n_int_errors; @@ -1451,8 +1442,8 @@ out: */ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) { - struct efx_nic *efx = (struct efx_nic *)dev_id; - efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr; + struct efx_nic *efx = dev_id; + efx_oword_t *int_ker = efx->irq_status.addr; struct efx_channel *channel; efx_dword_t reg; u32 queues; @@ -1489,8 +1480,8 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) { - struct efx_nic *efx = (struct efx_nic *)dev_id; - efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr; + struct efx_nic *efx = dev_id; + efx_oword_t *int_ker = efx->irq_status.addr; struct efx_channel *channel; int syserr; int queues; @@ -1542,9 +1533,9 @@ static irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id) */ static irqreturn_t falcon_msi_interrupt(int irq, void *dev_id) { - struct efx_channel *channel = (struct efx_channel *)dev_id; + struct efx_channel *channel = dev_id; struct efx_nic *efx = channel->efx; - efx_oword_t *int_ker = (efx_oword_t *) efx->irq_status.addr; + efx_oword_t *int_ker = efx->irq_status.addr; int syserr; efx->last_irq_cpu = raw_smp_processor_id(); @@ -1572,7 +1563,7 @@ static void falcon_setup_rss_indir_table(struct efx_nic *efx) unsigned long offset; efx_dword_t dword; - if (FALCON_REV(efx) < FALCON_REV_B0) + if (falcon_rev(efx) < FALCON_REV_B0) return; for (offset = RX_RSS_INDIR_TBL_B0; @@ -1595,7 +1586,7 @@ int falcon_init_interrupt(struct efx_nic *efx) if (!EFX_INT_MODE_USE_MSI(efx)) { irq_handler_t handler; - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) handler = falcon_legacy_interrupt_b0; else handler = falcon_legacy_interrupt_a1; @@ -1636,12 +1627,13 @@ void falcon_fini_interrupt(struct efx_nic *efx) efx_oword_t reg; /* Disable MSI/MSI-X interrupts */ - efx_for_each_channel_with_interrupt(channel, efx) + efx_for_each_channel_with_interrupt(channel, efx) { if (channel->irq) free_irq(channel->irq, channel); + } /* ACK legacy interrupt */ - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) falcon_read(efx, ®, INT_ISR0_B0); else falcon_irq_ack_a1(efx); @@ -1732,7 +1724,7 @@ void falcon_drain_tx_fifo(struct efx_nic *efx) efx_oword_t temp; int count; - if ((FALCON_REV(efx) < FALCON_REV_B0) || + if ((falcon_rev(efx) < FALCON_REV_B0) || (efx->loopback_mode != LOOPBACK_NONE)) return; @@ -1785,7 +1777,7 @@ void falcon_deconfigure_mac_wrapper(struct efx_nic *efx) { efx_oword_t temp; - if (FALCON_REV(efx) < FALCON_REV_B0) + if (falcon_rev(efx) < FALCON_REV_B0) return; /* Isolate the MAC -> RX */ @@ -1823,7 +1815,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) MAC_SPEED, link_speed); /* On B0, MAC backpressure can be disabled and packets get * discarded. */ - if (FALCON_REV(efx) >= FALCON_REV_B0) { + if (falcon_rev(efx) >= FALCON_REV_B0) { EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, !efx->link_up); } @@ -1841,7 +1833,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx) EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc); /* Unisolate the MAC -> RX */ - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 1); falcon_write(efx, ®, RX_CFG_REG_KER); } @@ -1856,7 +1848,7 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset) return 0; /* Statistics fetch will fail if the MAC is in TX drain */ - if (FALCON_REV(efx) >= FALCON_REV_B0) { + if (falcon_rev(efx) >= FALCON_REV_B0) { efx_oword_t temp; falcon_read(efx, &temp, MAC0_CTRL_REG_KER); if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0)) @@ -1940,7 +1932,7 @@ static int falcon_gmii_wait(struct efx_nic *efx) static void falcon_mdio_write(struct net_device *net_dev, int phy_id, int addr, int value) { - struct efx_nic *efx = (struct efx_nic *)net_dev->priv; + struct efx_nic *efx = net_dev->priv; unsigned int phy_id2 = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; @@ -2008,7 +2000,7 @@ static void falcon_mdio_write(struct net_device *net_dev, int phy_id, * could be read, -1 will be returned. */ static int falcon_mdio_read(struct net_device *net_dev, int phy_id, int addr) { - struct efx_nic *efx = (struct efx_nic *)net_dev->priv; + struct efx_nic *efx = net_dev->priv; unsigned int phy_addr = phy_id & FALCON_PHY_ID_ID_MASK; efx_oword_t reg; int value = -1; @@ -2113,7 +2105,7 @@ int falcon_probe_port(struct efx_nic *efx) falcon_init_mdio(&efx->mii); /* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */ - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) efx->flow_control = EFX_FC_RX | EFX_FC_TX; else efx->flow_control = EFX_FC_RX; @@ -2373,7 +2365,7 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) return -ENODEV; } - switch (FALCON_REV(efx)) { + switch (falcon_rev(efx)) { case FALCON_REV_A0: case 0xff: EFX_ERR(efx, "Falcon rev A0 not supported\n"); @@ -2399,7 +2391,7 @@ static int falcon_probe_nic_variant(struct efx_nic *efx) break; default: - EFX_ERR(efx, "Unknown Falcon rev %d\n", FALCON_REV(efx)); + EFX_ERR(efx, "Unknown Falcon rev %d\n", falcon_rev(efx)); return -ENODEV; } @@ -2419,7 +2411,7 @@ int falcon_probe_nic(struct efx_nic *efx) /* Allocate storage for hardware specific data */ nic_data = kzalloc(sizeof(*nic_data), GFP_KERNEL); - efx->nic_data = (void *) nic_data; + efx->nic_data = nic_data; /* Determine number of ports etc. */ rc = falcon_probe_nic_variant(efx); @@ -2489,13 +2481,10 @@ int falcon_probe_nic(struct efx_nic *efx) */ int falcon_init_nic(struct efx_nic *efx) { - struct falcon_nic_data *data; efx_oword_t temp; unsigned thresh; int rc; - data = (struct falcon_nic_data *)efx->nic_data; - /* Set up the address region register. This is only needed * for the B0 FPGA, but since we are just pushing in the * reset defaults this may as well be unconditional. */ @@ -2562,7 +2551,7 @@ int falcon_init_nic(struct efx_nic *efx) /* Set number of RSS queues for receive path. */ falcon_read(efx, &temp, RX_FILTER_CTL_REG); - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) EFX_SET_OWORD_FIELD(temp, NUM_KER, 0); else EFX_SET_OWORD_FIELD(temp, NUM_KER, efx->rss_queues - 1); @@ -2600,7 +2589,7 @@ int falcon_init_nic(struct efx_nic *efx) /* Prefetch threshold 2 => fetch when descriptor cache half empty */ EFX_SET_OWORD_FIELD(temp, TX_PREF_THRESHOLD, 2); /* Squash TX of packets of 16 bytes or less */ - if (FALCON_REV(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx)) + if (falcon_rev(efx) >= FALCON_REV_B0 && EFX_WORKAROUND_9141(efx)) EFX_SET_OWORD_FIELD(temp, TX_FLUSH_MIN_LEN_EN_B0, 1); falcon_write(efx, &temp, TX_CFG2_REG_KER); @@ -2617,7 +2606,7 @@ int falcon_init_nic(struct efx_nic *efx) if (EFX_WORKAROUND_7575(efx)) EFX_SET_OWORD_FIELD_VER(efx, temp, RX_USR_BUF_SIZE, (3 * 4096) / 32); - if (FALCON_REV(efx) >= FALCON_REV_B0) + if (falcon_rev(efx) >= FALCON_REV_B0) EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 1); /* RX FIFO flow control thresholds */ @@ -2633,7 +2622,7 @@ int falcon_init_nic(struct efx_nic *efx) falcon_write(efx, &temp, RX_CFG_REG_KER); /* Set destination of both TX and RX Flush events */ - if (FALCON_REV(efx) >= FALCON_REV_B0) { + if (falcon_rev(efx) >= FALCON_REV_B0) { EFX_POPULATE_OWORD_1(temp, FLS_EVQ_ID, 0); falcon_write(efx, &temp, DP_CTRL_REG); } @@ -2647,7 +2636,7 @@ void falcon_remove_nic(struct efx_nic *efx) falcon_free_buffer(efx, &efx->irq_status); - (void) falcon_reset_hw(efx, RESET_TYPE_ALL); + falcon_reset_hw(efx, RESET_TYPE_ALL); /* Release the second function after the reset */ if (nic_data->pci_dev2) { diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 6117403b0c03..492f9bc28840 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h @@ -23,7 +23,10 @@ enum falcon_revision { FALCON_REV_B0 = 2, }; -#define FALCON_REV(efx) ((efx)->pci_dev->revision) +static inline int falcon_rev(struct efx_nic *efx) +{ + return efx->pci_dev->revision; +} extern struct efx_nic_type falcon_a_nic_type; extern struct efx_nic_type falcon_b_nic_type; diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index 06e2d68fc3d1..6d003114eeab 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h @@ -1125,7 +1125,7 @@ struct falcon_nvconfig_board_v2 { u8 port1_phy_type; __le16 asic_sub_revision; __le16 board_revision; -} __attribute__ ((packed)); +} __packed; #define NVCONFIG_BASE 0x300 #define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C @@ -1144,6 +1144,6 @@ struct falcon_nvconfig { __le16 board_struct_ver; __le16 board_checksum; struct falcon_nvconfig_board_v2 board_v2; -} __attribute__ ((packed)); +} __packed; #endif /* EFX_FALCON_HWDEFS_H */ diff --git a/drivers/net/sfc/falcon_io.h b/drivers/net/sfc/falcon_io.h index ea08184ddfa9..6670cdfc41ab 100644 --- a/drivers/net/sfc/falcon_io.h +++ b/drivers/net/sfc/falcon_io.h @@ -56,14 +56,27 @@ #define FALCON_USE_QWORD_IO 1 #endif -#define _falcon_writeq(efx, value, reg) \ - __raw_writeq((__force u64) (value), (efx)->membase + (reg)) -#define _falcon_writel(efx, value, reg) \ - __raw_writel((__force u32) (value), (efx)->membase + (reg)) -#define _falcon_readq(efx, reg) \ - ((__force __le64) __raw_readq((efx)->membase + (reg))) -#define _falcon_readl(efx, reg) \ - ((__force __le32) __raw_readl((efx)->membase + (reg))) +#ifdef FALCON_USE_QWORD_IO +static inline void _falcon_writeq(struct efx_nic *efx, __le64 value, + unsigned int reg) +{ + __raw_writeq((__force u64)value, efx->membase + reg); +} +static inline __le64 _falcon_readq(struct efx_nic *efx, unsigned int reg) +{ + return (__force __le64)__raw_readq(efx->membase + reg); +} +#endif + +static inline void _falcon_writel(struct efx_nic *efx, __le32 value, + unsigned int reg) +{ + __raw_writel((__force u32)value, efx->membase + reg); +} +static inline __le32 _falcon_readl(struct efx_nic *efx, unsigned int reg) +{ + return (__force __le32)__raw_readl(efx->membase + reg); +} /* Writes to a normal 16-byte Falcon register, locking as appropriate. */ static inline void falcon_write(struct efx_nic *efx, efx_oword_t *value, diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index a74b7931a3c4..dbdcee4b0f8d 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -221,7 +221,7 @@ static int falcon_xgmii_status(struct efx_nic *efx) { efx_dword_t reg; - if (FALCON_REV(efx) < FALCON_REV_B0) + if (falcon_rev(efx) < FALCON_REV_B0) return 1; /* The ISR latches, so clear it and re-read */ @@ -241,7 +241,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, int enable) { efx_dword_t reg; - if ((FALCON_REV(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) + if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) return; /* Flush the ISR */ @@ -454,7 +454,7 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx) EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n", __func__, tries); - (void) falcon_reset_xaui(efx); + falcon_reset_xaui(efx); udelay(200); tries--; } @@ -572,7 +572,7 @@ int falcon_check_xmac(struct efx_nic *efx) xaui_link_ok = falcon_xaui_link_ok(efx); if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok) - (void) falcon_reset_xaui(efx); + falcon_reset_xaui(efx); /* Call the PHY check_hw routine */ rc = efx->phy_op->check_hw(efx); @@ -639,7 +639,7 @@ int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control) reset = ((flow_control & EFX_FC_TX) && !(efx->flow_control & EFX_FC_TX)); if (EFX_WORKAROUND_11482(efx) && reset) { - if (FALCON_REV(efx) >= FALCON_REV_B0) { + if (falcon_rev(efx) >= FALCON_REV_B0) { /* Recover by resetting the EM block */ if (efx->link_up) falcon_drain_tx_fifo(efx); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 59f261b4171f..5e20e7551dae 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -42,7 +42,7 @@ #ifndef EFX_DRIVER_NAME #define EFX_DRIVER_NAME "sfc" #endif -#define EFX_DRIVER_VERSION "2.2.0136" +#define EFX_DRIVER_VERSION "2.2" #ifdef EFX_ENABLE_DEBUG #define EFX_BUG_ON_PARANOID(x) BUG_ON(x) @@ -52,28 +52,19 @@ #define EFX_WARN_ON_PARANOID(x) do {} while (0) #endif -#define NET_DEV_REGISTERED(efx) \ - ((efx)->net_dev->reg_state == NETREG_REGISTERED) - -/* Include net device name in log messages if it has been registered. - * Use efx->name not efx->net_dev->name so that races with (un)registration - * are harmless. - */ -#define NET_DEV_NAME(efx) (NET_DEV_REGISTERED(efx) ? (efx)->name : "") - /* Un-rate-limited logging */ #define EFX_ERR(efx, fmt, args...) \ -dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, NET_DEV_NAME(efx), ##args) +dev_err(&((efx)->pci_dev->dev), "ERR: %s " fmt, efx_dev_name(efx), ##args) #define EFX_INFO(efx, fmt, args...) \ -dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, NET_DEV_NAME(efx), ##args) +dev_info(&((efx)->pci_dev->dev), "INFO: %s " fmt, efx_dev_name(efx), ##args) #ifdef EFX_ENABLE_DEBUG #define EFX_LOG(efx, fmt, args...) \ -dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args) +dev_info(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args) #else #define EFX_LOG(efx, fmt, args...) \ -dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, NET_DEV_NAME(efx), ##args) +dev_dbg(&((efx)->pci_dev->dev), "DBG: %s " fmt, efx_dev_name(efx), ##args) #endif #define EFX_TRACE(efx, fmt, args...) do {} while (0) @@ -90,11 +81,6 @@ do {if (net_ratelimit()) EFX_INFO(efx, fmt, ##args); } while (0) #define EFX_LOG_RL(efx, fmt, args...) \ do {if (net_ratelimit()) EFX_LOG(efx, fmt, ##args); } while (0) -/* Kernel headers may redefine inline anyway */ -#ifndef inline -#define inline inline __attribute__ ((always_inline)) -#endif - /************************************************************************** * * Efx data structures @@ -695,7 +681,7 @@ struct efx_nic { struct workqueue_struct *workqueue; struct work_struct reset_work; struct delayed_work monitor_work; - unsigned long membase_phys; + resource_size_t membase_phys; void __iomem *membase; spinlock_t biu_lock; enum efx_int_mode interrupt_mode; @@ -719,7 +705,7 @@ struct efx_nic { unsigned n_rx_nodesc_drop_cnt; - void *nic_data; + struct falcon_nic_data *nic_data; struct mutex mac_lock; int port_enabled; @@ -760,6 +746,20 @@ struct efx_nic { void *loopback_selftest; }; +static inline int efx_dev_registered(struct efx_nic *efx) +{ + return efx->net_dev->reg_state == NETREG_REGISTERED; +} + +/* Net device name, for inclusion in log messages if it has been registered. + * Use efx->name not efx->net_dev->name so that races with (un)registration + * are harmless. + */ +static inline const char *efx_dev_name(struct efx_nic *efx) +{ + return efx_dev_registered(efx) ? efx->name : ""; +} + /** * struct efx_nic_type - Efx device type definition * @mem_bar: Memory BAR number @@ -795,7 +795,7 @@ struct efx_nic_type { unsigned int txd_ring_mask; unsigned int rxd_ring_mask; unsigned int evq_size; - dma_addr_t max_dma_mask; + u64 max_dma_mask; unsigned int tx_dma_mask; unsigned bug5391_mask; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 670622373ddf..601b001437c0 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -86,14 +86,17 @@ static unsigned int rx_refill_limit = 95; */ #define EFX_RXD_HEAD_ROOM 2 -/* Macros for zero-order pages (potentially) containing multiple RX buffers */ -#define RX_DATA_OFFSET(_data) \ - (((unsigned long) (_data)) & (PAGE_SIZE-1)) -#define RX_BUF_OFFSET(_rx_buf) \ - RX_DATA_OFFSET((_rx_buf)->data) - -#define RX_PAGE_SIZE(_efx) \ - (PAGE_SIZE * (1u << (_efx)->rx_buffer_order)) +static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf) +{ + /* Offset is always within one page, so we don't need to consider + * the page order. + */ + return (__force unsigned long) buf->data & (PAGE_SIZE - 1); +} +static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) +{ + return PAGE_SIZE << efx->rx_buffer_order; +} /************************************************************************** @@ -106,7 +109,7 @@ static unsigned int rx_refill_limit = 95; static int efx_lro_get_skb_hdr(struct sk_buff *skb, void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags, void *priv) { - struct efx_channel *channel = (struct efx_channel *)priv; + struct efx_channel *channel = priv; struct iphdr *iph; struct tcphdr *th; @@ -131,12 +134,12 @@ static int efx_get_frag_hdr(struct skb_frag_struct *frag, void **mac_hdr, void **ip_hdr, void **tcpudp_hdr, u64 *hdr_flags, void *priv) { - struct efx_channel *channel = (struct efx_channel *)priv; + struct efx_channel *channel = priv; struct ethhdr *eh; struct iphdr *iph; /* We support EtherII and VLAN encapsulated IPv4 */ - eh = (struct ethhdr *)(page_address(frag->page) + frag->page_offset); + eh = page_address(frag->page) + frag->page_offset; *mac_hdr = eh; if (eh->h_proto == htons(ETH_P_IP)) { @@ -269,7 +272,7 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue, return -ENOMEM; dma_addr = pci_map_page(efx->pci_dev, rx_buf->page, - 0, RX_PAGE_SIZE(efx), + 0, efx_rx_buf_size(efx), PCI_DMA_FROMDEVICE); if (unlikely(pci_dma_mapping_error(dma_addr))) { @@ -280,14 +283,14 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue, rx_queue->buf_page = rx_buf->page; rx_queue->buf_dma_addr = dma_addr; - rx_queue->buf_data = ((char *) page_address(rx_buf->page) + + rx_queue->buf_data = (page_address(rx_buf->page) + EFX_PAGE_IP_ALIGN); } - offset = RX_DATA_OFFSET(rx_queue->buf_data); rx_buf->len = bytes; - rx_buf->dma_addr = rx_queue->buf_dma_addr + offset; rx_buf->data = rx_queue->buf_data; + offset = efx_rx_buf_offset(rx_buf); + rx_buf->dma_addr = rx_queue->buf_dma_addr + offset; /* Try to pack multiple buffers per page */ if (efx->rx_buffer_order == 0) { @@ -295,7 +298,7 @@ static inline int efx_init_rx_buffer_page(struct efx_rx_queue *rx_queue, rx_queue->buf_data += ((bytes + 0x1ff) & ~0x1ff); offset += ((bytes + 0x1ff) & ~0x1ff); - space = RX_PAGE_SIZE(efx) - offset; + space = efx_rx_buf_size(efx) - offset; if (space >= bytes) { /* Refs dropped on kernel releasing each skb */ get_page(rx_queue->buf_page); @@ -344,7 +347,8 @@ static inline void efx_unmap_rx_buffer(struct efx_nic *efx, EFX_BUG_ON_PARANOID(rx_buf->skb); if (rx_buf->unmap_addr) { pci_unmap_page(efx->pci_dev, rx_buf->unmap_addr, - RX_PAGE_SIZE(efx), PCI_DMA_FROMDEVICE); + efx_rx_buf_size(efx), + PCI_DMA_FROMDEVICE); rx_buf->unmap_addr = 0; } } else if (likely(rx_buf->skb)) { @@ -400,9 +404,10 @@ static int __efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue, return 0; /* Record minimum fill level */ - if (unlikely(fill_level < rx_queue->min_fill)) + if (unlikely(fill_level < rx_queue->min_fill)) { if (fill_level) rx_queue->min_fill = fill_level; + } /* Acquire RX add lock. If this lock is contended, then a fast * fill must already be in progress (e.g. in the refill @@ -552,7 +557,7 @@ static inline void efx_rx_packet_lro(struct efx_channel *channel, struct skb_frag_struct frags; frags.page = rx_buf->page; - frags.page_offset = RX_BUF_OFFSET(rx_buf); + frags.page_offset = efx_rx_buf_offset(rx_buf); frags.size = rx_buf->len; lro_receive_frags(lro_mgr, &frags, rx_buf->len, @@ -597,7 +602,7 @@ static inline struct sk_buff *efx_rx_mk_skb(struct efx_rx_buffer *rx_buf, if (unlikely(rx_buf->len > hdr_len)) { struct skb_frag_struct *frag = skb_shinfo(skb)->frags; frag->page = rx_buf->page; - frag->page_offset = RX_BUF_OFFSET(rx_buf) + hdr_len; + frag->page_offset = efx_rx_buf_offset(rx_buf) + hdr_len; frag->size = skb->len - hdr_len; skb_shinfo(skb)->nr_frags = 1; skb->data_len = frag->size; @@ -851,7 +856,8 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue) /* For a page that is part-way through splitting into RX buffers */ if (rx_queue->buf_page != NULL) { pci_unmap_page(rx_queue->efx->pci_dev, rx_queue->buf_dma_addr, - RX_PAGE_SIZE(rx_queue->efx), PCI_DMA_FROMDEVICE); + efx_rx_buf_size(rx_queue->efx), + PCI_DMA_FROMDEVICE); __free_pages(rx_queue->buf_page, rx_queue->efx->rx_buffer_order); rx_queue->buf_page = NULL; diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index cbda15946e8f..3b2de9fe7f27 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c @@ -290,7 +290,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx, payload = &state->payload; - received = (struct efx_loopback_payload *)(char *) buf_ptr; + received = (struct efx_loopback_payload *) buf_ptr; received->ip.saddr = payload->ip.saddr; received->ip.check = payload->ip.check; @@ -424,10 +424,10 @@ static int efx_tx_loopback(struct efx_tx_queue *tx_queue) * interrupt handler. */ smp_wmb(); - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_lock_bh(efx->net_dev); rc = efx_xmit(efx, tx_queue, skb); - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_unlock_bh(efx->net_dev); if (rc != NETDEV_TX_OK) { @@ -453,7 +453,7 @@ static int efx_rx_loopback(struct efx_tx_queue *tx_queue, int tx_done = 0, rx_good, rx_bad; int i, rc = 0; - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_lock_bh(efx->net_dev); /* Count the number of tx completions, and decrement the refcnt. Any @@ -465,7 +465,7 @@ static int efx_rx_loopback(struct efx_tx_queue *tx_queue, dev_kfree_skb_any(skb); } - if (NET_DEV_REGISTERED(efx)) + if (efx_dev_registered(efx)) netif_tx_unlock_bh(efx->net_dev); /* Check TX completion and received packet counts */ @@ -517,6 +517,8 @@ efx_test_loopback(struct efx_tx_queue *tx_queue, state->packet_count = min(1 << (i << 2), state->packet_count); state->skbs = kzalloc(sizeof(state->skbs[0]) * state->packet_count, GFP_KERNEL); + if (!state->skbs) + return -ENOMEM; state->flush = 0; EFX_LOG(efx, "TX queue %d testing %s loopback with %d " @@ -700,7 +702,7 @@ int efx_offline_test(struct efx_nic *efx, * "flushing" so all inflight packets are dropped */ BUG_ON(efx->loopback_selftest); state->flush = 1; - efx->loopback_selftest = (void *)state; + efx->loopback_selftest = state; rc = efx_test_loopbacks(efx, tests, loopback_modes); diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 725d1a539c49..66a0d1442aba 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -116,18 +116,18 @@ void sfe4001_poweroff(struct efx_nic *efx) /* Turn off all power rails */ out = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); + efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); /* Disable port 1 outputs on IO expander */ cfg = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1); + efx_i2c_write(i2c, PCA9539, P1_CONFIG, &cfg, 1); /* Disable port 0 outputs on IO expander */ cfg = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1); + efx_i2c_write(i2c, PCA9539, P0_CONFIG, &cfg, 1); /* Clear any over-temperature alert */ - (void) efx_i2c_read(i2c, MAX6647, RSL, &in, 1); + efx_i2c_read(i2c, MAX6647, RSL, &in, 1); } /* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected @@ -253,14 +253,14 @@ done: fail3: /* Turn off all power rails */ out = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); + efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); /* Disable port 1 outputs on IO expander */ out = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1); + efx_i2c_write(i2c, PCA9539, P1_CONFIG, &out, 1); fail2: /* Disable port 0 outputs on IO expander */ out = 0xff; - (void) efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1); + efx_i2c_write(i2c, PCA9539, P0_CONFIG, &out, 1); fail1: return rc; } diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index b1cd6deec01f..c0146061c326 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -211,6 +211,8 @@ static int tenxpress_phy_init(struct efx_nic *efx) int rc = 0; phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); + if (!phy_data) + return -ENOMEM; efx->phy_data = phy_data; tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL); @@ -376,7 +378,7 @@ static void tenxpress_phy_reconfigure(struct efx_nic *efx) * perform a special software reset */ if ((phy_data->tx_disabled && !efx->tx_disabled) || loop_change) { - (void) tenxpress_special_reset(efx); + tenxpress_special_reset(efx); falcon_reset_xaui(efx); } diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index 9b436f5b4888..5cdd082ab8f6 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -387,7 +387,7 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index) if (unlikely(tx_queue->stopped)) { fill_level = tx_queue->insert_count - tx_queue->read_count; if (fill_level < EFX_NETDEV_TX_THRESHOLD(tx_queue)) { - EFX_BUG_ON_PARANOID(!NET_DEV_REGISTERED(efx)); + EFX_BUG_ON_PARANOID(!efx_dev_registered(efx)); /* Do this under netif_tx_lock(), to avoid racing * with efx_xmit(). */ @@ -639,11 +639,12 @@ static void efx_tsoh_block_free(struct efx_tx_queue *tx_queue, base_dma = tsoh->dma_addr & PAGE_MASK; p = &tx_queue->tso_headers_free; - while (*p != NULL) + while (*p != NULL) { if (((unsigned long)*p & PAGE_MASK) == base_kva) *p = (*p)->next; else p = &(*p)->next; + } pci_free_consistent(pci_dev, PAGE_SIZE, (void *)base_kva, base_dma); } @@ -939,9 +940,10 @@ static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue, /* Allocate a DMA-mapped header buffer. */ if (likely(TSOH_SIZE(st->p.header_length) <= TSOH_STD_SIZE)) { - if (tx_queue->tso_headers_free == NULL) + if (tx_queue->tso_headers_free == NULL) { if (efx_tsoh_block_alloc(tx_queue)) return -1; + } EFX_BUG_ON_PARANOID(!tx_queue->tso_headers_free); tsoh = tx_queue->tso_headers_free; tx_queue->tso_headers_free = tsoh->next; @@ -1106,9 +1108,10 @@ static void efx_fini_tso(struct efx_tx_queue *tx_queue) { unsigned i; - if (tx_queue->buffer) + if (tx_queue->buffer) { for (i = 0; i <= tx_queue->efx->type->txd_ring_mask; ++i) efx_tsoh_free(tx_queue, &tx_queue->buffer[i]); + } while (tx_queue->tso_headers_free != NULL) efx_tsoh_block_free(tx_queue, tx_queue->tso_headers_free, diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index dca62f190198..35ab19c27f8d 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -16,7 +16,7 @@ */ #define EFX_WORKAROUND_ALWAYS(efx) 1 -#define EFX_WORKAROUND_FALCON_A(efx) (FALCON_REV(efx) <= FALCON_REV_A1) +#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1) /* XAUI resets if link not detected */ #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 3b9f9ddbc372..f3684ad28887 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -85,7 +85,9 @@ static int xfp_phy_init(struct efx_nic *efx) int rc; phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); - efx->phy_data = (void *) phy_data; + if (!phy_data) + return -ENOMEM; + efx->phy_data = phy_data; EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index f226bcac7d17..3bb60530d4d7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1159,17 +1159,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } #ifdef SKY2_VLAN_TAG_USED -static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) +static void sky2_set_vlan_mode(struct sky2_hw *hw, u16 port, bool onoff) { - struct sky2_port *sky2 = netdev_priv(dev); - struct sky2_hw *hw = sky2->hw; - u16 port = sky2->port; - - netif_tx_lock_bh(dev); - napi_disable(&hw->napi); - - sky2->vlgrp = grp; - if (grp) { + if (onoff) { sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON); sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), @@ -1180,6 +1172,19 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_VLAN_TAG_OFF); } +} + +static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) +{ + struct sky2_port *sky2 = netdev_priv(dev); + struct sky2_hw *hw = sky2->hw; + u16 port = sky2->port; + + netif_tx_lock_bh(dev); + napi_disable(&hw->napi); + + sky2->vlgrp = grp; + sky2_set_vlan_mode(hw, port, grp != NULL); sky2_read32(hw, B0_Y2_SP_LISR); napi_enable(&hw->napi); @@ -1418,6 +1423,10 @@ static int sky2_up(struct net_device *dev) sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, TX_RING_SIZE - 1); +#ifdef SKY2_VLAN_TAG_USED + sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL); +#endif + err = sky2_rx_start(sky2); if (err) goto err_out; diff --git a/drivers/net/tokenring/3c359.h b/drivers/net/tokenring/3c359.h index b880cba0f6fd..74cf8e1a181b 100644 --- a/drivers/net/tokenring/3c359.h +++ b/drivers/net/tokenring/3c359.h @@ -264,7 +264,7 @@ struct xl_private { u16 asb; u8 __iomem *xl_mmio; - char *xl_card_name; + const char *xl_card_name; struct pci_dev *pdev ; spinlock_t xl_lock ; diff --git a/drivers/net/tokenring/olympic.h b/drivers/net/tokenring/olympic.h index c91956310fb2..10fbba08978f 100644 --- a/drivers/net/tokenring/olympic.h +++ b/drivers/net/tokenring/olympic.h @@ -254,7 +254,7 @@ struct olympic_private { u8 __iomem *olympic_mmio; u8 __iomem *olympic_lap; struct pci_dev *pdev ; - char *olympic_card_name ; + const char *olympic_card_name; spinlock_t olympic_lock ; diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 2511ca7a12aa..e9e628621639 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c @@ -225,6 +225,9 @@ static void uli526x_set_filter_mode(struct net_device *); static const struct ethtool_ops netdev_ethtool_ops; static u16 read_srom_word(long, int); static irqreturn_t uli526x_interrupt(int, void *); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void uli526x_poll(struct net_device *dev); +#endif static void uli526x_descriptor_init(struct uli526x_board_info *, unsigned long); static void allocate_rx_buffer(struct uli526x_board_info *); static void update_cr6(u32, unsigned long); @@ -339,6 +342,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev, dev->get_stats = &uli526x_get_stats; dev->set_multicast_list = &uli526x_set_filter_mode; dev->ethtool_ops = &netdev_ethtool_ops; +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = &uli526x_poll; +#endif spin_lock_init(&db->lock); @@ -681,8 +687,9 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id) db->cr5_data = inl(ioaddr + DCR5); outl(db->cr5_data, ioaddr + DCR5); if ( !(db->cr5_data & 0x180c1) ) { - spin_unlock_irqrestore(&db->lock, flags); + /* Restore CR7 to enable interrupt mask */ outl(db->cr7_data, ioaddr + DCR7); + spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED; } @@ -715,6 +722,13 @@ static irqreturn_t uli526x_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +#ifdef CONFIG_NET_POLL_CONTROLLER +static void uli526x_poll(struct net_device *dev) +{ + /* ISR grabs the irqsave lock, so this should be safe */ + uli526x_interrupt(dev->irq, dev); +} +#endif /* * Free TX resource after TX complete diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index ca0bdac07a78..fb0b918e5ccb 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -237,7 +237,7 @@ static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, skb->dev = ugeth->dev; out_be32(&((struct qe_bd __iomem *)bd)->buf, - dma_map_single(NULL, + dma_map_single(&ugeth->dev->dev, skb->data, ugeth->ug_info->uf_info.max_rx_buf_length + UCC_GETH_RX_DATA_BUF_ALIGNMENT, @@ -2158,7 +2158,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) continue; for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { if (ugeth->tx_skbuff[i][j]) { - dma_unmap_single(NULL, + dma_unmap_single(&ugeth->dev->dev, in_be32(&((struct qe_bd __iomem *)bd)->buf), (in_be32((u32 __iomem *)bd) & BD_LENGTH_MASK), @@ -2186,7 +2186,7 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth) bd = ugeth->p_rx_bd_ring[i]; for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) { if (ugeth->rx_skbuff[i][j]) { - dma_unmap_single(NULL, + dma_unmap_single(&ugeth->dev->dev, in_be32(&((struct qe_bd __iomem *)bd)->buf), ugeth->ug_info-> uf_info.max_rx_buf_length + @@ -3406,7 +3406,8 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) /* set up the buffer descriptor */ out_be32(&((struct qe_bd __iomem *)bd)->buf, - dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE)); + dma_map_single(&ugeth->dev->dev, skb->data, + skb->len, DMA_TO_DEVICE)); /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index dc6f097062df..37ecf845edfe 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1440,6 +1440,10 @@ static const struct usb_device_id products [] = { // Belkin F5D5055 USB_DEVICE(0x050d, 0x5055), .driver_info = (unsigned long) &ax88178_info, +}, { + // Apple USB Ethernet Adapter + USB_DEVICE(0x05ac, 0x1402), + .driver_info = (unsigned long) &ax88772_info, }, { }, // END }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index 3969b7a2b8e6..ae467f182c40 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -194,7 +194,7 @@ int rndis_command(struct usbnet *dev, struct rndis_msg_hdr *buf) dev_dbg(&info->control->dev, "rndis response error, code %d\n", retval); } - msleep(2); + msleep(20); } dev_dbg(&info->control->dev, "rndis response timeout\n"); return -ETIMEDOUT; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f926b5ab3d09..fe7cdf2a2a23 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -470,8 +470,7 @@ static void virtnet_remove(struct virtio_device *vdev) kfree_skb(skb); vi->num--; } - while ((skb = __skb_dequeue(&vi->send)) != NULL) - kfree_skb(skb); + __skb_queue_purge(&vi->send); BUG_ON(vi->num != 0); diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c index 9a83c9d5b8cf..7f984895b0d5 100644 --- a/drivers/net/wan/hdlc.c +++ b/drivers/net/wan/hdlc.c @@ -43,8 +43,7 @@ static const char* version = "HDLC support module revision 1.22"; #undef DEBUG_LINK -static struct hdlc_proto *first_proto = NULL; - +static struct hdlc_proto *first_proto; static int hdlc_change_mtu(struct net_device *dev, int new_mtu) { @@ -314,21 +313,25 @@ void detach_hdlc_protocol(struct net_device *dev) void register_hdlc_protocol(struct hdlc_proto *proto) { + rtnl_lock(); proto->next = first_proto; first_proto = proto; + rtnl_unlock(); } void unregister_hdlc_protocol(struct hdlc_proto *proto) { - struct hdlc_proto **p = &first_proto; - while (*p) { - if (*p == proto) { - *p = proto->next; - return; - } + struct hdlc_proto **p; + + rtnl_lock(); + p = &first_proto; + while (*p != proto) { + BUG_ON(!*p); p = &((*p)->next); } + *p = proto->next; + rtnl_unlock(); } diff --git a/drivers/net/wan/hdlc_cisco.c b/drivers/net/wan/hdlc_cisco.c index 7133c688cf20..762d21c1c703 100644 --- a/drivers/net/wan/hdlc_cisco.c +++ b/drivers/net/wan/hdlc_cisco.c @@ -56,6 +56,7 @@ struct cisco_state { cisco_proto settings; struct timer_list timer; + spinlock_t lock; unsigned long last_poll; int up; int request_sent; @@ -158,6 +159,7 @@ static int cisco_rx(struct sk_buff *skb) { struct net_device *dev = skb->dev; hdlc_device *hdlc = dev_to_hdlc(dev); + struct cisco_state *st = state(hdlc); struct hdlc_header *data = (struct hdlc_header*)skb->data; struct cisco_packet *cisco_data; struct in_device *in_dev; @@ -220,11 +222,12 @@ static int cisco_rx(struct sk_buff *skb) goto rx_error; case CISCO_KEEPALIVE_REQ: - state(hdlc)->rxseq = ntohl(cisco_data->par1); - if (state(hdlc)->request_sent && - ntohl(cisco_data->par2) == state(hdlc)->txseq) { - state(hdlc)->last_poll = jiffies; - if (!state(hdlc)->up) { + spin_lock(&st->lock); + st->rxseq = ntohl(cisco_data->par1); + if (st->request_sent && + ntohl(cisco_data->par2) == st->txseq) { + st->last_poll = jiffies; + if (!st->up) { u32 sec, min, hrs, days; sec = ntohl(cisco_data->time) / 1000; min = sec / 60; sec -= min * 60; @@ -232,12 +235,12 @@ static int cisco_rx(struct sk_buff *skb) days = hrs / 24; hrs -= days * 24; printk(KERN_INFO "%s: Link up (peer " "uptime %ud%uh%um%us)\n", - dev->name, days, hrs, - min, sec); + dev->name, days, hrs, min, sec); netif_dormant_off(dev); - state(hdlc)->up = 1; + st->up = 1; } } + spin_unlock(&st->lock); dev_kfree_skb_any(skb); return NET_RX_SUCCESS; @@ -261,24 +264,25 @@ static void cisco_timer(unsigned long arg) { struct net_device *dev = (struct net_device *)arg; hdlc_device *hdlc = dev_to_hdlc(dev); + struct cisco_state *st = state(hdlc); - if (state(hdlc)->up && - time_after(jiffies, state(hdlc)->last_poll + - state(hdlc)->settings.timeout * HZ)) { - state(hdlc)->up = 0; + spin_lock(&st->lock); + if (st->up && + time_after(jiffies, st->last_poll + st->settings.timeout * HZ)) { + st->up = 0; printk(KERN_INFO "%s: Link down\n", dev->name); netif_dormant_on(dev); } - cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, - htonl(++state(hdlc)->txseq), - htonl(state(hdlc)->rxseq)); - state(hdlc)->request_sent = 1; - state(hdlc)->timer.expires = jiffies + - state(hdlc)->settings.interval * HZ; - state(hdlc)->timer.function = cisco_timer; - state(hdlc)->timer.data = arg; - add_timer(&state(hdlc)->timer); + cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, htonl(++st->txseq), + htonl(st->rxseq)); + st->request_sent = 1; + spin_unlock(&st->lock); + + st->timer.expires = jiffies + st->settings.interval * HZ; + st->timer.function = cisco_timer; + st->timer.data = arg; + add_timer(&st->timer); } @@ -286,15 +290,20 @@ static void cisco_timer(unsigned long arg) static void cisco_start(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - state(hdlc)->up = 0; - state(hdlc)->request_sent = 0; - state(hdlc)->txseq = state(hdlc)->rxseq = 0; - - init_timer(&state(hdlc)->timer); - state(hdlc)->timer.expires = jiffies + HZ; /*First poll after 1s*/ - state(hdlc)->timer.function = cisco_timer; - state(hdlc)->timer.data = (unsigned long)dev; - add_timer(&state(hdlc)->timer); + struct cisco_state *st = state(hdlc); + unsigned long flags; + + spin_lock_irqsave(&st->lock, flags); + st->up = 0; + st->request_sent = 0; + st->txseq = st->rxseq = 0; + spin_unlock_irqrestore(&st->lock, flags); + + init_timer(&st->timer); + st->timer.expires = jiffies + HZ; /* First poll after 1 s */ + st->timer.function = cisco_timer; + st->timer.data = (unsigned long)dev; + add_timer(&st->timer); } @@ -302,10 +311,16 @@ static void cisco_start(struct net_device *dev) static void cisco_stop(struct net_device *dev) { hdlc_device *hdlc = dev_to_hdlc(dev); - del_timer_sync(&state(hdlc)->timer); + struct cisco_state *st = state(hdlc); + unsigned long flags; + + del_timer_sync(&st->timer); + + spin_lock_irqsave(&st->lock, flags); netif_dormant_on(dev); - state(hdlc)->up = 0; - state(hdlc)->request_sent = 0; + st->up = 0; + st->request_sent = 0; + spin_unlock_irqrestore(&st->lock, flags); } @@ -367,6 +382,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr) return result; memcpy(&state(hdlc)->settings, &new_settings, size); + spin_lock_init(&state(hdlc)->lock); dev->hard_start_xmit = hdlc->xmit; dev->header_ops = &cisco_header_ops; dev->type = ARPHRD_CISCO; diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 4e5c8fc35200..635b9ac9aaa1 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1787,6 +1787,8 @@ ath5k_tasklet_rx(unsigned long data) spin_lock(&sc->rxbuflock); do { + rxs.flag = 0; + if (unlikely(list_empty(&sc->rxbuf))) { ATH5K_WARN(sc, "empty rx buf pool\n"); break; diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 5fb1ae6ad3e2..77990b56860b 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -4119,6 +4119,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); rs->rs_status = 0; + rs->rs_phyerr = 0; /* * Key table status @@ -4145,7 +4146,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); } @@ -4193,6 +4194,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); rs->rs_status = 0; + rs->rs_phyerr = 0; /* * Key table status @@ -4215,7 +4217,7 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1, + rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); } diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 437a9bcc9bd3..ed4317a17cbb 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -833,6 +833,7 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001), PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000), conflict with pcnet_cs */ + PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index dcfdb404678b..688d60de55cb 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -73,8 +73,8 @@ out: return ret; } -static void lbs_ethtool_get_stats(struct net_device * dev, - struct ethtool_stats * stats, u64 * data) +static void lbs_ethtool_get_stats(struct net_device *dev, + struct ethtool_stats *stats, uint64_t *data) { struct lbs_private *priv = dev->priv; struct cmd_ds_mesh_access mesh_access; @@ -83,12 +83,12 @@ static void lbs_ethtool_get_stats(struct net_device * dev, lbs_deb_enter(LBS_DEB_ETHTOOL); /* Get Mesh Statistics */ - ret = lbs_prepare_and_send_command(priv, - CMD_MESH_ACCESS, CMD_ACT_MESH_GET_STATS, - CMD_OPTION_WAITFORRSP, 0, &mesh_access); + ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); - if (ret) + if (ret) { + memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); return; + } priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); @@ -111,19 +111,18 @@ static void lbs_ethtool_get_stats(struct net_device * dev, lbs_deb_enter(LBS_DEB_ETHTOOL); } -static int lbs_ethtool_get_sset_count(struct net_device * dev, int sset) +static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) { - switch (sset) { - case ETH_SS_STATS: + struct lbs_private *priv = dev->priv; + + if (sset == ETH_SS_STATS && dev == priv->mesh_dev) return MESH_STATS_NUM; - default: - return -EOPNOTSUPP; - } + + return -EOPNOTSUPP; } static void lbs_ethtool_get_strings(struct net_device *dev, - u32 stringset, - u8 * s) + uint32_t stringset, uint8_t *s) { int i; diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c index 8b7f5768a103..1c216e015f64 100644 --- a/drivers/net/wireless/orinoco_cs.c +++ b/drivers/net/wireless/orinoco_cs.c @@ -461,6 +461,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = { PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ + PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index d5787b37e1fb..9223ada5f00e 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -92,6 +92,7 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, u8 data[4]; struct usb_ctrlrequest dr; } *buf; + int rc; buf = kmalloc(sizeof(*buf), GFP_ATOMIC); if (!buf) @@ -116,7 +117,11 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), (unsigned char *)dr, buf, len, rtl8187_iowrite_async_cb, buf); - usb_submit_urb(urb, GFP_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + kfree(buf); + usb_free_urb(urb); + } } static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, @@ -169,6 +174,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, struct urb *urb; __le16 rts_dur = 0; u32 flags; + int rc; urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { @@ -208,7 +214,11 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, info->dev = dev; usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), hdr, skb->len, rtl8187_tx_cb, skb); - usb_submit_urb(urb, GFP_ATOMIC); + rc = usb_submit_urb(urb, GFP_ATOMIC); + if (rc < 0) { + usb_free_urb(urb); + kfree_skb(skb); + } return 0; } diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 8bddff150c70..d26f69b0184f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -946,8 +946,7 @@ err: work_done++; } - while ((skb = __skb_dequeue(&errq))) - kfree_skb(skb); + __skb_queue_purge(&errq); work_done -= handle_incoming_queue(dev, &rxq); @@ -1079,8 +1078,7 @@ static void xennet_release_rx_bufs(struct netfront_info *np) } } - while ((skb = __skb_dequeue(&free_list)) != NULL) - dev_kfree_skb(skb); + __skb_queue_purge(&free_list); spin_unlock_bh(&np->rx_lock); } diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index b31faeccb9cd..867f6fd5c2c0 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -1278,7 +1278,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) error = 0; /* Check for command packet errors */ if (full_command_packet->command.newcommand.status != 0) { - if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id] != NULL) { error = twa_fill_sense(tw_dev, request_id, 1, 1); } else { /* Skip ioctl error prints */ @@ -1290,7 +1290,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) /* Check for correct state */ if (tw_dev->state[request_id] != TW_S_POSTED) { - if (tw_dev->srb[request_id] != 0) { + if (tw_dev->srb[request_id] != NULL) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Received a request id that wasn't posted"); TW_CLEAR_ALL_INTERRUPTS(tw_dev); goto twa_interrupt_bail; @@ -1298,7 +1298,7 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) } /* Check for internal command completion */ - if (tw_dev->srb[request_id] == 0) { + if (tw_dev->srb[request_id] == NULL) { if (request_id != tw_dev->chrdev_request_id) { if (twa_aen_complete(tw_dev, request_id)) TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Error completing AEN during attention interrupt"); diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 1dca1775f4b1..0899cb61e3dd 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -3582,7 +3582,7 @@ static int checksetup(struct aha152x_setup *setup) if (i == ARRAY_SIZE(ports)) return 0; - if ( request_region(setup->io_port, IO_RANGE, "aha152x")==0 ) { + if (!request_region(setup->io_port, IO_RANGE, "aha152x")) { printk(KERN_ERR "aha152x: io port 0x%x busy.\n", setup->io_port); return 0; } @@ -3842,7 +3842,7 @@ static int __init aha152x_init(void) if ((setup_count == 1) && (setup[0].io_port == ports[i])) continue; - if ( request_region(ports[i], IO_RANGE, "aha152x")==0 ) { + if (!request_region(ports[i], IO_RANGE, "aha152x")) { printk(KERN_ERR "aha152x: io port 0x%x busy.\n", ports[i]); continue; } diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index db6de5e6afb3..7d311541c76c 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -747,7 +747,7 @@ static void send_s870(struct atp_unit *dev,unsigned char c) dev->quhd[c] = 0; } workreq = dev->quereq[c][dev->quhd[c]]; - if (dev->id[c][scmd_id(workreq)].curr_req == 0) { + if (dev->id[c][scmd_id(workreq)].curr_req == NULL) { dev->id[c][scmd_id(workreq)].curr_req = workreq; dev->last_cmd[c] = scmd_id(workreq); goto cmd_subp; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index aaa48e0c8ed0..da876d3924be 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -444,7 +444,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) { printk(KERN_ERR "scsi%d: pci resource invalid\n", hba->host->host_no); - return 0; + return NULL; } mem_base_phy = pci_resource_start(pcidev, index); @@ -454,7 +454,7 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) if (!mem_base_virt) { printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", hba->host->host_no); - return 0; + return NULL; } return mem_base_virt; } @@ -476,11 +476,11 @@ static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba) { hba->u.mv.regs = hptiop_map_pci_bar(hba, 0); - if (hba->u.mv.regs == 0) + if (hba->u.mv.regs == NULL) return -1; hba->u.mv.mu = hptiop_map_pci_bar(hba, 2); - if (hba->u.mv.mu == 0) { + if (hba->u.mv.mu == NULL) { iounmap(hba->u.mv.regs); return -1; } @@ -1210,8 +1210,8 @@ static void hptiop_remove(struct pci_dev *pcidev) static struct hptiop_adapter_ops hptiop_itl_ops = { .iop_wait_ready = iop_wait_ready_itl, - .internal_memalloc = 0, - .internal_memfree = 0, + .internal_memalloc = NULL, + .internal_memfree = NULL, .map_pci_bar = hptiop_map_pci_bar_itl, .unmap_pci_bar = hptiop_unmap_pci_bar_itl, .enable_intr = hptiop_enable_intr_itl, diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 51e2f299dbbb..3754ab87f89a 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2811,7 +2811,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) /* Check for room in outstanding command list. */ for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS && - ha->outstanding_cmds[cnt] != 0; cnt++); + ha->outstanding_cmds[cnt] != NULL; cnt++); if (cnt >= MAX_OUTSTANDING_COMMANDS) { status = 1; diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 53fa19cf2f06..788c3559522d 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -2602,7 +2602,12 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */ pbn_b2_2_115200 }, - + /* + * IntaShield IS-400 + */ + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */ + pbn_b2_4_115200 }, /* * Perle PCI-RAS cards */ diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index eab032733790..53b03c629aff 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -2054,6 +2054,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) int uart_resume_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state = drv->state + port->line; + struct device *tty_dev; + struct uart_match match = {port, drv}; mutex_lock(&state->mutex); @@ -2063,7 +2065,8 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) return 0; } - if (!port->suspended) { + tty_dev = device_find_child(port->dev, &match, serial_match_port); + if (!port->suspended && device_may_wakeup(tty_dev)) { disable_irq_wake(port->irq); mutex_unlock(&state->mutex); return 0; diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index 145c0281495d..2847336742d7 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c @@ -499,7 +499,6 @@ static void sunhv_console_write_bychar(struct console *con, const char *s, unsig } else spin_lock(&port->lock); - spin_lock_irqsave(&port->lock, flags); for (i = 0; i < n; i++) { if (*s == '\n') sunhv_console_putchar(port, '\r'); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index b3518ca9f04e..41620c0fb046 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -68,6 +68,7 @@ static unsigned long minors[N_SPI_MINORS / BITS_PER_LONG]; struct spidev_data { struct device dev; + spinlock_t spi_lock; struct spi_device *spi; struct list_head device_entry; @@ -85,12 +86,75 @@ MODULE_PARM_DESC(bufsiz, "data bytes in biggest supported SPI message"); /*-------------------------------------------------------------------------*/ +/* + * We can't use the standard synchronous wrappers for file I/O; we + * need to protect against async removal of the underlying spi_device. + */ +static void spidev_complete(void *arg) +{ + complete(arg); +} + +static ssize_t +spidev_sync(struct spidev_data *spidev, struct spi_message *message) +{ + DECLARE_COMPLETION_ONSTACK(done); + int status; + + message->complete = spidev_complete; + message->context = &done; + + spin_lock_irq(&spidev->spi_lock); + if (spidev->spi == NULL) + status = -ESHUTDOWN; + else + status = spi_async(spidev->spi, message); + spin_unlock_irq(&spidev->spi_lock); + + if (status == 0) { + wait_for_completion(&done); + status = message->status; + if (status == 0) + status = message->actual_length; + } + return status; +} + +static inline ssize_t +spidev_sync_write(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .tx_buf = spidev->buffer, + .len = len, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +static inline ssize_t +spidev_sync_read(struct spidev_data *spidev, size_t len) +{ + struct spi_transfer t = { + .rx_buf = spidev->buffer, + .len = len, + }; + struct spi_message m; + + spi_message_init(&m); + spi_message_add_tail(&t, &m); + return spidev_sync(spidev, &m); +} + +/*-------------------------------------------------------------------------*/ + /* Read-only message with current device setup */ static ssize_t spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct spidev_data *spidev; - struct spi_device *spi; ssize_t status = 0; /* chipselect only toggles at start or end of operation */ @@ -98,10 +162,9 @@ spidev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) return -EMSGSIZE; spidev = filp->private_data; - spi = spidev->spi; mutex_lock(&spidev->buf_lock); - status = spi_read(spi, spidev->buffer, count); + status = spidev_sync_read(spidev, count); if (status == 0) { unsigned long missing; @@ -122,7 +185,6 @@ spidev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct spidev_data *spidev; - struct spi_device *spi; ssize_t status = 0; unsigned long missing; @@ -131,12 +193,11 @@ spidev_write(struct file *filp, const char __user *buf, return -EMSGSIZE; spidev = filp->private_data; - spi = spidev->spi; mutex_lock(&spidev->buf_lock); missing = copy_from_user(spidev->buffer, buf, count); if (missing == 0) { - status = spi_write(spi, spidev->buffer, count); + status = spidev_sync_write(spidev, count); if (status == 0) status = count; } else @@ -153,7 +214,6 @@ static int spidev_message(struct spidev_data *spidev, struct spi_transfer *k_xfers; struct spi_transfer *k_tmp; struct spi_ioc_transfer *u_tmp; - struct spi_device *spi = spidev->spi; unsigned n, total; u8 *buf; int status = -EFAULT; @@ -215,7 +275,7 @@ static int spidev_message(struct spidev_data *spidev, spi_message_add_tail(k_tmp, &msg); } - status = spi_sync(spi, &msg); + status = spidev_sync(spidev, &msg); if (status < 0) goto done; @@ -269,8 +329,16 @@ spidev_ioctl(struct inode *inode, struct file *filp, if (err) return -EFAULT; + /* guard against device removal before, or while, + * we issue this ioctl. + */ spidev = filp->private_data; - spi = spidev->spi; + spin_lock_irq(&spidev->spi_lock); + spi = spi_dev_get(spidev->spi); + spin_unlock_irq(&spidev->spi_lock); + + if (spi == NULL) + return -ESHUTDOWN; switch (cmd) { /* read requests */ @@ -356,8 +424,10 @@ spidev_ioctl(struct inode *inode, struct file *filp, default: /* segmented and/or full-duplex I/O request */ if (_IOC_NR(cmd) != _IOC_NR(SPI_IOC_MESSAGE(0)) - || _IOC_DIR(cmd) != _IOC_WRITE) - return -ENOTTY; + || _IOC_DIR(cmd) != _IOC_WRITE) { + retval = -ENOTTY; + break; + } tmp = _IOC_SIZE(cmd); if ((tmp % sizeof(struct spi_ioc_transfer)) != 0) { @@ -385,6 +455,7 @@ spidev_ioctl(struct inode *inode, struct file *filp, kfree(ioc); break; } + spi_dev_put(spi); return retval; } @@ -488,6 +559,7 @@ static int spidev_probe(struct spi_device *spi) /* Initialize the driver data */ spidev->spi = spi; + spin_lock_init(&spidev->spi_lock); mutex_init(&spidev->buf_lock); INIT_LIST_HEAD(&spidev->device_entry); @@ -526,13 +598,17 @@ static int spidev_remove(struct spi_device *spi) { struct spidev_data *spidev = dev_get_drvdata(&spi->dev); - mutex_lock(&device_list_lock); + /* make sure ops on existing fds can abort cleanly */ + spin_lock_irq(&spidev->spi_lock); + spidev->spi = NULL; + spin_unlock_irq(&spidev->spi_lock); + /* prevent new opens */ + mutex_lock(&device_list_lock); list_del(&spidev->device_entry); dev_set_drvdata(&spi->dev, NULL); clear_bit(MINOR(spidev->dev.devt), minors); device_unregister(&spidev->dev); - mutex_unlock(&device_list_lock); return 0; diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index e4bcf5376a99..bd4ac0bafecb 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -3356,7 +3356,7 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *i info->fix.mmio_start = raddr; par->ati_regbase = ioremap(info->fix.mmio_start, 0x1000); - if (par->ati_regbase == 0) + if (par->ati_regbase == NULL) return -ENOMEM; info->fix.mmio_start += par->aux_start ? 0x400 : 0xc00; diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 72cd0d2f14ec..400e9264e456 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2277,8 +2277,8 @@ static int __devinit radeonfb_pci_register (struct pci_dev *pdev, do { rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->mapped_vram); - } while ( rinfo->fb_base == 0 && - ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) ); + } while (rinfo->fb_base == NULL && + ((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM)); if (rinfo->fb_base == NULL) { printk (KERN_ERR "radeonfb (%s): cannot map FB\n", diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index f3107ad7e545..95883236c0cd 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -200,7 +200,7 @@ static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, virt->vaddr = ioremap_nocache(phys, size); else virt->vaddr = ioremap(phys, size); - return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */ + return (virt->vaddr == NULL); /* 0, !0... 0, error_code in future */ } static inline void mga_iounmap(vaddr_t va) { diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 3ee314beacc1..274bc93ab7d8 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -1351,7 +1351,6 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev) struct pxafb_info *fbi; void *addr; struct pxafb_mach_info *inf = dev->platform_data; - struct pxafb_mode_info *mode = inf->modes; /* Alloc the pxafb_info and pseudo_palette in one step */ fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 13b38cbbe4cf..f0598961c6b0 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -1,75 +1,15 @@ -/* - * linux/drivers/video/s3c2410fb.c - * Copyright (c) Arnaud Patard, Ben Dooks +/* linux/drivers/video/s3c2410fb.c + * Copyright (c) 2004,2005 Arnaud Patard + * Copyright (c) 2004-2008 Ben Dooks + * + * S3C2410 LCD Framebuffer Driver * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * - * S3C2410 LCD Controller Frame Buffer Driver - * based on skeletonfb.c, sa1100fb.c and others - * - * ChangeLog - * 2005-04-07: Arnaud Patard <arnaud.patard@rtp-net.org> - * - u32 state -> pm_message_t state - * - S3C2410_{VA,SZ}_LCD -> S3C24XX - * - * 2005-03-15: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Removed the ioctl - * - use readl/writel instead of __raw_writel/__raw_readl - * - * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Added the possibility to set on or off the - * debugging messages - * - Replaced 0 and 1 by on or off when reading the - * /sys files - * - * 2005-03-23: Ben Dooks <ben-linux@fluff.org> - * - added non 16bpp modes - * - updated platform information for range of x/y/bpp - * - add code to ensure palette is written correctly - * - add pixel clock divisor control - * - * 2004-11-11: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Removed the use of currcon as it no more exists - * - Added LCD power sysfs interface - * - * 2004-11-03: Ben Dooks <ben-linux@fluff.org> - * - minor cleanups - * - add suspend/resume support - * - s3c2410fb_setcolreg() not valid in >8bpp modes - * - removed last CONFIG_FB_S3C2410_FIXED - * - ensure lcd controller stopped before cleanup - * - added sysfs interface for backlight power - * - added mask for gpio configuration - * - ensured IRQs disabled during GPIO configuration - * - disable TPAL before enabling video - * - * 2004-09-20: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Suppress command line options - * - * 2004-09-15: Arnaud Patard <arnaud.patard@rtp-net.org> - * - code cleanup - * - * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Renamed from h1940fb.c to s3c2410fb.c - * - Add support for different devices - * - Backlight support - * - * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at> - * - added clock (de-)allocation code - * - added fixem fbmem option - * - * 2004-07-27: Arnaud Patard <arnaud.patard@rtp-net.org> - * - code cleanup - * - added a forgotten return in h1940fb_init - * - * 2004-07-19: Herbert Pötzl <herbert@13thfloor.at> - * - code cleanup and extended debugging - * - * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org> - * - First version - */ + * Driver based on skeletonfb.c, sa1100fb.c and others. +*/ #include <linux/module.h> #include <linux/kernel.h> @@ -580,6 +520,27 @@ static int s3c2410fb_setcolreg(unsigned regno, return 0; } +/* s3c2410fb_lcd_enable + * + * shutdown the lcd controller + */ +static void s3c2410fb_lcd_enable(struct s3c2410fb_info *fbi, int enable) +{ + unsigned long flags; + + local_irq_save(flags); + + if (enable) + fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; + else + fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; + + writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1); + + local_irq_restore(flags); +} + + /* * s3c2410fb_blank * @blank_mode: the blank mode we want. @@ -589,9 +550,6 @@ static int s3c2410fb_setcolreg(unsigned regno, * blanking succeeded, != 0 if un-/blanking failed due to e.g. a * video mode which doesn't support it. Implements VESA suspend * and powerdown modes on hardware that supports disabling hsync/vsync: - * blank_mode == 2: suspend vsync - * blank_mode == 3: suspend hsync - * blank_mode == 4: powerdown * * Returns negative errno on error, or zero on success. * @@ -605,6 +563,12 @@ static int s3c2410fb_blank(int blank_mode, struct fb_info *info) tpal_reg += is_s3c2412(fbi) ? S3C2412_TPAL : S3C2410_TPAL; + if (blank_mode == FB_BLANK_POWERDOWN) { + s3c2410fb_lcd_enable(fbi, 0); + } else { + s3c2410fb_lcd_enable(fbi, 1); + } + if (blank_mode == FB_BLANK_UNBLANK) writel(0x0, tpal_reg); else { @@ -948,7 +912,10 @@ static int __init s3c24xxfb_probe(struct platform_device *pdev, } /* create device files */ - device_create_file(&pdev->dev, &dev_attr_debug); + ret = device_create_file(&pdev->dev, &dev_attr_debug); + if (ret) { + printk(KERN_ERR "failed to add debug attribute\n"); + } printk(KERN_INFO "fb%d: %s frame buffer device\n", fbinfo->node, fbinfo->fix.id); @@ -983,21 +950,6 @@ static int __init s3c2412fb_probe(struct platform_device *pdev) return s3c24xxfb_probe(pdev, DRV_S3C2412); } -/* s3c2410fb_stop_lcd - * - * shutdown the lcd controller - */ -static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi) -{ - unsigned long flags; - - local_irq_save(flags); - - fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; - writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1); - - local_irq_restore(flags); -} /* * Cleanup @@ -1010,7 +962,7 @@ static int s3c2410fb_remove(struct platform_device *pdev) unregister_framebuffer(fbinfo); - s3c2410fb_stop_lcd(info); + s3c2410fb_lcd_enable(info, 0); msleep(1); s3c2410fb_unmap_video_memory(fbinfo); @@ -1043,7 +995,7 @@ static int s3c2410fb_suspend(struct platform_device *dev, pm_message_t state) struct fb_info *fbinfo = platform_get_drvdata(dev); struct s3c2410fb_info *info = fbinfo->par; - s3c2410fb_stop_lcd(info); + s3c2410fb_lcd_enable(info, 0); /* sleep before disabling the clock, we need to ensure * the LCD DMA engine is not going to get back on the bus @@ -1118,3 +1070,5 @@ MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " "Ben Dooks <ben-linux@fluff.org>"); MODULE_DESCRIPTION("Framebuffer driver for the s3c2410"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s3c2410-lcd"); +MODULE_ALIAS("platform:s3c2412-lcd"); diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index dbb73b95e2ef..9a6ba3e9d1b8 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -1,26 +1,14 @@ /* * linux/drivers/video/s3c2410fb.h - * Copyright (c) Arnaud Patard + * Copyright (c) 2004 Arnaud Patard + * + * S3C2410 LCD Framebuffer Driver * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * - * S3C2410 LCD Controller Frame Buffer Driver - * based on skeletonfb.c, sa1100fb.h - * - * ChangeLog - * - * 2004-12-04: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Moved dprintk to s3c2410fb.c - * - * 2004-09-07: Arnaud Patard <arnaud.patard@rtp-net.org> - * - Renamed from h1940fb.h to s3c2410fb.h - * - Changed h1940 to s3c2410 - * - * 2004-07-15: Arnaud Patard <arnaud.patard@rtp-net.org> - * - First version - */ +*/ #ifndef __S3C2410FB_H #define __S3C2410FB_H diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 73803624c131..b9343844cd1f 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -5787,7 +5787,7 @@ sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } else { struct sis_video_info *countvideo = card_list; ivideo->cardnumber = 1; - while((countvideo = countvideo->next) != 0) + while((countvideo = countvideo->next) != NULL) ivideo->cardnumber++; } diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index 742b5c656d66..15d4a768b1f6 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c @@ -663,14 +663,14 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) sm501fb_sync_regs(fbi); mdelay(10); - if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { + if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } - if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { + if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { control |= SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); @@ -678,14 +678,14 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) } } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { /* disable panel power */ - if (pd->flags & SM501FB_FLAG_PANEL_USE_FPEN) { + if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { control &= ~SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } - if (pd->flags & SM501FB_FLAG_PANEL_USE_VBIASEN) { + if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { control &= ~SM501_DC_PANEL_CONTROL_BIAS; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 254d115cafab..ccb78f66c2b6 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -295,6 +295,19 @@ config ALIM7101_WDT Most people will say N. +config GEODE_WDT + tristate "AMD Geode CS5535/CS5536 Watchdog" + depends on MGEODE_LX + help + This driver enables a watchdog capability built into the + CS5535/CS5536 companion chips for the AMD Geode GX and LX + processors. This watchdog watches your kernel to make sure + it doesn't freeze, and if it does, it reboots your computer after + a certain amount of time. + + You can compile this driver directly into the kernel, or use + it as a module. The module will be called geodewdt. + config SC520_WDT tristate "AMD Elan SC520 processor Watchdog" depends on X86 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f3fb170fe5c6..25b352b664d9 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o obj-$(CONFIG_ALIM1535_WDT) += alim1535_wdt.o obj-$(CONFIG_ALIM7101_WDT) += alim7101_wdt.o +obj-$(CONFIG_GEODE_WDT) += geodewdt.o obj-$(CONFIG_SC520_WDT) += sc520_wdt.o obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o obj-$(CONFIG_IB700_WDT) += ib700wdt.o diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 1237113dc14a..03b3e3d91e7c 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c @@ -29,7 +29,8 @@ #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) #define stampit() stamp("here i am") -#define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); }) +#define pr_devinit(fmt, args...) ({ static const __devinitconst char __fmt[] = fmt; printk(__fmt, ## args); }) +#define pr_init(fmt, args...) ({ static const __initconst char __fmt[] = fmt; printk(__fmt, ## args); }) #define WATCHDOG_NAME "bfin-wdt" #define PFX WATCHDOG_NAME ": " @@ -377,20 +378,6 @@ static int bfin_wdt_resume(struct platform_device *pdev) # define bfin_wdt_resume NULL #endif -static struct platform_device bfin_wdt_device = { - .name = WATCHDOG_NAME, - .id = -1, -}; - -static struct platform_driver bfin_wdt_driver = { - .driver = { - .name = WATCHDOG_NAME, - .owner = THIS_MODULE, - }, - .suspend = bfin_wdt_suspend, - .resume = bfin_wdt_resume, -}; - static const struct file_operations bfin_wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -418,11 +405,67 @@ static struct notifier_block bfin_wdt_notifier = { }; /** - * bfin_wdt_init - Initialize module + * bfin_wdt_probe - Initialize module * - * Registers the device and notifier handler. Actual device + * Registers the misc device and notifier handler. Actual device * initialization is handled by bfin_wdt_open(). */ +static int __devinit bfin_wdt_probe(struct platform_device *pdev) +{ + int ret; + + ret = register_reboot_notifier(&bfin_wdt_notifier); + if (ret) { + pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); + return ret; + } + + ret = misc_register(&bfin_wdt_miscdev); + if (ret) { + pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&bfin_wdt_notifier); + return ret; + } + + pr_devinit(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", + timeout, nowayout); + + return 0; +} + +/** + * bfin_wdt_remove - Initialize module + * + * Unregisters the misc device and notifier handler. Actual device + * deinitialization is handled by bfin_wdt_close(). + */ +static int __devexit bfin_wdt_remove(struct platform_device *pdev) +{ + misc_deregister(&bfin_wdt_miscdev); + unregister_reboot_notifier(&bfin_wdt_notifier); + return 0; +} + +static struct platform_device *bfin_wdt_device; + +static struct platform_driver bfin_wdt_driver = { + .probe = bfin_wdt_probe, + .remove = __devexit_p(bfin_wdt_remove), + .suspend = bfin_wdt_suspend, + .resume = bfin_wdt_resume, + .driver = { + .name = WATCHDOG_NAME, + .owner = THIS_MODULE, + }, +}; + +/** + * bfin_wdt_init - Initialize module + * + * Checks the module params and registers the platform device & driver. + * Real work is in the platform probe function. + */ static int __init bfin_wdt_init(void) { int ret; @@ -436,44 +479,32 @@ static int __init bfin_wdt_init(void) /* Since this is an on-chip device and needs no board-specific * resources, we'll handle all the platform device stuff here. */ - ret = platform_device_register(&bfin_wdt_device); - if (ret) - return ret; - - ret = platform_driver_probe(&bfin_wdt_driver, NULL); - if (ret) - return ret; - - ret = register_reboot_notifier(&bfin_wdt_notifier); + ret = platform_driver_register(&bfin_wdt_driver); if (ret) { - pr_init(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); + pr_init(KERN_ERR PFX "unable to register driver\n"); return ret; } - ret = misc_register(&bfin_wdt_miscdev); - if (ret) { - pr_init(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); - unregister_reboot_notifier(&bfin_wdt_notifier); - return ret; + bfin_wdt_device = platform_device_register_simple(WATCHDOG_NAME, -1, NULL, 0); + if (IS_ERR(bfin_wdt_device)) { + pr_init(KERN_ERR PFX "unable to register device\n"); + platform_driver_unregister(&bfin_wdt_driver); + return PTR_ERR(bfin_wdt_device); } - pr_init(KERN_INFO PFX "initialized: timeout=%d sec (nowayout=%d)\n", - timeout, nowayout); - return 0; } /** * bfin_wdt_exit - Deinitialize module * - * Unregisters the device and notifier handler. Actual device - * deinitialization is handled by bfin_wdt_close(). + * Back out the platform device & driver steps. Real work is in the + * platform remove function. */ static void __exit bfin_wdt_exit(void) { - misc_deregister(&bfin_wdt_miscdev); - unregister_reboot_notifier(&bfin_wdt_notifier); + platform_device_unregister(bfin_wdt_device); + platform_driver_unregister(&bfin_wdt_driver); } module_init(bfin_wdt_init); diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index d362f5bf658a..c1ba0db48501 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c @@ -1,12 +1,10 @@ /* - * drivers/char/watchdog/booke_wdt.c - * * Watchdog timer for PowerPC Book-E systems * * Author: Matthew McClintock * Maintainer: Kumar Gala <galak@kernel.crashing.org> * - * Copyright 2005 Freescale Semiconductor Inc. + * Copyright 2005, 2008 Freescale Semiconductor Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,6 +14,7 @@ #include <linux/module.h> #include <linux/fs.h> +#include <linux/smp.h> #include <linux/miscdevice.h> #include <linux/notifier.h> #include <linux/watchdog.h> @@ -38,7 +37,7 @@ #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ #endif /* for timing information */ -u32 booke_wdt_enabled = 0; +u32 booke_wdt_enabled; u32 booke_wdt_period = WDT_PERIOD_DEFAULT; #ifdef CONFIG_FSL_BOOKE @@ -47,33 +46,31 @@ u32 booke_wdt_period = WDT_PERIOD_DEFAULT; #define WDTP(x) (TCR_WP(x)) #endif -/* - * booke_wdt_ping: - */ -static __inline__ void booke_wdt_ping(void) +static DEFINE_SPINLOCK(booke_wdt_lock); + +static void __booke_wdt_ping(void *data) { mtspr(SPRN_TSR, TSR_ENW|TSR_WIS); } -/* - * booke_wdt_enable: - */ -static __inline__ void booke_wdt_enable(void) +static void booke_wdt_ping(void) +{ + on_each_cpu(__booke_wdt_ping, NULL, 0, 0); +} + +static void __booke_wdt_enable(void *data) { u32 val; /* clear status before enabling watchdog */ - booke_wdt_ping(); + __booke_wdt_ping(NULL); val = mfspr(SPRN_TCR); val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); mtspr(SPRN_TCR, val); } -/* - * booke_wdt_write: - */ -static ssize_t booke_wdt_write (struct file *file, const char __user *buf, +static ssize_t booke_wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { booke_wdt_ping(); @@ -81,15 +78,11 @@ static ssize_t booke_wdt_write (struct file *file, const char __user *buf, } static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, - .firmware_version = 0, - .identity = "PowerPC Book-E Watchdog", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, + .identity = "PowerPC Book-E Watchdog", }; -/* - * booke_wdt_ioctl: - */ -static int booke_wdt_ioctl (struct inode *inode, struct file *file, +static int booke_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { u32 tmp = 0; @@ -97,7 +90,7 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file, switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user ((struct watchdog_info __user *) arg, &ident, + if (copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(struct watchdog_info))) return -EFAULT; case WDIOC_GETSTATUS: @@ -132,33 +125,33 @@ static int booke_wdt_ioctl (struct inode *inode, struct file *file, return 0; } -/* - * booke_wdt_open: - */ -static int booke_wdt_open (struct inode *inode, struct file *file) + +static int booke_wdt_open(struct inode *inode, struct file *file) { + spin_lock(&booke_wdt_lock); if (booke_wdt_enabled == 0) { booke_wdt_enabled = 1; - booke_wdt_enable(); - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", - booke_wdt_period); + on_each_cpu(__booke_wdt_enable, NULL, 0, 0); + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " + "(wdt_period=%d)\n", booke_wdt_period); } + spin_unlock(&booke_wdt_lock); return nonseekable_open(inode, file); } static const struct file_operations booke_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = booke_wdt_write, - .ioctl = booke_wdt_ioctl, - .open = booke_wdt_open, + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = booke_wdt_write, + .ioctl = booke_wdt_ioctl, + .open = booke_wdt_open, }; static struct miscdevice booke_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &booke_wdt_fops, + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &booke_wdt_fops, }; static void __exit booke_wdt_exit(void) @@ -166,28 +159,27 @@ static void __exit booke_wdt_exit(void) misc_deregister(&booke_wdt_miscdev); } -/* - * booke_wdt_init: - */ static int __init booke_wdt_init(void) { int ret = 0; - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Loaded\n"); ident.firmware_version = cur_cpu_spec->pvr_value; ret = misc_register(&booke_wdt_miscdev); if (ret) { - printk (KERN_CRIT "Cannot register miscdev on minor=%d (err=%d)\n", + printk(KERN_CRIT "Cannot register miscdev on minor=%d: %d\n", WATCHDOG_MINOR, ret); return ret; } + spin_lock(&booke_wdt_lock); if (booke_wdt_enabled == 1) { - printk (KERN_INFO "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", - booke_wdt_period); - booke_wdt_enable(); + printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " + "(wdt_period=%d)\n", booke_wdt_period); + on_each_cpu(__booke_wdt_enable, NULL, 0, 0); } + spin_unlock(&booke_wdt_lock); return ret; } diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c new file mode 100644 index 000000000000..f85b19625f97 --- /dev/null +++ b/drivers/watchdog/geodewdt.c @@ -0,0 +1,309 @@ +/* Watchdog timer for the Geode GX/LX with the CS5535/CS5536 companion chip + * + * Copyright (C) 2006-2007, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + + +#include <linux/module.h> +#include <linux/moduleparam.h> +#include <linux/types.h> +#include <linux/miscdevice.h> +#include <linux/watchdog.h> +#include <linux/fs.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> + +#include <asm/uaccess.h> +#include <asm/geode.h> + +#define GEODEWDT_HZ 500 +#define GEODEWDT_SCALE 6 +#define GEODEWDT_MAX_SECONDS 131 + +#define WDT_FLAGS_OPEN 1 +#define WDT_FLAGS_ORPHAN 2 + +#define DRV_NAME "geodewdt" +#define WATCHDOG_NAME "Geode GX/LX WDT" +#define WATCHDOG_TIMEOUT 60 + +static int timeout = WATCHDOG_TIMEOUT; +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=131, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static struct platform_device *geodewdt_platform_device; +static unsigned long wdt_flags; +static int wdt_timer; +static int safe_close; + +static void geodewdt_ping(void) +{ + /* Stop the counter */ + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); + + /* Reset the counter */ + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); + + /* Enable the counter */ + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); +} + +static void geodewdt_disable(void) +{ + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); +} + +static int geodewdt_set_heartbeat(int val) +{ + if (val < 1 || val > GEODEWDT_MAX_SECONDS) + return -EINVAL; + + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, 0); + geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, val * GEODEWDT_HZ); + geode_mfgpt_write(wdt_timer, MFGPT_REG_COUNTER, 0); + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, MFGPT_SETUP_CNTEN); + + timeout = val; + return 0; +} + +static int +geodewdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) + return -EBUSY; + + if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) + __module_get(THIS_MODULE); + + geodewdt_ping(); + return nonseekable_open(inode, file); +} + +static int +geodewdt_release(struct inode *inode, struct file *file) +{ + if (safe_close) { + geodewdt_disable(); + module_put(THIS_MODULE); + } + else { + printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); + geodewdt_ping(); + + set_bit(WDT_FLAGS_ORPHAN, &wdt_flags); + } + + clear_bit(WDT_FLAGS_OPEN, &wdt_flags); + safe_close = 0; + return 0; +} + +static ssize_t +geodewdt_write(struct file *file, const char __user *data, size_t len, + loff_t *ppos) +{ + if(len) { + if (!nowayout) { + size_t i; + safe_close = 0; + + for (i = 0; i != len; i++) { + char c; + + if (get_user(c, data + i)) + return -EFAULT; + + if (c == 'V') + safe_close = 1; + } + } + + geodewdt_ping(); + } + return len; +} + +static int +geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int interval; + + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING + | WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = WATCHDOG_NAME, + }; + + switch(cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_KEEPALIVE: + geodewdt_ping(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(interval, p)) + return -EFAULT; + + if (geodewdt_set_heartbeat(interval)) + return -EINVAL; + +/* Fall through */ + + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + case WDIOC_SETOPTIONS: + { + int options, ret = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + geodewdt_disable(); + ret = 0; + } + + if (options & WDIOS_ENABLECARD) { + geodewdt_ping(); + ret = 0; + } + + return ret; + } + default: + return -ENOTTY; + } + + return 0; +} + +static const struct file_operations geodewdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = geodewdt_write, + .ioctl = geodewdt_ioctl, + .open = geodewdt_open, + .release = geodewdt_release, +}; + +static struct miscdevice geodewdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &geodewdt_fops +}; + +static int __devinit +geodewdt_probe(struct platform_device *dev) +{ + int ret, timer; + + timer = geode_mfgpt_alloc_timer(MFGPT_TIMER_ANY, + MFGPT_DOMAIN_WORKING, THIS_MODULE); + + if (timer == -1) { + printk(KERN_ERR "geodewdt: No timers were available\n"); + return -ENODEV; + } + + wdt_timer = timer; + + /* Set up the timer */ + + geode_mfgpt_write(wdt_timer, MFGPT_REG_SETUP, + GEODEWDT_SCALE | (3 << 8)); + + /* Set up comparator 2 to reset when the event fires */ + geode_mfgpt_toggle_event(wdt_timer, MFGPT_CMP2, MFGPT_EVENT_RESET, 1); + + /* Set up the initial timeout */ + + geode_mfgpt_write(wdt_timer, MFGPT_REG_CMP2, + timeout * GEODEWDT_HZ); + + ret = misc_register(&geodewdt_miscdev); + + return ret; +} + +static int __devexit +geodewdt_remove(struct platform_device *dev) +{ + misc_deregister(&geodewdt_miscdev); + return 0; +} + +static void +geodewdt_shutdown(struct platform_device *dev) +{ + geodewdt_disable(); +} + +static struct platform_driver geodewdt_driver = { + .probe = geodewdt_probe, + .remove = __devexit_p(geodewdt_remove), + .shutdown = geodewdt_shutdown, + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, +}; + +static int __init +geodewdt_init(void) +{ + int ret; + + ret = platform_driver_register(&geodewdt_driver); + if (ret) + return ret; + + geodewdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); + if (IS_ERR(geodewdt_platform_device)) { + ret = PTR_ERR(geodewdt_platform_device); + goto err; + } + + return 0; +err: + platform_driver_unregister(&geodewdt_driver); + return ret; +} + +static void __exit +geodewdt_exit(void) +{ + platform_device_unregister(geodewdt_platform_device); + platform_driver_unregister(&geodewdt_driver); +} + +module_init(geodewdt_init); +module_exit(geodewdt_exit); + +MODULE_AUTHOR("Advanced Micro Devices, Inc"); +MODULE_DESCRIPTION("Geode GX/LX Watchdog Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 6483d1066b95..6a63535fc04d 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -418,23 +418,20 @@ static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, static unsigned long rom_pl; static int die_nmi_called; - if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) - return NOTIFY_OK; - - spin_lock_irqsave(&rom_lock, rom_pl); - if (!die_nmi_called) - asminline_call(&cmn_regs, cru_rom_addr); - die_nmi_called = 1; - spin_unlock_irqrestore(&rom_lock, rom_pl); - if (cmn_regs.u1.ral == 0) { - printk(KERN_WARNING "hpwdt: An NMI occurred, " - "but unable to determine source.\n"); - } else { - panic("An NMI occurred, please see the Integrated " - "Management Log for details.\n"); + if (ulReason == DIE_NMI || ulReason == DIE_NMI_IPI) { + spin_lock_irqsave(&rom_lock, rom_pl); + if (!die_nmi_called) + asminline_call(&cmn_regs, cru_rom_addr); + die_nmi_called = 1; + spin_unlock_irqrestore(&rom_lock, rom_pl); + if (cmn_regs.u1.ral != 0) { + panic("An NMI occurred, please see the Integrated " + "Management Log for details.\n"); + } } - return NOTIFY_STOP; + die_nmi_called = 0; + return NOTIFY_DONE; } /* diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index a0e6809e369f..95ba985bd341 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -41,9 +41,10 @@ * 82801HH (ICH8DH) : document number 313056-003, 313057-009, * 82801HO (ICH8DO) : document number 313056-003, 313057-009, * 82801HEM (ICH8M-E) : document number 313056-003, 313057-009, - * 82801IB (ICH9) : document number 316972-001, 316973-001, - * 82801IR (ICH9R) : document number 316972-001, 316973-001, - * 82801IH (ICH9DH) : document number 316972-001, 316973-001, + * 82801IB (ICH9) : document number 316972-001, 316973-006, + * 82801IR (ICH9R) : document number 316972-001, 316973-006, + * 82801IH (ICH9DH) : document number 316972-001, 316973-006, + * 82801IO (ICH9DO) : document number 316972-001, 316973-006, * 6300ESB (6300ESB) : document number 300641-003, 300884-010, * 631xESB (631xESB) : document number 313082-001, 313075-005, * 632xESB (632xESB) : document number 313082-001, 313075-005 @@ -55,8 +56,8 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" -#define DRV_VERSION "1.02" -#define DRV_RELDATE "26-Jul-2007" +#define DRV_VERSION "1.03" +#define DRV_RELDATE "30-Apr-2008" #define PFX DRV_NAME ": " /* Includes */ @@ -104,6 +105,7 @@ enum iTCO_chipsets { TCO_ICH9, /* ICH9 */ TCO_ICH9R, /* ICH9R */ TCO_ICH9DH, /* ICH9DH */ + TCO_ICH9DO, /* ICH9DO */ TCO_631XESB, /* 631xESB/632xESB */ }; @@ -136,6 +138,7 @@ static struct { {"ICH9", 2}, {"ICH9R", 2}, {"ICH9DH", 2}, + {"ICH9DO", 2}, {"631xESB/632xESB", 2}, {NULL,0} }; @@ -181,6 +184,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )}, { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )}, + { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO )}, { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index c622a0e6c9ae..528b882420b6 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c @@ -44,6 +44,7 @@ #define WATCHDOG_NAME "w83697hf/hg WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ +#define WATCHDOG_EARLY_DISABLE 1 /* Disable until userland kicks in */ static unsigned long wdt_is_open; static char expect_close; @@ -56,12 +57,16 @@ MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect) static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255 (default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +static int early_disable = WATCHDOG_EARLY_DISABLE; +module_param(early_disable, int, 0); +MODULE_PARM_DESC(early_disable, "Watchdog gets disabled at boot time (default=" __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")"); + /* * Kernel methods. */ @@ -140,7 +145,7 @@ w83697hf_init(void) w83697hf_deselect_wdt(); } -static int +static void wdt_ping(void) { spin_lock(&io_lock); @@ -150,10 +155,9 @@ wdt_ping(void) w83697hf_deselect_wdt(); spin_unlock(&io_lock); - return 0; } -static int +static void wdt_enable(void) { spin_lock(&io_lock); @@ -164,10 +168,9 @@ wdt_enable(void) w83697hf_deselect_wdt(); spin_unlock(&io_lock); - return 0; } -static int +static void wdt_disable(void) { spin_lock(&io_lock); @@ -178,7 +181,22 @@ wdt_disable(void) w83697hf_deselect_wdt(); spin_unlock(&io_lock); - return 0; +} + +static unsigned char +wdt_running(void) +{ + unsigned char t; + + spin_lock(&io_lock); + w83697hf_select_wdt(); + + t = w83697hf_get_reg(0xF4); /* Read timer */ + + w83697hf_deselect_wdt(); + spin_unlock(&io_lock); + + return t; } static int @@ -397,7 +415,11 @@ wdt_init(void) } w83697hf_init(); - wdt_disable(); /* Disable watchdog until first use */ + if (early_disable) { + if (wdt_running()) + printk (KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n"); + wdt_disable(); + } if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index 6653e29637a7..7013aaff6aed 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -119,6 +119,9 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo) dp = description + strlen(description); sprintf(dp, ";uid=0x%x", sesInfo->linux_uid); + dp = description + strlen(description); + sprintf(dp, ";user=%s", sesInfo->userName); + cFYI(1, ("key description = %s", description)); spnego_key = request_key(&cifs_spnego_key_type, description, ""); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 7b9938445b07..9b8b4cfdf993 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -2159,8 +2159,7 @@ copyRetry: cFYI(1, ("Send error in copy = %d with %d files copied", rc, le16_to_cpu(pSMBr->CopyCount))); } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto copyRetry; @@ -2249,8 +2248,7 @@ createSymLinkRetry: if (rc) cFYI(1, ("Send error in SetPathInfo create symlink = %d", rc)); - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto createSymLinkRetry; @@ -4095,8 +4093,7 @@ getDFSRetry: target_nodes, nls_codepage); GetDFSRefExit: - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto getDFSRetry; @@ -5117,8 +5114,7 @@ setPermsRetry: if (rc) cFYI(1, ("SetPathInfo (perms) returned %d", rc)); - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto setPermsRetry; return rc; @@ -5340,8 +5336,7 @@ QAllEAsRetry: } } } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto QAllEAsRetry; @@ -5490,8 +5485,7 @@ QEARetry: } } } - if (pSMB) - cifs_buf_release(pSMB); + cifs_buf_release(pSMB); if (rc == -EAGAIN) goto QEARetry; diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 00ced97bd53a..129dbfe4dca7 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -172,7 +172,7 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat, { struct inode *pinode = NULL; - memset(pfnd_dat, sizeof(FILE_UNIX_BASIC_INFO), 0); + memset(pfnd_dat, 0, sizeof(FILE_UNIX_BASIC_INFO)); /* __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); __le64 pfnd_dat->NumOfBytes = cpu_to_le64(0); @@ -384,7 +384,7 @@ static int get_sfu_mode(struct inode *inode, static void fill_fake_finddata(FILE_ALL_INFO *pfnd_dat, struct super_block *sb) { - memset(pfnd_dat, sizeof(FILE_ALL_INFO), 0); + memset(pfnd_dat, 0, sizeof(FILE_ALL_INFO)); /* __le64 pfnd_dat->AllocationSize = cpu_to_le64(0); __le64 pfnd_dat->EndOfFile = cpu_to_le64(0); diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index cd62d75b2cc0..e2832bc7869a 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c @@ -1906,9 +1906,9 @@ int ecryptfs_get_tfm_and_mutex_for_cipher_name(struct crypto_blkcipher **tfm, goto out; } } - mutex_unlock(&key_tfm_list_mutex); (*tfm) = key_tfm->key_tfm; (*tfm_mutex) = &key_tfm->key_tfm_mutex; out: + mutex_unlock(&key_tfm_list_mutex); return rc; } diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index fb77e0962132..43e99513334a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -488,7 +488,12 @@ static struct fuse_conn *new_conn(struct super_block *sb) err = bdi_init(&fc->bdi); if (err) goto error_kfree; - err = bdi_register_dev(&fc->bdi, fc->dev); + if (sb->s_bdev) { + err = bdi_register(&fc->bdi, NULL, "%u:%u-fuseblk", + MAJOR(fc->dev), MINOR(fc->dev)); + } else { + err = bdi_register_dev(&fc->bdi, fc->dev); + } if (err) goto error_bdi_destroy; /* diff --git a/fs/ntfs/upcase.c b/fs/ntfs/upcase.c index 9101807dc81a..e2f72ca98037 100644 --- a/fs/ntfs/upcase.c +++ b/fs/ntfs/upcase.c @@ -77,11 +77,10 @@ ntfschar *generate_default_upcase(void) uc[i] = cpu_to_le16(i); for (r = 0; uc_run_table[r][0]; r++) for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++) - uc[i] = cpu_to_le16(le16_to_cpu(uc[i]) + - uc_run_table[r][2]); + le16_add_cpu(&uc[i], uc_run_table[r][2]); for (r = 0; uc_dup_table[r][0]; r++) for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2) - uc[i + 1] = cpu_to_le16(le16_to_cpu(uc[i + 1]) - 1); + le16_add_cpu(&uc[i + 1], -1); for (r = 0; uc_word_table[r][0]; r++) uc[uc_word_table[r][0]] = cpu_to_le16(uc_word_table[r][1]); return uc; diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 6f4e8dc97da1..b08d10017911 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -425,7 +425,8 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, } } unlock_new_inode(inode); - } + } else + module_put(de->owner); return inode; out_ino: diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 74a323d2b850..32dc14cd8900 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -139,7 +139,7 @@ static int meminfo_read_proc(char *page, char **start, off_t off, #define K(x) ((x) << (PAGE_SHIFT - 10)) si_meminfo(&i); si_swapinfo(&i); - committed = atomic_read(&vm_committed_space); + committed = atomic_long_read(&vm_committed_space); allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 5105015a75ad..98e0e86093b4 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -387,6 +387,8 @@ _xfs_buf_lookup_pages( if (unlikely(page == NULL)) { if (flags & XBF_READ_AHEAD) { bp->b_page_count = i; + for (i = 0; i < bp->b_page_count; i++) + unlock_page(bp->b_pages[i]); return -ENOMEM; } @@ -416,17 +418,24 @@ _xfs_buf_lookup_pages( ASSERT(!PagePrivate(page)); if (!PageUptodate(page)) { page_count--; - if (blocksize < PAGE_CACHE_SIZE && !PagePrivate(page)) { + if (blocksize >= PAGE_CACHE_SIZE) { + if (flags & XBF_READ) + bp->b_flags |= _XBF_PAGE_LOCKED; + } else if (!PagePrivate(page)) { if (test_page_region(page, offset, nbytes)) page_count++; } } - unlock_page(page); bp->b_pages[i] = page; offset = 0; } + if (!(bp->b_flags & _XBF_PAGE_LOCKED)) { + for (i = 0; i < bp->b_page_count; i++) + unlock_page(bp->b_pages[i]); + } + if (page_count == bp->b_page_count) bp->b_flags |= XBF_DONE; @@ -746,6 +755,7 @@ xfs_buf_associate_memory( bp->b_count_desired = len; bp->b_buffer_length = buflen; bp->b_flags |= XBF_MAPPED; + bp->b_flags &= ~_XBF_PAGE_LOCKED; return 0; } @@ -1093,8 +1103,10 @@ _xfs_buf_ioend( xfs_buf_t *bp, int schedule) { - if (atomic_dec_and_test(&bp->b_io_remaining) == 1) + if (atomic_dec_and_test(&bp->b_io_remaining) == 1) { + bp->b_flags &= ~_XBF_PAGE_LOCKED; xfs_buf_ioend(bp, schedule); + } } STATIC void @@ -1125,6 +1137,9 @@ xfs_buf_bio_end_io( if (--bvec >= bio->bi_io_vec) prefetchw(&bvec->bv_page->flags); + + if (bp->b_flags & _XBF_PAGE_LOCKED) + unlock_page(page); } while (bvec >= bio->bi_io_vec); _xfs_buf_ioend(bp, 1); @@ -1163,7 +1178,8 @@ _xfs_buf_ioapply( * filesystem block size is not smaller than the page size. */ if ((bp->b_buffer_length < PAGE_CACHE_SIZE) && - (bp->b_flags & XBF_READ) && + ((bp->b_flags & (XBF_READ|_XBF_PAGE_LOCKED)) == + (XBF_READ|_XBF_PAGE_LOCKED)) && (blocksize >= PAGE_CACHE_SIZE)) { bio = bio_alloc(GFP_NOIO, 1); diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h index 841d7883528d..f948ec7ba9a4 100644 --- a/fs/xfs/linux-2.6/xfs_buf.h +++ b/fs/xfs/linux-2.6/xfs_buf.h @@ -66,6 +66,25 @@ typedef enum { _XBF_PAGES = (1 << 18), /* backed by refcounted pages */ _XBF_RUN_QUEUES = (1 << 19),/* run block device task queue */ _XBF_DELWRI_Q = (1 << 21), /* buffer on delwri queue */ + + /* + * Special flag for supporting metadata blocks smaller than a FSB. + * + * In this case we can have multiple xfs_buf_t on a single page and + * need to lock out concurrent xfs_buf_t readers as they only + * serialise access to the buffer. + * + * If the FSB size >= PAGE_CACHE_SIZE case, we have no serialisation + * between reads of the page. Hence we can have one thread read the + * page and modify it, but then race with another thread that thinks + * the page is not up-to-date and hence reads it again. + * + * The result is that the first modifcation to the page is lost. + * This sort of AGF/AGI reading race can happen when unlinking inodes + * that require truncation and results in the AGI unlinked list + * modifications being lost. + */ + _XBF_PAGE_LOCKED = (1 << 22), } xfs_buf_flags_t; typedef enum { diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 65e78c13d4ae..5f60363b9343 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c @@ -184,19 +184,24 @@ xfs_file_release( return -xfs_release(XFS_I(inode)); } +/* + * We ignore the datasync flag here because a datasync is effectively + * identical to an fsync. That is, datasync implies that we need to write + * only the metadata needed to be able to access the data that is written + * if we crash after the call completes. Hence if we are writing beyond + * EOF we have to log the inode size change as well, which makes it a + * full fsync. If we don't write beyond EOF, the inode core will be + * clean in memory and so we don't need to log the inode, just like + * fsync. + */ STATIC int xfs_file_fsync( struct file *filp, struct dentry *dentry, int datasync) { - int flags = FSYNC_WAIT; - - if (datasync) - flags |= FSYNC_DATA; xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED); - return -xfs_fsync(XFS_I(dentry->d_inode), flags, - (xfs_off_t)0, (xfs_off_t)-1); + return -xfs_fsync(XFS_I(dentry->d_inode)); } /* diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 9d73cb5c0fc7..25eb2a9e8d9b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h @@ -230,14 +230,6 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ /* - * Flags to vop_fsync/reclaim. - */ -#define FSYNC_NOWAIT 0 /* asynchronous flush */ -#define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ -#define FSYNC_INVAL 0x2 /* flush and invalidate cached data */ -#define FSYNC_DATA 0x4 /* synchronous fsync of data only */ - -/* * Tracking vnode activity. */ #if defined(XFS_INODE_TRACE) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index cf0bb9c1d621..e569bf5d6cf0 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2974,6 +2974,7 @@ xfs_iflush_cluster( xfs_mount_t *mp = ip->i_mount; xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino); unsigned long first_index, mask; + unsigned long inodes_per_cluster; int ilist_size; xfs_inode_t **ilist; xfs_inode_t *iq; @@ -2985,8 +2986,9 @@ xfs_iflush_cluster( ASSERT(pag->pagi_inodeok); ASSERT(pag->pag_ici_init); - ilist_size = XFS_INODE_CLUSTER_SIZE(mp) * sizeof(xfs_inode_t *); - ilist = kmem_alloc(ilist_size, KM_MAYFAIL); + inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog; + ilist_size = inodes_per_cluster * sizeof(xfs_inode_t *); + ilist = kmem_alloc(ilist_size, KM_MAYFAIL|KM_NOFS); if (!ilist) return 0; @@ -2995,8 +2997,7 @@ xfs_iflush_cluster( read_lock(&pag->pag_ici_lock); /* really need a gang lookup range call here */ nr_found = radix_tree_gang_lookup(&pag->pag_ici_root, (void**)ilist, - first_index, - XFS_INODE_CLUSTER_SIZE(mp)); + first_index, inodes_per_cluster); if (nr_found == 0) goto out_free; diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 70702a60b4bb..e475e3717eb3 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c @@ -856,18 +856,14 @@ xfs_readlink( /* * xfs_fsync * - * This is called to sync the inode and its data out to disk. - * We need to hold the I/O lock while flushing the data, and - * the inode lock while flushing the inode. The inode lock CANNOT - * be held while flushing the data, so acquire after we're done - * with that. + * This is called to sync the inode and its data out to disk. We need to hold + * the I/O lock while flushing the data, and the inode lock while flushing the + * inode. The inode lock CANNOT be held while flushing the data, so acquire + * after we're done with that. */ int xfs_fsync( - xfs_inode_t *ip, - int flag, - xfs_off_t start, - xfs_off_t stop) + xfs_inode_t *ip) { xfs_trans_t *tp; int error; @@ -875,103 +871,79 @@ xfs_fsync( xfs_itrace_entry(ip); - ASSERT(start >= 0 && stop >= -1); - if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return XFS_ERROR(EIO); - if (flag & FSYNC_DATA) - filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping); + /* capture size updates in I/O completion before writing the inode. */ + error = filemap_fdatawait(vn_to_inode(XFS_ITOV(ip))->i_mapping); + if (error) + return XFS_ERROR(error); /* - * We always need to make sure that the required inode state - * is safe on disk. The vnode might be clean but because - * of committed transactions that haven't hit the disk yet. - * Likewise, there could be unflushed non-transactional - * changes to the inode core that have to go to disk. + * We always need to make sure that the required inode state is safe on + * disk. The vnode might be clean but we still might need to force the + * log because of committed transactions that haven't hit the disk yet. + * Likewise, there could be unflushed non-transactional changes to the + * inode core that have to go to disk and this requires us to issue + * a synchronous transaction to capture these changes correctly. * - * The following code depends on one assumption: that - * any transaction that changes an inode logs the core - * because it has to change some field in the inode core - * (typically nextents or nblocks). That assumption - * implies that any transactions against an inode will - * catch any non-transactional updates. If inode-altering - * transactions exist that violate this assumption, the - * code breaks. Right now, it figures that if the involved - * update_* field is clear and the inode is unpinned, the - * inode is clean. Either it's been flushed or it's been - * committed and the commit has hit the disk unpinning the inode. - * (Note that xfs_inode_item_format() called at commit clears - * the update_* fields.) + * This code relies on the assumption that if the update_* fields + * of the inode are clear and the inode is unpinned then it is clean + * and no action is required. */ xfs_ilock(ip, XFS_ILOCK_SHARED); - /* If we are flushing data then we care about update_size - * being set, otherwise we care about update_core - */ - if ((flag & FSYNC_DATA) ? - (ip->i_update_size == 0) : - (ip->i_update_core == 0)) { + if (!(ip->i_update_size || ip->i_update_core)) { /* - * Timestamps/size haven't changed since last inode - * flush or inode transaction commit. That means - * either nothing got written or a transaction - * committed which caught the updates. If the - * latter happened and the transaction hasn't - * hit the disk yet, the inode will be still - * be pinned. If it is, force the log. + * Timestamps/size haven't changed since last inode flush or + * inode transaction commit. That means either nothing got + * written or a transaction committed which caught the updates. + * If the latter happened and the transaction hasn't hit the + * disk yet, the inode will be still be pinned. If it is, + * force the log. */ xfs_iunlock(ip, XFS_ILOCK_SHARED); if (xfs_ipincount(ip)) { - _xfs_log_force(ip->i_mount, (xfs_lsn_t)0, - XFS_LOG_FORCE | - ((flag & FSYNC_WAIT) - ? XFS_LOG_SYNC : 0), + error = _xfs_log_force(ip->i_mount, (xfs_lsn_t)0, + XFS_LOG_FORCE | XFS_LOG_SYNC, &log_flushed); } else { /* - * If the inode is not pinned and nothing - * has changed we don't need to flush the - * cache. + * If the inode is not pinned and nothing has changed + * we don't need to flush the cache. */ changed = 0; } - error = 0; } else { /* - * Kick off a transaction to log the inode - * core to get the updates. Make it - * sync if FSYNC_WAIT is passed in (which - * is done by everybody but specfs). The - * sync transaction will also force the log. + * Kick off a transaction to log the inode core to get the + * updates. The sync transaction will also force the log. */ xfs_iunlock(ip, XFS_ILOCK_SHARED); tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); - if ((error = xfs_trans_reserve(tp, 0, - XFS_FSYNC_TS_LOG_RES(ip->i_mount), - 0, 0, 0))) { + error = xfs_trans_reserve(tp, 0, + XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); + if (error) { xfs_trans_cancel(tp, 0); return error; } xfs_ilock(ip, XFS_ILOCK_EXCL); /* - * Note - it's possible that we might have pushed - * ourselves out of the way during trans_reserve - * which would flush the inode. But there's no - * guarantee that the inode buffer has actually - * gone out yet (it's delwri). Plus the buffer - * could be pinned anyway if it's part of an - * inode in another recent transaction. So we - * play it safe and fire off the transaction anyway. + * Note - it's possible that we might have pushed ourselves out + * of the way during trans_reserve which would flush the inode. + * But there's no guarantee that the inode buffer has actually + * gone out yet (it's delwri). Plus the buffer could be pinned + * anyway if it's part of an inode in another recent + * transaction. So we play it safe and fire off the + * transaction anyway. */ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); xfs_trans_ihold(tp, ip); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - if (flag & FSYNC_WAIT) - xfs_trans_set_sync(tp); + xfs_trans_set_sync(tp); error = _xfs_trans_commit(tp, 0, &log_flushed); xfs_iunlock(ip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index 8abe8f186e20..57335ba4ce53 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h @@ -18,8 +18,7 @@ int xfs_open(struct xfs_inode *ip); int xfs_setattr(struct xfs_inode *ip, struct bhv_vattr *vap, int flags, struct cred *credp); int xfs_readlink(struct xfs_inode *ip, char *link); -int xfs_fsync(struct xfs_inode *ip, int flag, xfs_off_t start, - xfs_off_t stop); +int xfs_fsync(struct xfs_inode *ip); int xfs_release(struct xfs_inode *ip); int xfs_inactive(struct xfs_inode *ip); int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, diff --git a/include/asm-arm/arch-omap/board-palmte.h b/include/asm-arm/arch-omap/board-palmte.h index cd22035a7160..6fac2c8935be 100644 --- a/include/asm-arm/arch-omap/board-palmte.h +++ b/include/asm-arm/arch-omap/board-palmte.h @@ -14,8 +14,6 @@ #ifndef __OMAP_BOARD_PALMTE_H #define __OMAP_BOARD_PALMTE_H -#include <asm/arch/gpio.h> - #define PALMTE_USBDETECT_GPIO 0 #define PALMTE_USB_OR_DC_GPIO 1 #define PALMTE_TSC_GPIO 4 diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h index 57523bdb642b..12a5e4de9518 100644 --- a/include/asm-arm/arch-omap/clock.h +++ b/include/asm-arm/arch-omap/clock.h @@ -73,6 +73,8 @@ struct clk { #endif }; +struct cpufreq_frequency_table; + struct clk_functions { int (*clk_enable)(struct clk *clk); void (*clk_disable)(struct clk *clk); @@ -83,6 +85,9 @@ struct clk_functions { void (*clk_allow_idle)(struct clk *clk); void (*clk_deny_idle)(struct clk *clk); void (*clk_disable_unused)(struct clk *clk); +#ifdef CONFIG_CPU_FREQ + void (*clk_init_cpufreq_table)(struct cpufreq_frequency_table **); +#endif }; extern unsigned int mpurate; diff --git a/include/asm-arm/arch-omap/entry-macro.S b/include/asm-arm/arch-omap/entry-macro.S index 74cd57221c8e..369093a45fcf 100644 --- a/include/asm-arm/arch-omap/entry-macro.S +++ b/include/asm-arm/arch-omap/entry-macro.S @@ -8,6 +8,7 @@ * warranty of any kind, whether express or implied. */ #include <asm/hardware.h> +#include <asm/arch/io.h> #include <asm/arch/irqs.h> #if defined(CONFIG_ARCH_OMAP1) diff --git a/include/asm-arm/arch-omap/gpio.h b/include/asm-arm/arch-omap/gpio.h index 86621a04cd8f..5ee6a49864c3 100644 --- a/include/asm-arm/arch-omap/gpio.h +++ b/include/asm-arm/arch-omap/gpio.h @@ -26,7 +26,6 @@ #ifndef __ASM_ARCH_OMAP_GPIO_H #define __ASM_ARCH_OMAP_GPIO_H -#include <asm/hardware.h> #include <asm/arch/irqs.h> #include <asm/io.h> diff --git a/include/asm-arm/arch-omap/hardware.h b/include/asm-arm/arch-omap/hardware.h index da572092e255..91d85b3417b7 100644 --- a/include/asm-arm/arch-omap/hardware.h +++ b/include/asm-arm/arch-omap/hardware.h @@ -41,7 +41,6 @@ #include <asm/types.h> #include <asm/arch/cpu.h> #endif -#include <asm/arch/io.h> #include <asm/arch/serial.h> /* diff --git a/include/asm-arm/arch-sa1100/collie.h b/include/asm-arm/arch-sa1100/collie.h index 14a344aa3cc7..762eba535813 100644 --- a/include/asm-arm/arch-sa1100/collie.h +++ b/include/asm-arm/arch-sa1100/collie.h @@ -34,9 +34,12 @@ #define COLLIE_GPIO_ON_KEY GPIO_GPIO (0) #define COLLIE_GPIO_AC_IN GPIO_GPIO (1) +#define COLLIE_GPIO_SDIO_INT GPIO_GPIO (11) #define COLLIE_GPIO_CF_IRQ GPIO_GPIO (14) #define COLLIE_GPIO_nREMOCON_INT GPIO_GPIO (15) #define COLLIE_GPIO_UCB1x00_RESET GPIO_GPIO (16) +#define COLLIE_GPIO_nMIC_ON GPIO_GPIO (17) +#define COLLIE_GPIO_nREMOCON_ON GPIO_GPIO (18) #define COLLIE_GPIO_CO GPIO_GPIO (20) #define COLLIE_GPIO_MCP_CLK GPIO_GPIO (21) #define COLLIE_GPIO_CF_CD GPIO_GPIO (22) @@ -49,6 +52,7 @@ #define COLLIE_IRQ_GPIO_ON_KEY IRQ_GPIO0 #define COLLIE_IRQ_GPIO_AC_IN IRQ_GPIO1 +#define COLLIE_IRQ_GPIO_SDIO_IRQ IRQ_GPIO11 #define COLLIE_IRQ_GPIO_CF_IRQ IRQ_GPIO14 #define COLLIE_IRQ_GPIO_nREMOCON_INT IRQ_GPIO15 #define COLLIE_IRQ_GPIO_CO IRQ_GPIO20 diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h index 5c22b0112106..8e05bdb5f12f 100644 --- a/include/asm-arm/page.h +++ b/include/asm-arm/page.h @@ -179,10 +179,10 @@ typedef unsigned long pgprot_t; #endif /* STRICT_MM_TYPECHECKS */ -typedef struct page *pgtable_t; - #endif /* CONFIG_MMU */ +typedef struct page *pgtable_t; + #include <asm/memory.h> #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h index 6335de9a2bb3..514af792a598 100644 --- a/include/asm-arm/system.h +++ b/include/asm-arm/system.h @@ -48,20 +48,6 @@ #define CPUID_TCM 2 #define CPUID_TLBTYPE 3 -#ifdef CONFIG_CPU_CP15 -#define read_cpuid(reg) \ - ({ \ - unsigned int __val; \ - asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \ - : "=r" (__val) \ - : \ - : "cc"); \ - __val; \ - }) -#else -#define read_cpuid(reg) (processor_id) -#endif - /* * This is used to ensure the compiler did actually allocate the register we * asked it for some inline assembly sequences. Apparently we can't trust @@ -78,6 +64,21 @@ #include <linux/stringify.h> #include <linux/irqflags.h> +#ifdef CONFIG_CPU_CP15 +#define read_cpuid(reg) \ + ({ \ + unsigned int __val; \ + asm("mrc p15, 0, %0, c0, c0, " __stringify(reg) \ + : "=r" (__val) \ + : \ + : "cc"); \ + __val; \ + }) +#else +extern unsigned int processor_id; +#define read_cpuid(reg) (processor_id) +#endif + /* * The CPU ID never changes at run time, so we might as well tell the * compiler that it's constant. Use this function to read the CPU ID diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index ecf675a59d21..6be061d09da9 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -1,8 +1,12 @@ #ifndef _ASM_GENERIC_GPIO_H #define _ASM_GENERIC_GPIO_H +#include <linux/types.h> + #ifdef CONFIG_HAVE_GPIO_LIB +#include <linux/compiler.h> + /* Platforms may implement their GPIO interface with library code, * at a small performance cost for non-inlined operations and some * extra memory (for code and for per-GPIO table entries). @@ -74,7 +78,7 @@ struct gpio_chip { extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset); -extern int __init __must_check gpiochip_reserve(int start, int ngpio); +extern int __must_check gpiochip_reserve(int start, int ngpio); /* add/remove chips */ extern int gpiochip_add(struct gpio_chip *chip); diff --git a/include/asm-mips/gic.h b/include/asm-mips/gic.h index 01b2f92dc33d..3a492f225f00 100644 --- a/include/asm-mips/gic.h +++ b/include/asm-mips/gic.h @@ -330,7 +330,7 @@ #define GIC_SH_RMASK_OFS 0x0300 #define GIC_CLR_INTR_MASK(intr, val) \ - GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32)) + GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_RMASK_OFS + 4 + (((((intr) / 32) ^ 1) - 1) * 4)), ((val) << ((intr) % 32))) /* Register Map for Local Section */ #define GIC_VPE_CTL_OFS 0x0000 diff --git a/include/asm-mips/mach-au1x00/au1000.h b/include/asm-mips/mach-au1x00/au1000.h index 363a14ee0ae5..1b5064dac007 100644 --- a/include/asm-mips/mach-au1x00/au1000.h +++ b/include/asm-mips/mach-au1x00/au1000.h @@ -1036,7 +1036,7 @@ enum soc_au1200_ints { #define USBD_INTSTAT 0xB020001C # define USBDEV_INT_SOF (1 << 12) # define USBDEV_INT_HF_BIT 6 -# define USBDEV_INT_HF_MASK 0x3f << USBDEV_INT_HF_BIT) +# define USBDEV_INT_HF_MASK (0x3f << USBDEV_INT_HF_BIT) # define USBDEV_INT_CMPLT_BIT 0 # define USBDEV_INT_CMPLT_MASK (0x3f << USBDEV_INT_CMPLT_BIT) #define USBD_CONFIG 0xB0200020 diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index 943c5a3fac8a..a4d0f876b427 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h @@ -428,12 +428,11 @@ extern void mpic_init(struct mpic *mpic); */ -/* Change/Read the priority of an interrupt. Default is 8 for irqs and +/* Change the priority of an interrupt. Default is 8 for irqs and * 10 for IPIs. You can call this on both IPIs and IRQ numbers, but the * IPI number is then the offset'ed (linux irq number mapped to the IPI) */ extern void mpic_irq_set_priority(unsigned int irq, unsigned int pri); -extern unsigned int mpic_irq_get_priority(unsigned int irq); /* Setup a non-boot CPU */ extern void mpic_setup_this_cpu(void); diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index d8a56cddf7f2..b163da79bb6d 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -126,6 +126,8 @@ struct sparc_trapf { #define TRACEREG32_SZ sizeof(struct pt_regs32) #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) +#ifdef __KERNEL__ + struct global_reg_snapshot { unsigned long tstate; unsigned long tpc; @@ -137,8 +139,6 @@ struct global_reg_snapshot { unsigned long pad2; }; -#ifdef __KERNEL__ - #define __ARCH_WANT_COMPAT_SYS_PTRACE #define force_successful_syscall_return() \ @@ -306,6 +306,8 @@ extern void __show_regs(struct pt_regs *); #define SF_XARG5 0x58 #define SF_XXARG 0x5c +#ifdef __KERNEL__ + /* global_reg_snapshot offsets */ #define GR_SNAP_TSTATE 0x00 #define GR_SNAP_TPC 0x08 @@ -316,6 +318,8 @@ extern void __show_regs(struct pt_regs *); #define GR_SNAP_PAD1 0x30 #define GR_SNAP_PAD2 0x38 +#endif /* __KERNEL__ */ + /* Stuff for the ptrace system call */ #define PTRACE_SPARC_DETACH 11 #define PTRACE_GETREGS 12 diff --git a/include/asm-x86/tlbflush.h b/include/asm-x86/tlbflush.h index 0c0674d94255..35c76ceb9f40 100644 --- a/include/asm-x86/tlbflush.h +++ b/include/asm-x86/tlbflush.h @@ -22,12 +22,23 @@ static inline void __native_flush_tlb(void) static inline void __native_flush_tlb_global(void) { - unsigned long cr4 = read_cr4(); + unsigned long flags; + unsigned long cr4; + /* + * Read-modify-write to CR4 - protect it from preemption and + * from interrupts. (Use the raw variant because this code can + * be called from deep inside debugging code.) + */ + raw_local_irq_save(flags); + + cr4 = read_cr4(); /* clear PGE */ write_cr4(cr4 & ~X86_CR4_PGE); /* write old PGE again and flush TLBs */ write_cr4(cr4); + + raw_local_irq_restore(flags); } static inline void __native_flush_tlb_single(unsigned long addr) diff --git a/include/linux/gpio.h b/include/linux/gpio.h index 4987a84078ef..98be6c5762b9 100644 --- a/include/linux/gpio.h +++ b/include/linux/gpio.h @@ -8,6 +8,9 @@ #else +#include <linux/types.h> +#include <linux/errno.h> + /* * Some platforms don't support the GPIO programming interface. * diff --git a/include/linux/mman.h b/include/linux/mman.h index 87920a0852a3..dab8892e6ff1 100644 --- a/include/linux/mman.h +++ b/include/linux/mman.h @@ -17,14 +17,14 @@ extern int sysctl_overcommit_memory; extern int sysctl_overcommit_ratio; -extern atomic_t vm_committed_space; +extern atomic_long_t vm_committed_space; #ifdef CONFIG_SMP extern void vm_acct_memory(long pages); #else static inline void vm_acct_memory(long pages) { - atomic_add(pages, &vm_committed_space); + atomic_long_add(pages, &vm_committed_space); } #endif diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index c463cd8a15a4..443bc7cd8c62 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -703,7 +703,7 @@ extern struct pglist_data *next_online_pgdat(struct pglist_data *pgdat); extern struct zone *next_zone(struct zone *zone); /** - * for_each_pgdat - helper macro to iterate over all nodes + * for_each_online_pgdat - helper macro to iterate over all online nodes * @pgdat - pointer to a pg_data_t variable */ #define for_each_online_pgdat(pgdat) \ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 2b0266484c84..f27fd2009334 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -514,12 +514,10 @@ struct net_device #define NETIF_F_NETNS_LOCAL 8192 /* Does not change network namespaces */ #define NETIF_F_MULTI_QUEUE 16384 /* Has multiple TX/RX queues */ #define NETIF_F_LRO 32768 /* large receive offload */ -#define NETIF_F_VLAN_TSO 65536 /* Supports TSO for VLANs */ -#define NETIF_F_VLAN_CSUM 131072 /* Supports TX checksumming for VLANs */ /* Segmentation offload features */ -#define NETIF_F_GSO_SHIFT 20 -#define NETIF_F_GSO_MASK 0xfff00000 +#define NETIF_F_GSO_SHIFT 16 +#define NETIF_F_GSO_MASK 0xffff0000 #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) @@ -747,6 +745,9 @@ struct net_device /* rtnetlink link ops */ const struct rtnl_link_ops *rtnl_link_ops; + /* VLAN feature mask */ + unsigned long vlan_features; + /* for setting kernel sock attribute on TCP connection setup */ #define GSO_MAX_SIZE 65536 unsigned int gso_max_size; diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h index e4c66593b5c6..0c5eb7ed8b3f 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -3,7 +3,6 @@ #ifdef __KERNEL__ #include <linux/init.h> -#include <linux/types.h> #include <linux/skbuff.h> #include <linux/net.h> #include <linux/netdevice.h> @@ -14,6 +13,7 @@ #include <linux/list.h> #include <net/net_namespace.h> #endif +#include <linux/types.h> #include <linux/compiler.h> /* Responses from hook functions. */ diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index dd9c97f2d436..590ac3d6d5d6 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -11,11 +11,11 @@ #ifdef __KERNEL__ #include <linux/if.h> -#include <linux/types.h> #include <linux/in.h> #include <linux/if_arp.h> #include <linux/skbuff.h> #endif +#include <linux/types.h> #include <linux/compiler.h> #include <linux/netfilter_arp.h> diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h index bfc889f90276..092bd50581a9 100644 --- a/include/linux/netfilter_ipv4/ip_tables.h +++ b/include/linux/netfilter_ipv4/ip_tables.h @@ -17,11 +17,11 @@ #ifdef __KERNEL__ #include <linux/if.h> -#include <linux/types.h> #include <linux/in.h> #include <linux/ip.h> #include <linux/skbuff.h> #endif +#include <linux/types.h> #include <linux/compiler.h> #include <linux/netfilter_ipv4.h> diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h index f2507dcc5750..1089e33cf633 100644 --- a/include/linux/netfilter_ipv6/ip6_tables.h +++ b/include/linux/netfilter_ipv6/ip6_tables.h @@ -17,11 +17,11 @@ #ifdef __KERNEL__ #include <linux/if.h> -#include <linux/types.h> #include <linux/in6.h> #include <linux/ipv6.h> #include <linux/skbuff.h> #endif +#include <linux/types.h> #include <linux/compiler.h> #include <linux/netfilter_ipv6.h> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index cf6dbd759395..9b940e644179 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1761,6 +1761,7 @@ #define PCI_VENDOR_ID_INTASHIELD 0x135a #define PCI_DEVICE_ID_INTASHIELD_IS200 0x0d80 +#define PCI_DEVICE_ID_INTASHIELD_IS400 0x0dc0 #define PCI_VENDOR_ID_QUATECH 0x135C #define PCI_DEVICE_ID_QUATECH_QSC100 0x0010 @@ -2383,6 +2384,9 @@ #define PCI_DEVICE_ID_INTEL_ICH10_4 0x3a30 #define PCI_DEVICE_ID_INTEL_ICH10_5 0x3a60 #define PCI_DEVICE_ID_INTEL_IOAT_SNB 0x402f +#define PCI_DEVICE_ID_INTEL_5400_ERR 0x4030 +#define PCI_DEVICE_ID_INTEL_5400_FBD0 0x4035 +#define PCI_DEVICE_ID_INTEL_5400_FBD1 0x4036 #define PCI_DEVICE_ID_INTEL_IOAT_SCNB 0x65ff #define PCI_DEVICE_ID_INTEL_TOLAPAI_0 0x5031 #define PCI_DEVICE_ID_INTEL_TOLAPAI_1 0x5032 diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 47fbcba11850..78bfdea24a8e 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h @@ -262,7 +262,6 @@ int bitmap_create(mddev_t *mddev); void bitmap_flush(mddev_t *mddev); void bitmap_destroy(mddev_t *mddev); -char *file_path(struct file *file, char *buf, int count); void bitmap_print_sb(struct bitmap *bitmap); void bitmap_update_sb(struct bitmap *bitmap); diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 81a1a02d4566..b7386ae9d288 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -72,6 +72,8 @@ */ #define MD_PATCHLEVEL_VERSION 3 +extern int mdp_major; + extern int register_md_personality (struct mdk_personality *p); extern int unregister_md_personality (struct mdk_personality *p); extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev), diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 812ffa590cff..3dea9f545c8f 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -180,13 +180,15 @@ struct mddev_s int sync_speed_min; int sync_speed_max; + /* resync even though the same disks are shared among md-devices */ + int parallel_resync; + int ok_start_degraded; /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started * SYNC: actually doing a resync, not a recovery - * ERR: and IO error was detected - abort the resync/recovery - * INTR: someone requested a (clean) early abort. + * INTR: resync needs to be aborted for some reason * DONE: thread is done and is waiting to be reaped * REQUEST: user-space has requested a sync (used with SYNC) * CHECK: user-space request for for check-only, no repair @@ -196,7 +198,6 @@ struct mddev_s */ #define MD_RECOVERY_RUNNING 0 #define MD_RECOVERY_SYNC 1 -#define MD_RECOVERY_ERR 2 #define MD_RECOVERY_INTR 3 #define MD_RECOVERY_DONE 4 #define MD_RECOVERY_NEEDED 5 diff --git a/include/linux/sm501.h b/include/linux/sm501.h index bca134544700..95c1c39ba445 100644 --- a/include/linux/sm501.h +++ b/include/linux/sm501.h @@ -71,8 +71,8 @@ extern unsigned long sm501_gpio_get(struct device *dev, #define SM501FB_FLAG_DISABLE_AT_EXIT (1<<1) #define SM501FB_FLAG_USE_HWCURSOR (1<<2) #define SM501FB_FLAG_USE_HWACCEL (1<<3) -#define SM501FB_FLAG_PANEL_USE_FPEN (1<<4) -#define SM501FB_FLAG_PANEL_USE_VBIASEN (1<<5) +#define SM501FB_FLAG_PANEL_NO_FPEN (1<<4) +#define SM501FB_FLAG_PANEL_NO_VBIASEN (1<<5) struct sm501_platdata_fbsub { struct fb_videomode *def_mode; diff --git a/include/linux/tcp.h b/include/linux/tcp.h index d96d9b122304..18e62e3d406f 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -355,7 +355,7 @@ struct tcp_sock { u32 lost_retrans_low; /* Sent seq after any rxmit (lowest) */ u16 advmss; /* Advertised MSS */ - u16 prior_ssthresh; /* ssthresh saved at recovery start */ + u32 prior_ssthresh; /* ssthresh saved at recovery start */ u32 lost_out; /* Lost packets */ u32 sacked_out; /* SACK'd packets */ u32 fackets_out; /* FACK'd packets */ diff --git a/include/linux/types.h b/include/linux/types.h index 9dc2346627b4..d4a9ce6e2760 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -197,8 +197,6 @@ typedef u64 resource_size_t; typedef u32 resource_size_t; #endif -#endif /* __KERNEL__ */ - struct ustat { __kernel_daddr_t f_tfree; __kernel_ino_t f_tinode; @@ -206,4 +204,6 @@ struct ustat { char f_fpack[6]; }; +#endif /* __KERNEL__ */ + #endif /* _LINUX_TYPES_H */ diff --git a/include/net/netlink.h b/include/net/netlink.h index a5506c42f03c..112dcdf7e34e 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -772,12 +772,13 @@ static inline int __nla_parse_nested_compat(struct nlattr *tb[], int maxtype, const struct nla_policy *policy, int len) { - if (nla_len(nla) < len) + int nested_len = nla_len(nla) - NLA_ALIGN(len); + + if (nested_len < 0) return -1; - if (nla_len(nla) >= NLA_ALIGN(len) + sizeof(struct nlattr)) - return nla_parse_nested(tb, maxtype, - nla_data(nla) + NLA_ALIGN(len), - policy); + if (nested_len >= nla_attr_size(0)) + return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len), + nested_len, policy); memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); return 0; } diff --git a/init/Kconfig b/init/Kconfig index 6135d07f31ec..6199d1120900 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -13,6 +13,7 @@ config DEFCONFIG_LIST default "/lib/modules/$UNAME_RELEASE/.config" default "/etc/kernel-config" default "/boot/config-$UNAME_RELEASE" + default "$ARCH_DEFCONFIG" default "arch/$ARCH/defconfig" menu "General setup" diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c index 7473b0c59d4d..693d24694a6c 100644 --- a/init/do_mounts_md.c +++ b/init/do_mounts_md.c @@ -24,7 +24,6 @@ static struct { static int md_setup_ents __initdata; -extern int mdp_major; /* * Parse the command-line parameters given our kernel, but do not * actually try to invoke the MD device now; that is handled by diff --git a/kernel/cgroup.c b/kernel/cgroup.c index fbc6fc8949b4..15ac0e1e4f4d 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2903,7 +2903,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys) cg = tsk->cgroups; parent = task_cgroup(tsk, subsys->subsys_id); - snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "node_%d", tsk->pid); + snprintf(nodename, MAX_CGROUP_TYPE_NAMELEN, "%d", tsk->pid); /* Pin the hierarchy */ atomic_inc(&parent->root->sb->s_active); diff --git a/kernel/exit.c b/kernel/exit.c index 1510f78a0ffa..8f6185e69b69 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -126,6 +126,12 @@ static void __exit_signal(struct task_struct *tsk) __unhash_process(tsk); + /* + * Do this under ->siglock, we can race with another thread + * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals. + */ + flush_sigqueue(&tsk->pending); + tsk->signal = NULL; tsk->sighand = NULL; spin_unlock(&sighand->siglock); @@ -133,7 +139,6 @@ static void __exit_signal(struct task_struct *tsk) __cleanup_sighand(sighand); clear_tsk_thread_flag(tsk,TIF_SIGPENDING); - flush_sigqueue(&tsk->pending); if (sig) { flush_sigqueue(&sig->shared_pending); taskstats_tgid_free(sig); diff --git a/kernel/module.c b/kernel/module.c index f5e9491ef7ac..5f80478b746d 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1337,7 +1337,19 @@ out_unreg: kobject_put(&mod->mkobj.kobj); return err; } -#endif + +static void mod_sysfs_fini(struct module *mod) +{ + kobject_put(&mod->mkobj.kobj); +} + +#else /* CONFIG_SYSFS */ + +static void mod_sysfs_fini(struct module *mod) +{ +} + +#endif /* CONFIG_SYSFS */ static void mod_kobject_remove(struct module *mod) { @@ -1345,7 +1357,7 @@ static void mod_kobject_remove(struct module *mod) module_param_sysfs_remove(mod); kobject_put(mod->mkobj.drivers_dir); kobject_put(mod->holders_dir); - kobject_put(&mod->mkobj.kobj); + mod_sysfs_fini(mod); } /* @@ -1780,7 +1792,7 @@ static struct module *load_module(void __user *umod, /* Sanity checks against insmoding binaries or wrong arch, weird elf version */ - if (memcmp(hdr->e_ident, ELFMAG, 4) != 0 + if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0 || hdr->e_type != ET_REL || !elf_check_arch(hdr) || hdr->e_shentsize != sizeof(*sechdrs)) { diff --git a/kernel/signal.c b/kernel/signal.c index 72bb4f51f963..12ffea7c201d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1242,7 +1242,8 @@ void sigqueue_free(struct sigqueue *q) /* * If the signal is still pending remove it from the * pending queue. We must hold ->siglock while testing - * q->list to serialize with collect_signal(). + * q->list to serialize with collect_signal() or with + * __exit_signal()->flush_sigqueue(). */ spin_lock_irqsave(lock, flags); if (!list_empty(&q->list)) diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 0101aeef7ed7..b7350bbfb076 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -62,8 +62,7 @@ static int stopmachine(void *cpu) * help our sisters onto their CPUs. */ if (!prepared && !irqs_disabled) yield(); - else - cpu_relax(); + cpu_relax(); } /* Ack: we are exiting. */ @@ -106,8 +105,10 @@ static int stop_machine(void) } /* Wait for them all to come to life. */ - while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) + while (atomic_read(&stopmachine_thread_ack) != stopmachine_num_threads) { yield(); + cpu_relax(); + } /* If some failed, kill them all. */ if (ret < 0) { diff --git a/kernel/sys.c b/kernel/sys.c index 895d2d4c9493..14e97282eb6c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1652,7 +1652,7 @@ asmlinkage long sys_umask(int mask) asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { - long uninitialized_var(error); + long error = 0; if (security_task_prctl(option, arg2, arg3, arg4, arg5, &error)) return error; @@ -1701,9 +1701,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, error = PR_TIMING_STATISTICAL; break; case PR_SET_TIMING: - if (arg2 == PR_TIMING_STATISTICAL) - error = 0; - else + if (arg2 != PR_TIMING_STATISTICAL) error = -EINVAL; break; diff --git a/mm/memory.c b/mm/memory.c index fb5608a120ed..19e0ae9beecb 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2295,8 +2295,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, vmf.flags = flags; vmf.page = NULL; - BUG_ON(vma->vm_flags & VM_PFNMAP); - ret = vma->vm_ops->fault(vma, &vmf); if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) return ret; diff --git a/mm/mmap.c b/mm/mmap.c index fac66337da2a..669499e7c2f5 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -80,7 +80,7 @@ EXPORT_SYMBOL(vm_get_page_prot); int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT; -atomic_t vm_committed_space = ATOMIC_INIT(0); +atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0); /* * Check that a process has enough memory to allocate a new virtual @@ -177,7 +177,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) * cast `allowed' as a signed long because vm_committed_space * sometimes has a negative value */ - if (atomic_read(&vm_committed_space) < (long)allowed) + if (atomic_long_read(&vm_committed_space) < (long)allowed) return 0; error: vm_unacct_memory(pages); diff --git a/mm/nommu.c b/mm/nommu.c index ef8c62cec697..dca93fcb8b7a 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -39,7 +39,7 @@ struct page *mem_map; unsigned long max_mapnr; unsigned long num_physpages; unsigned long askedalloc, realalloc; -atomic_t vm_committed_space = ATOMIC_INIT(0); +atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0); int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */ int sysctl_overcommit_ratio = 50; /* default is 50% */ int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT; @@ -1410,7 +1410,7 @@ int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin) * cast `allowed' as a signed long because vm_committed_space * sometimes has a negative value */ - if (atomic_read(&vm_committed_space) < (long)allowed) + if (atomic_long_read(&vm_committed_space) < (long)allowed) return 0; error: vm_unacct_memory(pages); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 63835579323a..8e83f02cd2d3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1396,6 +1396,9 @@ get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, (void)first_zones_zonelist(zonelist, high_zoneidx, nodemask, &preferred_zone); + if (!preferred_zone) + return NULL; + classzone_idx = zone_idx(preferred_zone); zonelist_scan: @@ -2804,7 +2807,7 @@ int zone_wait_table_init(struct zone *zone, unsigned long zone_size_pages) alloc_size = zone->wait_table_hash_nr_entries * sizeof(wait_queue_head_t); - if (system_state == SYSTEM_BOOTING) { + if (!slab_is_available()) { zone->wait_table = (wait_queue_head_t *) alloc_bootmem_node(pgdat, alloc_size); } else { @@ -3378,7 +3381,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, * is used by this zone for memmap. This affects the watermark * and per-cpu initialisations */ - memmap_pages = (size * sizeof(struct page)) >> PAGE_SHIFT; + memmap_pages = + PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT; if (realsize >= memmap_pages) { realsize -= memmap_pages; printk(KERN_DEBUG diff --git a/mm/swap.c b/mm/swap.c index 91e194445a5e..45c9f25a8a3b 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -503,7 +503,7 @@ void vm_acct_memory(long pages) local = &__get_cpu_var(committed_space); *local += pages; if (*local > ACCT_THRESHOLD || *local < -ACCT_THRESHOLD) { - atomic_add(*local, &vm_committed_space); + atomic_long_add(*local, &vm_committed_space); *local = 0; } preempt_enable(); @@ -520,7 +520,7 @@ static int cpu_swap_callback(struct notifier_block *nfb, committed = &per_cpu(committed_space, (long)hcpu); if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) { - atomic_add(*committed, &vm_committed_space); + atomic_long_add(*committed, &vm_committed_space); *committed = 0; drain_cpu_pagevecs((long)hcpu); } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 51961300b586..ab2225da0ee2 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -387,14 +387,8 @@ static void vlan_transfer_features(struct net_device *dev, { unsigned long old_features = vlandev->features; - if (dev->features & NETIF_F_VLAN_TSO) { - vlandev->features &= ~VLAN_TSO_FEATURES; - vlandev->features |= dev->features & VLAN_TSO_FEATURES; - } - if (dev->features & NETIF_F_VLAN_CSUM) { - vlandev->features &= ~NETIF_F_ALL_CSUM; - vlandev->features |= dev->features & NETIF_F_ALL_CSUM; - } + vlandev->features &= ~dev->vlan_features; + vlandev->features |= dev->features & dev->vlan_features; if (old_features != vlandev->features) netdev_features_change(vlandev); diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 79625696e86a..5229a72c7ea1 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h @@ -7,8 +7,6 @@ #define VLAN_GRP_HASH_SIZE (1 << VLAN_GRP_HASH_SHIFT) #define VLAN_GRP_HASH_MASK (VLAN_GRP_HASH_SIZE - 1) -#define VLAN_TSO_FEATURES (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG) - /* Find a VLAN device by the MAC address of its Ethernet device, and * it's VLAN ID. The default configuration is to have VLAN's scope * to be box-wide, so the MAC will be ignored. The mac will only be diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b1cfbaa88db2..5d055c242ed8 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -663,10 +663,7 @@ static int vlan_dev_init(struct net_device *dev) (1<<__LINK_STATE_DORMANT))) | (1<<__LINK_STATE_PRESENT); - if (real_dev->features & NETIF_F_VLAN_TSO) - dev->features |= real_dev->features & VLAN_TSO_FEATURES; - if (real_dev->features & NETIF_F_VLAN_CSUM) - dev->features |= real_dev->features & NETIF_F_ALL_CSUM; + dev->features |= real_dev->features & real_dev->vlan_features; /* ipv6 shared card related stuff */ dev->dev_id = real_dev->dev_id; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 418862f1bf22..9b539fa9fe18 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1288,7 +1288,6 @@ static void arp_format_neigh_entry(struct seq_file *seq, struct neighbour *n) { char hbuffer[HBUFFERLEN]; - const char hexbuf[] = "0123456789ABCDEF"; int k, j; char tbuf[16]; struct net_device *dev = n->dev; @@ -1302,8 +1301,8 @@ static void arp_format_neigh_entry(struct seq_file *seq, else { #endif for (k = 0, j = 0; k < HBUFFERLEN - 3 && j < dev->addr_len; j++) { - hbuffer[k++] = hexbuf[(n->ha[j] >> 4) & 15]; - hbuffer[k++] = hexbuf[n->ha[j] & 15]; + hbuffer[k++] = hex_asc_hi(n->ha[j]); + hbuffer[k++] = hex_asc_lo(n->ha[j]); hbuffer[k++] = ':'; } hbuffer[--k] = 0; diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 2ada033406de..4342cba4ff82 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -313,9 +313,8 @@ static void ipgre_tunnel_uninit(struct net_device *dev) static void ipgre_err(struct sk_buff *skb, u32 info) { -#ifndef I_WISH_WORLD_WERE_PERFECT -/* It is not :-( All the routers (except for Linux) return only +/* All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. @@ -398,149 +397,6 @@ static void ipgre_err(struct sk_buff *skb, u32 info) out: read_unlock(&ipgre_lock); return; -#else - struct iphdr *iph = (struct iphdr*)dp; - struct iphdr *eiph; - __be16 *p = (__be16*)(dp+(iph->ihl<<2)); - const int type = icmp_hdr(skb)->type; - const int code = icmp_hdr(skb)->code; - int rel_type = 0; - int rel_code = 0; - __be32 rel_info = 0; - __u32 n = 0; - __be16 flags; - int grehlen = (iph->ihl<<2) + 4; - struct sk_buff *skb2; - struct flowi fl; - struct rtable *rt; - - if (p[1] != htons(ETH_P_IP)) - return; - - flags = p[0]; - if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { - if (flags&(GRE_VERSION|GRE_ROUTING)) - return; - if (flags&GRE_CSUM) - grehlen += 4; - if (flags&GRE_KEY) - grehlen += 4; - if (flags&GRE_SEQ) - grehlen += 4; - } - if (len < grehlen + sizeof(struct iphdr)) - return; - eiph = (struct iphdr*)(dp + grehlen); - - switch (type) { - default: - return; - case ICMP_PARAMETERPROB: - n = ntohl(icmp_hdr(skb)->un.gateway) >> 24; - if (n < (iph->ihl<<2)) - return; - - /* So... This guy found something strange INSIDE encapsulated - packet. Well, he is fool, but what can we do ? - */ - rel_type = ICMP_PARAMETERPROB; - n -= grehlen; - rel_info = htonl(n << 24); - break; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return; - case ICMP_FRAG_NEEDED: - /* And it is the only really necessary thing :-) */ - n = ntohs(icmp_hdr(skb)->un.frag.mtu); - if (n < grehlen+68) - return; - n -= grehlen; - /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ - if (n > ntohs(eiph->tot_len)) - return; - rel_info = htonl(n); - break; - default: - /* All others are translated to HOST_UNREACH. - rfc2003 contains "deep thoughts" about NET_UNREACH, - I believe, it is just ether pollution. --ANK - */ - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return; - break; - } - - /* Prepare fake skb to feed it to icmp_send */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - return; - dst_release(skb2->dst); - skb2->dst = NULL; - skb_pull(skb2, skb->data - (u8*)eiph); - skb_reset_network_header(skb2); - - /* Try to guess incoming interface */ - memset(&fl, 0, sizeof(fl)); - fl.fl4_dst = eiph->saddr; - fl.fl4_tos = RT_TOS(eiph->tos); - fl.proto = IPPROTO_GRE; - if (ip_route_output_key(dev_net(skb->dev), &rt, &fl)) { - kfree_skb(skb2); - return; - } - skb2->dev = rt->u.dst.dev; - - /* route "incoming" packet */ - if (rt->rt_flags&RTCF_LOCAL) { - ip_rt_put(rt); - rt = NULL; - fl.fl4_dst = eiph->daddr; - fl.fl4_src = eiph->saddr; - fl.fl4_tos = eiph->tos; - if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || - rt->u.dst.dev->type != ARPHRD_IPGRE) { - ip_rt_put(rt); - kfree_skb(skb2); - return; - } - } else { - ip_rt_put(rt); - if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || - skb2->dst->dev->type != ARPHRD_IPGRE) { - kfree_skb(skb2); - return; - } - } - - /* change mtu on this route */ - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - if (n > dst_mtu(skb2->dst)) { - kfree_skb(skb2); - return; - } - skb2->dst->ops->update_pmtu(skb2->dst, n); - } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = netdev_priv(skb2->dev); - if (t->parms.iph.ttl) { - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - } - } - - icmp_send(skb2, rel_type, rel_code, rel_info); - kfree_skb(skb2); -#endif } static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 149111f08e8d..af5cb53da5cc 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -278,9 +278,8 @@ static void ipip_tunnel_uninit(struct net_device *dev) static int ipip_err(struct sk_buff *skb, u32 info) { -#ifndef I_WISH_WORLD_WERE_PERFECT -/* It is not :-( All the routers (except for Linux) return only +/* All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ @@ -337,133 +336,6 @@ static int ipip_err(struct sk_buff *skb, u32 info) out: read_unlock(&ipip_lock); return err; -#else - struct iphdr *iph = (struct iphdr*)dp; - int hlen = iph->ihl<<2; - struct iphdr *eiph; - const int type = icmp_hdr(skb)->type; - const int code = icmp_hdr(skb)->code; - int rel_type = 0; - int rel_code = 0; - __be32 rel_info = 0; - __u32 n = 0; - struct sk_buff *skb2; - struct flowi fl; - struct rtable *rt; - - if (len < hlen + sizeof(struct iphdr)) - return 0; - eiph = (struct iphdr*)(dp + hlen); - - switch (type) { - default: - return 0; - case ICMP_PARAMETERPROB: - n = ntohl(icmp_hdr(skb)->un.gateway) >> 24; - if (n < hlen) - return 0; - - /* So... This guy found something strange INSIDE encapsulated - packet. Well, he is fool, but what can we do ? - */ - rel_type = ICMP_PARAMETERPROB; - rel_info = htonl((n - hlen) << 24); - break; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return 0; - case ICMP_FRAG_NEEDED: - /* And it is the only really necessary thing :-) */ - n = ntohs(icmp_hdr(skb)->un.frag.mtu); - if (n < hlen+68) - return 0; - n -= hlen; - /* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */ - if (n > ntohs(eiph->tot_len)) - return 0; - rel_info = htonl(n); - break; - default: - /* All others are translated to HOST_UNREACH. - rfc2003 contains "deep thoughts" about NET_UNREACH, - I believe, it is just ether pollution. --ANK - */ - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return 0; - break; - } - - /* Prepare fake skb to feed it to icmp_send */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - return 0; - dst_release(skb2->dst); - skb2->dst = NULL; - skb_pull(skb2, skb->data - (u8*)eiph); - skb_reset_network_header(skb2); - - /* Try to guess incoming interface */ - memset(&fl, 0, sizeof(fl)); - fl.fl4_daddr = eiph->saddr; - fl.fl4_tos = RT_TOS(eiph->tos); - fl.proto = IPPROTO_IPIP; - if (ip_route_output_key(dev_net(skb->dev), &rt, &key)) { - kfree_skb(skb2); - return 0; - } - skb2->dev = rt->u.dst.dev; - - /* route "incoming" packet */ - if (rt->rt_flags&RTCF_LOCAL) { - ip_rt_put(rt); - rt = NULL; - fl.fl4_daddr = eiph->daddr; - fl.fl4_src = eiph->saddr; - fl.fl4_tos = eiph->tos; - if (ip_route_output_key(dev_net(skb->dev), &rt, &fl) || - rt->u.dst.dev->type != ARPHRD_TUNNEL) { - ip_rt_put(rt); - kfree_skb(skb2); - return 0; - } - } else { - ip_rt_put(rt); - if (ip_route_input(skb2, eiph->daddr, eiph->saddr, eiph->tos, skb2->dev) || - skb2->dst->dev->type != ARPHRD_TUNNEL) { - kfree_skb(skb2); - return 0; - } - } - - /* change mtu on this route */ - if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) { - if (n > dst_mtu(skb2->dst)) { - kfree_skb(skb2); - return 0; - } - skb2->dst->ops->update_pmtu(skb2->dst, n); - } else if (type == ICMP_TIME_EXCEEDED) { - struct ip_tunnel *t = netdev_priv(skb2->dev); - if (t->parms.iph.ttl) { - rel_type = ICMP_DEST_UNREACH; - rel_code = ICMP_HOST_UNREACH; - } - } - - icmp_send(skb2, rel_type, rel_code, rel_info); - kfree_skb(skb2); - return 0; -#endif } static inline void ipip_ecn_decapsulate(const struct iphdr *outer_iph, diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index debf23581606..e399bde7813a 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1836,7 +1836,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); - unsigned int cur_mss = tcp_current_mss(sk, 0); + unsigned int cur_mss; int err; /* Inconslusive MTU probe */ @@ -1858,6 +1858,11 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) return -ENOMEM; } + if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) + return -EHOSTUNREACH; /* Routing failure or similar. */ + + cur_mss = tcp_current_mss(sk, 0); + /* If receiver has shrunk his window, and skb is out of * new window, do not retransmit it. The exception is the * case, when window is shrunk to zero. In this case @@ -1884,9 +1889,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) (sysctl_tcp_retrans_collapse != 0)) tcp_retrans_try_collapse(sk, skb, cur_mss); - if (inet_csk(sk)->icsk_af_ops->rebuild_header(sk)) - return -EHOSTUNREACH; /* Routing failure or similar. */ - /* Some Solaris stacks overoptimize and ignore the FIN on a * retransmit when old data is attached. So strip it off * since it is cheap to do so and saves bytes on the network. diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 5a6fab95569f..3de6ffdaedf2 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -403,9 +403,8 @@ static void ipip6_tunnel_uninit(struct net_device *dev) static int ipip6_err(struct sk_buff *skb, u32 info) { -#ifndef I_WISH_WORLD_WERE_PERFECT -/* It is not :-( All the routers (except for Linux) return only +/* All the routers (except for Linux) return only 8 bytes of packet payload. It means, that precise relaying of ICMP in the real Internet is absolutely infeasible. */ @@ -462,92 +461,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info) out: read_unlock(&ipip6_lock); return err; -#else - struct iphdr *iph = (struct iphdr*)dp; - int hlen = iph->ihl<<2; - struct ipv6hdr *iph6; - const int type = icmp_hdr(skb)->type; - const int code = icmp_hdr(skb)->code; - int rel_type = 0; - int rel_code = 0; - int rel_info = 0; - struct sk_buff *skb2; - struct rt6_info *rt6i; - - if (len < hlen + sizeof(struct ipv6hdr)) - return; - iph6 = (struct ipv6hdr*)(dp + hlen); - - switch (type) { - default: - return; - case ICMP_PARAMETERPROB: - if (icmp_hdr(skb)->un.gateway < hlen) - return; - - /* So... This guy found something strange INSIDE encapsulated - packet. Well, he is fool, but what can we do ? - */ - rel_type = ICMPV6_PARAMPROB; - rel_info = icmp_hdr(skb)->un.gateway - hlen; - break; - - case ICMP_DEST_UNREACH: - switch (code) { - case ICMP_SR_FAILED: - case ICMP_PORT_UNREACH: - /* Impossible event. */ - return; - case ICMP_FRAG_NEEDED: - /* Too complicated case ... */ - return; - default: - /* All others are translated to HOST_UNREACH. - rfc2003 contains "deep thoughts" about NET_UNREACH, - I believe, it is just ether pollution. --ANK - */ - rel_type = ICMPV6_DEST_UNREACH; - rel_code = ICMPV6_ADDR_UNREACH; - break; - } - break; - case ICMP_TIME_EXCEEDED: - if (code != ICMP_EXC_TTL) - return; - rel_type = ICMPV6_TIME_EXCEED; - rel_code = ICMPV6_EXC_HOPLIMIT; - break; - } - - /* Prepare fake skb to feed it to icmpv6_send */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - return 0; - dst_release(skb2->dst); - skb2->dst = NULL; - skb_pull(skb2, skb->data - (u8*)iph6); - skb_reset_network_header(skb2); - - /* Try to guess incoming interface */ - rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0); - if (rt6i && rt6i->rt6i_dev) { - skb2->dev = rt6i->rt6i_dev; - - rt6i = rt6_lookup(dev_net(skb->dev), - &iph6->daddr, &iph6->saddr, NULL, 0); - - if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { - struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); - if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { - rel_type = ICMPV6_DEST_UNREACH; - rel_code = ICMPV6_ADDR_UNREACH; - } - icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); - } - } - kfree_skb(skb2); - return 0; -#endif } static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) diff --git a/net/key/af_key.c b/net/key/af_key.c index 9e7236ff6bcc..9bba7ac5fee0 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1251,7 +1251,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, x->sel.prefixlen_s = addr->sadb_address_prefixlen; } - if (x->props.mode == XFRM_MODE_TRANSPORT) + if (!x->sel.family) x->sel.family = x->props.family; if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) { diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e470bf12b765..7cfd12e0d1e2 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -730,7 +730,17 @@ static void ieee80211_send_assoc(struct net_device *dev, if (bss->wmm_ie) { wmm = 1; } + + /* get all rates supported by the device and the AP as + * some APs don't like getting a superset of their rates + * in the association request (e.g. D-Link DAP 1353 in + * b-only mode) */ + rates_len = ieee80211_compatible_rates(bss, sband, &rates); + ieee80211_rx_bss_put(dev, bss); + } else { + rates = ~0; + rates_len = sband->n_bitrates; } mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); @@ -761,10 +771,7 @@ static void ieee80211_send_assoc(struct net_device *dev, *pos++ = ifsta->ssid_len; memcpy(pos, ifsta->ssid, ifsta->ssid_len); - /* all supported rates should be added here but some APs - * (e.g. D-Link DAP 1353 in b-only mode) don't like that - * Therefore only add rates the AP supports */ - rates_len = ieee80211_compatible_rates(bss, sband, &rates); + /* add all rates which were marked to be used above */ supp_rates_len = rates_len; if (supp_rates_len > 8) supp_rates_len = 8; diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 76e1de1dc735..457ebf9e85ae 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -209,7 +209,6 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev, range->num_frequency = c; IW_EVENT_CAPA_SET_KERNEL(range->event_capa); - IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY); IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index a1b0fbe3ea35..b976d9ed10e4 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -50,19 +50,8 @@ static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) switch (type) { case XFRMA_ALG_AUTH: - if (!algp->alg_key_len && - strcmp(algp->alg_name, "digest_null") != 0) - return -EINVAL; - break; - case XFRMA_ALG_CRYPT: - if (!algp->alg_key_len && - strcmp(algp->alg_name, "cipher_null") != 0) - return -EINVAL; - break; - case XFRMA_ALG_COMP: - /* Zero length keys are legal. */ break; default: diff --git a/scripts/ver_linux b/scripts/ver_linux index ab69ecefedbd..7ac0e309be09 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -12,12 +12,9 @@ echo ' ' uname -a echo ' ' -gcc --version 2>&1| head -n 1 | grep -v gcc | awk \ +gcc -dumpversion 2>&1| awk \ 'NR==1{print "Gnu C ", $1}' -gcc --version 2>&1| grep gcc | awk \ -'NR==1{print "Gnu C ", $3}' - make --version 2>&1 | awk -F, '{print $1}' | awk \ '/GNU Make/{print "Gnu make ",$NF}' diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index f07cc1ee1fe7..1d661f795e8c 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h @@ -24,7 +24,8 @@ static DEFINE_SPINLOCK(i8253_lock); /* default timer freq for PC-Speaker: 18643 Hz */ #define DIV_18KHZ 64 #define MAX_DIV DIV_18KHZ -#define CUR_DIV() (MAX_DIV >> chip->treble) +#define CALC_DIV(d) (MAX_DIV >> (d)) +#define CUR_DIV() CALC_DIV(chip->treble) #define PCSP_MAX_TREBLE 1 /* unfortunately, with hrtimers 37KHz does not work very well :( */ @@ -36,7 +37,8 @@ static DEFINE_SPINLOCK(i8253_lock); #define PCSP_DEFAULT_SDIV (DIV_18KHZ >> 1) #define PCSP_DEFAULT_SRATE (PIT_TICK_RATE / PCSP_DEFAULT_SDIV) #define PCSP_INDEX_INC() (1 << (PCSP_MAX_TREBLE - chip->treble)) -#define PCSP_RATE() (PIT_TICK_RATE / CUR_DIV()) +#define PCSP_CALC_RATE(i) (PIT_TICK_RATE / CALC_DIV(i)) +#define PCSP_RATE() PCSP_CALC_RATE(chip->treble) #define PCSP_MIN_RATE__1 MAX_DIV/PIT_TICK_RATE #define PCSP_MAX_RATE__1 MIN_DIV/PIT_TICK_RATE #define PCSP_MAX_PERIOD_NS (1000000000ULL * PCSP_MIN_RATE__1) diff --git a/sound/drivers/pcsp/pcsp_mixer.c b/sound/drivers/pcsp/pcsp_mixer.c index 64a695fef74e..caeb0f57fcca 100644 --- a/sound/drivers/pcsp/pcsp_mixer.c +++ b/sound/drivers/pcsp/pcsp_mixer.c @@ -50,7 +50,8 @@ static int pcsp_treble_info(struct snd_kcontrol *kcontrol, uinfo->value.enumerated.items = chip->max_treble + 1; if (uinfo->value.enumerated.item > chip->max_treble) uinfo->value.enumerated.item = chip->max_treble; - sprintf(uinfo->value.enumerated.name, "%d", PCSP_RATE()); + sprintf(uinfo->value.enumerated.name, "%d", + PCSP_CALC_RATE(uinfo->value.enumerated.item)); return 0; } diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index e0a605adde42..ff1b922c610b 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2858,6 +2858,7 @@ static const char *ad1988_models[AD1988_MODEL_LAST] = { static struct snd_pci_quirk ad1988_cfg_tbl[] = { SND_PCI_QUIRK(0x1043, 0x81ec, "Asus P5B-DLX", AD1988_6STACK_DIG), SND_PCI_QUIRK(0x1043, 0x81f6, "Asus M2N-SLI", AD1988_6STACK_DIG), + SND_PCI_QUIRK(0x1043, 0x8277, "Asus P5K-E/WIFI-AP", AD1988_6STACK_DIG), {} }; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 864b2f598c38..8f31247c52bd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -853,6 +853,7 @@ do_sku: case 0x10ec0269: case 0x10ec0862: case 0x10ec0662: + case 0x10ec0889: snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_EAPD_BTLENABLE, 2); snd_hda_codec_write(codec, 0x15, 0, @@ -877,6 +878,7 @@ do_sku: case 0x10ec0883: case 0x10ec0885: case 0x10ec0888: + case 0x10ec0889: snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, 7); tmp = snd_hda_codec_read(codec, 0x20, 0, @@ -7743,6 +7745,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), + SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC), SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 393f7fd2b1be..a4f44a00bae8 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -840,7 +840,7 @@ static struct snd_kcontrol_new stac92hd71bxx_mixer[] = { static struct snd_kcontrol_new stac925x_mixer[] = { STAC_INPUT_SOURCE(1), HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT), - HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x14, 0, HDA_OUTPUT), HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT), { } /* end */ }; diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 52b1d81a26f7..e7e43524f8c7 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -447,6 +447,23 @@ static struct hda_pcm_stream vt1708_pcm_analog_playback = { }, }; +static struct hda_pcm_stream vt1708_pcm_analog_s16_playback = { + .substreams = 1, + .channels_min = 2, + .channels_max = 8, + .nid = 0x10, /* NID to query formats and rates */ + /* We got noisy outputs on the right channel on VT1708 when + * 24bit samples are used. Until any workaround is found, + * disable the 24bit format, so far. + */ + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .ops = { + .open = via_playback_pcm_open, + .prepare = via_playback_pcm_prepare, + .cleanup = via_playback_pcm_cleanup + }, +}; + static struct hda_pcm_stream vt1708_pcm_analog_capture = { .substreams = 2, .channels_min = 2, @@ -899,6 +916,9 @@ static int patch_vt1708(struct hda_codec *codec) spec->stream_name_analog = "VT1708 Analog"; spec->stream_analog_playback = &vt1708_pcm_analog_playback; + /* disable 32bit format on VT1708 */ + if (codec->vendor_id == 0x11061708) + spec->stream_analog_playback = &vt1708_pcm_analog_s16_playback; spec->stream_analog_capture = &vt1708_pcm_analog_capture; spec->stream_name_digital = "VT1708 Digital"; |