From 485ae77dc7f484563707557ccf8c5d228980619f Mon Sep 17 00:00:00 2001 From: Sven Anders Date: Thu, 24 Aug 2006 17:11:50 +0200 Subject: [WATCHDOG] Winbond SMsC37B787 watchdog driver New watchdog driver for the Winbond SMsC37B787 chipset. Signed-off-by: Sven Anders Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 20 ++ drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/smsc37b787_wdt.c | 614 +++++++++++++++++++++++++++++++++ 3 files changed, 635 insertions(+) create mode 100644 drivers/char/watchdog/smsc37b787_wdt.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 89e46d6dfc4e..8d2ebc73c894 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -395,6 +395,26 @@ config CPU5_WDT To compile this driver as a module, choose M here: the module will be called cpu5wdt. +config SMSC37B787_WDT + tristate "Winbond SMsC37B787 Watchdog Timer" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog component on the + Winbond SMsC37B787 chipset as used on the NetRunner Mainboard + from Vision Systems and maybe others. + + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. + + Usually a userspace daemon will notify the kernel WDT driver that + userspace is still alive, at regular intervals. + + To compile this driver as a module, choose M here: the + module will be called smsc37b787_wdt. + + Most people will say N. + config W83627HF_WDT tristate "W83627HF Watchdog Timer" depends on WATCHDOG && X86 diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 7f70abad465a..630526f12376 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_SBC8360_WDT) += sbc8360.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o +obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c new file mode 100644 index 000000000000..47141c0b6f25 --- /dev/null +++ b/drivers/char/watchdog/smsc37b787_wdt.c @@ -0,0 +1,614 @@ +/* + * SMsC 37B787 Watchdog Timer driver for Linux 2.6.x.x + * + * Based on acquirewdt.c by Alan Cox + * and some other existing drivers + * + * 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. + * + * The authors do NOT admit liability nor provide warranty for + * any of this software. This material is provided "AS-IS" in + * the hope that it may be useful for others. + * + * (C) Copyright 2003-2006 Sven Anders + * + * History: + * 2003 - Created version 1.0 for Linux 2.4.x. + * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE + * features. Released version 1.1 + * + * Theory of operation: + * + * A Watchdog Timer (WDT) is a hardware circuit that can + * reset the computer system in case of a software fault. + * You probably knew that already. + * + * Usually a userspace daemon will notify the kernel WDT driver + * via the /dev/watchdog special device file that userspace is + * still alive, at regular intervals. When such a notification + * occurs, the driver will usually tell the hardware watchdog + * that everything is in order, and that the watchdog should wait + * for yet another little while to reset the system. + * If userspace fails (RAM error, kernel bug, whatever), the + * notifications cease to occur, and the hardware watchdog will + * reset the system (causing a reboot) after the timeout occurs. + * + * Create device with: + * mknod /dev/watchdog c 10 130 + * + * For an example userspace keep-alive daemon, see: + * Documentation/watchdog/watchdog.txt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* enable support for minutes as units? */ +/* (does not always work correctly, so disabled by default!) */ +#define SMSC_SUPPORT_MINUTES +#undef SMSC_SUPPORT_MINUTES + +#define MAX_TIMEOUT 255 + +#define UNIT_SECOND 0 +#define UNIT_MINUTE 1 + +#define MODNAME "smsc37b787_wdt: " +#define VERSION "1.1" + +#define WATCHDOG_MINOR 130 + +#define IOPORT 0x3F0 +#define IOPORT_SIZE 2 +#define IODEV_NO 8 + +static int unit = UNIT_SECOND; /* timer's unit */ +static int timeout = 60; /* timeout value: default is 60 "units" */ +static int timer_enabled = 0; /* is the timer enabled? */ + +static char expect_close; /* is the close expected? */ + +static int nowayout = WATCHDOG_NOWAYOUT; + +/* -- Low level function ----------------------------------------*/ + +/* unlock the IO chip */ + +static inline void open_io_config(void) +{ + outb(0x55, IOPORT); + mdelay(1); + outb(0x55, IOPORT); +} + +/* lock the IO chip */ +static inline void close_io_config(void) +{ + outb(0xAA, IOPORT); +} + +/* select the IO device */ +static inline void select_io_device(unsigned char devno) +{ + outb(0x07, IOPORT); + outb(devno, IOPORT+1); +} + +/* write to the control register */ +static inline void write_io_cr(unsigned char reg, unsigned char data) +{ + outb(reg, IOPORT); + outb(data, IOPORT+1); +} + +/* read from the control register */ +static inline char read_io_cr(unsigned char reg) +{ + outb(reg, IOPORT); + return inb(IOPORT+1); +} + +/* -- Medium level functions ------------------------------------*/ + +static inline void gpio_bit12(unsigned char reg) +{ + // -- General Purpose I/O Bit 1.2 -- + // Bit 0, In/Out: 0 = Output, 1 = Input + // Bit 1, Polarity: 0 = No Invert, 1 = Invert + // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable + // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17, + // 11 = Either Edge Triggered Intr. 2 + // Bit 5/6 (Reserved) + // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain + write_io_cr(0xE2, reg); +} + +static inline void gpio_bit13(unsigned char reg) +{ + // -- General Purpose I/O Bit 1.3 -- + // Bit 0, In/Out: 0 = Output, 1 = Input + // Bit 1, Polarity: 0 = No Invert, 1 = Invert + // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable + // Bit 3, Function select: 0 = GPI/O, 1 = LED + // Bit 4-6 (Reserved) + // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain + write_io_cr(0xE3, reg); +} + +static inline void wdt_timer_units(unsigned char new_units) +{ + // -- Watchdog timer units -- + // Bit 0-6 (Reserved) + // Bit 7, WDT Time-out Value Units Select + // (0 = Minutes, 1 = Seconds) + write_io_cr(0xF1, new_units); +} + +static inline void wdt_timeout_value(unsigned char new_timeout) +{ + // -- Watchdog Timer Time-out Value -- + // Bit 0-7 Binary coded units (0=Disabled, 1..255) + write_io_cr(0xF2, new_timeout); +} + +static inline void wdt_timer_conf(unsigned char conf) +{ + // -- Watchdog timer configuration -- + // Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O + // Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr. + // Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr. + // Bit 3 Reset the timer + // (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled) + // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled, + // 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15) + write_io_cr(0xF3, conf); +} + +static inline void wdt_timer_ctrl(unsigned char reg) +{ + // -- Watchdog timer control -- + // Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured + // Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz + // Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) + // Bit 3 P20 Force Timeout enabled: + // 0 = P20 activity does not generate the WD timeout event + // 1 = P20 Allows rising edge of P20, from the keyboard + // controller, to force the WD timeout event. + // Bit 4 (Reserved) + // -- Soft power management -- + // Bit 5 Stop Counter: 1 = Stop software power down counter + // set via register 0xB8, (self-cleaning) + // (Upon read: 0 = Counter running, 1 = Counter stopped) + // Bit 6 Restart Counter: 1 = Restart software power down counter + // set via register 0xB8, (self-cleaning) + // Bit 7 SPOFF: 1 = Force software power down (self-cleaning) + + write_io_cr(0xF4, reg); +} + +/* -- Higher level functions ------------------------------------*/ + +/* initialize watchdog */ + +static void wb_smsc_wdt_initialize(void) +{ + unsigned char old; + + open_io_config(); + select_io_device(IODEV_NO); + + // enable the watchdog + gpio_bit13(0x08); // Select pin 80 = LED not GPIO + gpio_bit12(0x0A); // Set pin 79 = WDT not GPIO/Output/Polarity=Invert + + // disable the timeout + wdt_timeout_value(0); + + // reset control register + wdt_timer_ctrl(0x00); + + // reset configuration register + wdt_timer_conf(0x00); + + // read old (timer units) register + old = read_io_cr(0xF1) & 0x7F; + if (unit == UNIT_SECOND) old |= 0x80; // set to seconds + + // set the watchdog timer units + wdt_timer_units(old); + + close_io_config(); +} + +/* shutdown the watchdog */ + +static void wb_smsc_wdt_shutdown(void) +{ + open_io_config(); + select_io_device(IODEV_NO); + + // disable the watchdog + gpio_bit13(0x09); + gpio_bit12(0x09); + + // reset watchdog config register + wdt_timer_conf(0x00); + + // reset watchdog control register + wdt_timer_ctrl(0x00); + + // disable timeout + wdt_timeout_value(0x00); + + close_io_config(); +} + +/* set timeout => enable watchdog */ + +static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) +{ + open_io_config(); + select_io_device(IODEV_NO); + + // set Power LED to blink, if we enable the timeout + wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02); + + // set timeout value + wdt_timeout_value(new_timeout); + + close_io_config(); +} + +/* get timeout */ + +static unsigned char wb_smsc_wdt_get_timeout(void) +{ + unsigned char set_timeout; + + open_io_config(); + select_io_device(IODEV_NO); + set_timeout = read_io_cr(0xF2); + close_io_config(); + + return set_timeout; +} + +/* disable watchdog */ + +static void wb_smsc_wdt_disable(void) +{ + // set the timeout to 0 to disable the watchdog + wb_smsc_wdt_set_timeout(0); +} + +/* enable watchdog by setting the current timeout */ + +static void wb_smsc_wdt_enable(void) +{ + // set the current timeout... + wb_smsc_wdt_set_timeout(timeout); +} + +/* reset the timer */ + +static void wb_smsc_wdt_reset_timer(void) +{ + open_io_config(); + select_io_device(IODEV_NO); + + // reset the timer + wdt_timeout_value(timeout); + wdt_timer_conf(0x08); + + close_io_config(); +} + +/* return, if the watchdog is enabled (timeout is set...) */ + +static int wb_smsc_wdt_status(void) +{ + return (wb_smsc_wdt_get_timeout() == 0) ? 0 : WDIOF_KEEPALIVEPING; +} + + +/* -- File operations -------------------------------------------*/ + +/* open => enable watchdog and set initial timeout */ + +static int wb_smsc_wdt_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + + if (timer_enabled) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); + + /* Reload and activate timer */ + timer_enabled = 1; + wb_smsc_wdt_enable(); + + printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); + + return nonseekable_open(inode, file); +} + +/* close => shut off the timer */ + +static int wb_smsc_wdt_release(struct inode *inode, struct file *file) +{ + /* Shut off the timer. */ + + if (expect_close == 42) { + wb_smsc_wdt_disable(); + printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n"); + } else { + printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n"); + wb_smsc_wdt_reset_timer(); + } + + timer_enabled = 0; + expect_close = 0; + return 0; +} + +/* write => update the timer to keep the machine alive */ + +static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) +{ + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* reset expect flag */ + expect_close = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + wb_smsc_wdt_reset_timer(); + } + return len; +} + +/* ioctl => control interface */ + +static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int new_timeout; + + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "SMsC 37B787 Watchdog" + }; + + uarg.i = (int __user *)arg; + + switch (cmd) { + default: + return -ENOTTY; + + case WDIOC_GETSUPPORT: + return copy_to_user(uarg.ident, &ident, sizeof(ident)); + + case WDIOC_GETSTATUS: + return put_user(wb_smsc_wdt_status(), uarg.i); + + case WDIOC_GETBOOTSTATUS: + return put_user(0, uarg.i); + + case WDIOC_KEEPALIVE: + wb_smsc_wdt_reset_timer(); + return 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; + + // the API states this is given in secs + if (unit == UNIT_MINUTE) + new_timeout /= 60; + + if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) + return -EINVAL; + + timeout = new_timeout; + wb_smsc_wdt_set_timeout(timeout); + + // fall through and return the new timeout... + + case WDIOC_GETTIMEOUT: + + new_timeout = timeout; + + if (unit == UNIT_MINUTE) + new_timeout *= 60; + + return put_user(new_timeout, uarg.i); + + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, uarg.i)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + wb_smsc_wdt_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + wb_smsc_wdt_enable(); + retval = 0; + } + + return retval; + } + } +} + +/* -- Notifier funtions -----------------------------------------*/ + +static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) + { + // set timeout to 0, to avoid possible race-condition + timeout = 0; + wb_smsc_wdt_disable(); + } + return NOTIFY_DONE; +} + +/* -- Module's structures ---------------------------------------*/ + +static struct file_operations wb_smsc_wdt_fops = +{ + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wb_smsc_wdt_write, + .ioctl = wb_smsc_wdt_ioctl, + .open = wb_smsc_wdt_open, + .release = wb_smsc_wdt_release +}; + +static struct notifier_block wb_smsc_wdt_notifier = +{ + .notifier_call = wb_smsc_wdt_notify_sys +}; + +static struct miscdevice wb_smsc_wdt_miscdev = +{ + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wb_smsc_wdt_fops, +}; + +/* -- Module init functions -------------------------------------*/ + +/* module's "constructor" */ + +static int __init wb_smsc_wdt_init(void) +{ + int ret; + + printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); + + if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { + printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT); + ret = -EBUSY; + goto out_pnp; + } + + ret = register_reboot_notifier(&wb_smsc_wdt_notifier); + if (ret) { + printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret); + goto out_io; + } + + ret = misc_register(&wb_smsc_wdt_miscdev); + if (ret) { + printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); + goto out_rbt; + } + + // init the watchdog timer + wb_smsc_wdt_initialize(); + + // set new maximum, if it's too big + if (timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; + + // output info + printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); + printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); + + // ret = 0 + +out_clean: + return ret; + +out_rbt: + unregister_reboot_notifier(&wb_smsc_wdt_notifier); + +out_io: + release_region(IOPORT, IOPORT_SIZE); + +out_pnp: + goto out_clean; +} + +/* module's "destructor" */ + +static void __exit wb_smsc_wdt_exit(void) +{ + /* Stop the timer before we leave */ + if (!nowayout) + { + wb_smsc_wdt_shutdown(); + printk(KERN_INFO MODNAME "Watchdog disabled.\n"); + } + + misc_deregister(&wb_smsc_wdt_miscdev); + unregister_reboot_notifier(&wb_smsc_wdt_notifier); + release_region(IOPORT, IOPORT_SIZE); + + printk("SMsC 37B787 watchdog component driver removed.\n"); +} + +module_init(wb_smsc_wdt_init); +module_exit(wb_smsc_wdt_exit); + +MODULE_AUTHOR("Sven Anders "); +MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")"); +MODULE_LICENSE("GPL"); + +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + +#ifdef SMSC_SUPPORT_MINUTES +module_param(unit, int, 0); +MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); +#endif + +module_param(timeout, int, 60); +MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -- cgit v1.2.3 From 8386c8cfb2131b2a9caae3db6bf94292bbbe1caf Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 2 Sep 2006 19:32:26 +0200 Subject: [WATCHDOG] Winbond SMsC37B787 - remove trailing whitespace Remove trailing whitespace. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/smsc37b787_wdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index 47141c0b6f25..1d01b3074db3 100644 --- a/drivers/char/watchdog/smsc37b787_wdt.c +++ b/drivers/char/watchdog/smsc37b787_wdt.c @@ -8,7 +8,7 @@ * 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. - * + * * The authors do NOT admit liability nor provide warranty for * any of this software. This material is provided "AS-IS" in * the hope that it may be useful for others. @@ -422,7 +422,7 @@ static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, switch (cmd) { default: - return -ENOTTY; + return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user(uarg.ident, &ident, sizeof(ident)); @@ -573,7 +573,7 @@ out_io: out_pnp: goto out_clean; -} +} /* module's "destructor" */ -- cgit v1.2.3 From aa1fd4d7c3b131026bf156da40fdf94bcbd705aa Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 2 Sep 2006 20:53:19 +0200 Subject: [WATCHDOG] Winbond SMsC37B787 watchdog fixes * Added io spinlocking * Deleted WATCHDOG_MINOR (it's in the miscdevice include * Changed timer_enabled to use set_bit functions * WDIOC_GETSUPPORT should return -EFAULT or 0 * timeout should be correct before we initialize the watchdog * we should initialize the watchdog before we give access to userspace * Third parameter of module_param is not the default or initial value Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/smsc37b787_wdt.c | 47 ++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/smsc37b787_wdt.c b/drivers/char/watchdog/smsc37b787_wdt.c index 1d01b3074db3..9f56913b484f 100644 --- a/drivers/char/watchdog/smsc37b787_wdt.c +++ b/drivers/char/watchdog/smsc37b787_wdt.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -72,18 +73,18 @@ #define MODNAME "smsc37b787_wdt: " #define VERSION "1.1" -#define WATCHDOG_MINOR 130 - #define IOPORT 0x3F0 #define IOPORT_SIZE 2 #define IODEV_NO 8 static int unit = UNIT_SECOND; /* timer's unit */ static int timeout = 60; /* timeout value: default is 60 "units" */ -static int timer_enabled = 0; /* is the timer enabled? */ +static unsigned long timer_enabled = 0; /* is the timer enabled? */ static char expect_close; /* is the close expected? */ +static spinlock_t io_lock; /* to guard the watchdog from io races */ + static int nowayout = WATCHDOG_NOWAYOUT; /* -- Low level function ----------------------------------------*/ @@ -210,6 +211,7 @@ static void wb_smsc_wdt_initialize(void) { unsigned char old; + spin_lock(&io_lock); open_io_config(); select_io_device(IODEV_NO); @@ -234,12 +236,14 @@ static void wb_smsc_wdt_initialize(void) wdt_timer_units(old); close_io_config(); + spin_unlock(&io_lock); } /* shutdown the watchdog */ static void wb_smsc_wdt_shutdown(void) { + spin_lock(&io_lock); open_io_config(); select_io_device(IODEV_NO); @@ -257,12 +261,14 @@ static void wb_smsc_wdt_shutdown(void) wdt_timeout_value(0x00); close_io_config(); + spin_unlock(&io_lock); } /* set timeout => enable watchdog */ static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) { + spin_lock(&io_lock); open_io_config(); select_io_device(IODEV_NO); @@ -273,6 +279,7 @@ static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) wdt_timeout_value(new_timeout); close_io_config(); + spin_unlock(&io_lock); } /* get timeout */ @@ -281,10 +288,12 @@ static unsigned char wb_smsc_wdt_get_timeout(void) { unsigned char set_timeout; + spin_lock(&io_lock); open_io_config(); select_io_device(IODEV_NO); set_timeout = read_io_cr(0xF2); close_io_config(); + spin_unlock(&io_lock); return set_timeout; } @@ -309,6 +318,7 @@ static void wb_smsc_wdt_enable(void) static void wb_smsc_wdt_reset_timer(void) { + spin_lock(&io_lock); open_io_config(); select_io_device(IODEV_NO); @@ -317,6 +327,7 @@ static void wb_smsc_wdt_reset_timer(void) wdt_timer_conf(0x08); close_io_config(); + spin_unlock(&io_lock); } /* return, if the watchdog is enabled (timeout is set...) */ @@ -335,14 +346,13 @@ static int wb_smsc_wdt_open(struct inode *inode, struct file *file) { /* /dev/watchdog can only be opened once */ - if (timer_enabled) + if (test_and_set_bit(0, &timer_enabled)) return -EBUSY; if (nowayout) __module_get(THIS_MODULE); /* Reload and activate timer */ - timer_enabled = 1; wb_smsc_wdt_enable(); printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); @@ -364,7 +374,7 @@ static int wb_smsc_wdt_release(struct inode *inode, struct file *file) wb_smsc_wdt_reset_timer(); } - timer_enabled = 0; + clear_bit(0, &timer_enabled); expect_close = 0; return 0; } @@ -425,7 +435,8 @@ static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, return -ENOTTY; case WDIOC_GETSUPPORT: - return copy_to_user(uarg.ident, &ident, sizeof(ident)); + return copy_to_user(uarg.ident, &ident, + sizeof(ident)) ? -EFAULT : 0; case WDIOC_GETSTATUS: return put_user(wb_smsc_wdt_status(), uarg.i); @@ -506,12 +517,12 @@ static struct file_operations wb_smsc_wdt_fops = .write = wb_smsc_wdt_write, .ioctl = wb_smsc_wdt_ioctl, .open = wb_smsc_wdt_open, - .release = wb_smsc_wdt_release + .release = wb_smsc_wdt_release, }; static struct notifier_block wb_smsc_wdt_notifier = { - .notifier_call = wb_smsc_wdt_notify_sys + .notifier_call = wb_smsc_wdt_notify_sys, }; static struct miscdevice wb_smsc_wdt_miscdev = @@ -529,6 +540,8 @@ static int __init wb_smsc_wdt_init(void) { int ret; + spin_lock_init(&io_lock); + printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { @@ -537,6 +550,13 @@ static int __init wb_smsc_wdt_init(void) goto out_pnp; } + // set new maximum, if it's too big + if (timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; + + // init the watchdog timer + wb_smsc_wdt_initialize(); + ret = register_reboot_notifier(&wb_smsc_wdt_notifier); if (ret) { printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret); @@ -549,13 +569,6 @@ static int __init wb_smsc_wdt_init(void) goto out_rbt; } - // init the watchdog timer - wb_smsc_wdt_initialize(); - - // set new maximum, if it's too big - if (timeout > MAX_TIMEOUT) - timeout = MAX_TIMEOUT; - // output info printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); @@ -607,7 +620,7 @@ module_param(unit, int, 0); MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); #endif -module_param(timeout, int, 60); +module_param(timeout, int, 0); MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); module_param(nowayout, int, 0); -- cgit v1.2.3 From f9a8c8913a95aed91bfa81f7d4043c6430423bf8 Mon Sep 17 00:00:00 2001 From: Marcus Junker Date: Thu, 24 Aug 2006 17:11:50 +0200 Subject: [WATCHDOG] w83697hf WDT driver New watchdog driver for the Winbond W83697HF chipset. Signed-off-by: Marcus Junker Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 13 ++ drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/w83697hf_wdt.c | 367 +++++++++++++++++++++++++++++++++++ 3 files changed, 381 insertions(+) create mode 100644 drivers/char/watchdog/w83697hf_wdt.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 8d2ebc73c894..3e67e01b0730 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -430,6 +430,19 @@ config W83627HF_WDT Most people will say N. +config W83697HF_WDT + tristate "W83697HF Watchdog Timer" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog on the W83697HF chipset + This watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of time. + + To compile this driver as a module, choose M here: the + module will be called w83697hf_wdt. + + Most people will say N. + config W83877F_WDT tristate "W83877F (EMACS) Watchdog Timer" depends on WATCHDOG && X86 diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 630526f12376..ee3474190e23 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_SBC8360_WDT) += sbc8360.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o +obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c new file mode 100644 index 000000000000..ef6612e1b91f --- /dev/null +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -0,0 +1,367 @@ +/* + * w83697hf WDT driver + * + * (c) Copyright 2006 Marcus Junker + * + * Based on w83627hf_wdt.c advantechwdt.c which is based on wdt.c. + * Original copyright messages: + * + * (c) Copyright 2003 Pádraig Brady + * + * (c) Copyright 2000-2001 Marek Michalkiewicz + * + * (c) Copyright 1996 Alan Cox , All Rights Reserved. + * http://www.redhat.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. + * + * Neither Marcus Junker nor ANDURAS AG admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WATCHDOG_NAME "w83697hf WDT" +#define PFX WATCHDOG_NAME ": " +#define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ + +static unsigned long wdt_is_open; +static char expect_close; + +/* You must set this - there is no sane way to probe for this board. */ +static int wdt_io = 0x2E; +module_param(wdt_io, int, 0); +MODULE_PARM_DESC(wdt_io, "w83697hf WDT io port (default 0x2E)"); + +static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, 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=CONFIG_WATCHDOG_NOWAYOUT)"); + +/* + * Kernel methods. + */ + +#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ +#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ +#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ + +static void +w83697hf_select_wd_register(void) +{ + outb_p(0x87, WDT_EFER); /* Enter extended function mode */ + outb_p(0x87, WDT_EFER); /* Again according to manual */ + + outb_p(0x29, WDT_EFER); /* select CR29 */ + outb_p(0x20, WDT_EFDR); /* select WDTO */ + + outb_p(0x07, WDT_EFER); /* point to logical device number reg */ + outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ + outb_p(0x30, WDT_EFER); /* select CR30 */ + outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ +} + +static void +w83697hf_unselect_wd_register(void) +{ + outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ +} + +/* tyan motherboards seem to set F5 to 0x4C ? + * So explicitly init to appropriate value. */ +static void +w83697hf_init(void) +{ + unsigned char t; + + w83697hf_select_wd_register(); + + outb_p(0xF3, WDT_EFER); /* Select CRF3 */ + + t=inb_p(WDT_EFDR); /* read CRF6 */ + if (t != 0) { + printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); + outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ + } + outb_p(0xF4, WDT_EFER); /* Select CRF4 */ + t=inb_p(WDT_EFDR); /* read CRF4 */ + t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ + outb_p(t, WDT_EFDR); /* Write back to CRF5 */ + + w83697hf_unselect_wd_register(); +} + +static void +wdt_ctrl(int timeout) +{ + w83697hf_select_wd_register(); + + outb_p(0xF4, WDT_EFER); /* Select CRF4 */ + outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ + + w83697hf_unselect_wd_register(); +} + +static int +wdt_ping(void) +{ + wdt_ctrl(timeout); + return 0; +} + +static int +wdt_disable(void) +{ + wdt_ctrl(0); + return 0; +} + +static int +wdt_set_heartbeat(int t) +{ + if ((t < 1) || (t > 63)) + return -EINVAL; + + timeout = t; + return 0; +} + +static ssize_t +wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + if (count) { + if (!nowayout) { + size_t i; + + expect_close = 0; + + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf+i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + wdt_ping(); + } + return count; +} + +static int +wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_timeout; + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "W83697HF WDT", + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + break; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_KEEPALIVE: + wdt_ping(); + break; + + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, p)) + return -EFAULT; + if (wdt_set_heartbeat(new_timeout)) + return -EINVAL; + wdt_ping(); + /* Fall */ + + case WDIOC_GETTIMEOUT: + return put_user(timeout, p); + + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, p)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + wdt_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + wdt_ping(); + retval = 0; + } + + return retval; + } + + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int +wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &wdt_is_open)) + return -EBUSY; + /* + * Activate + */ + + wdt_ping(); + return nonseekable_open(inode, file); +} + +static int +wdt_close(struct inode *inode, struct file *file) +{ + if (expect_close == 42) { + wdt_disable(); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + wdt_ping(); + } + expect_close = 0; + clear_bit(0, &wdt_is_open); + return 0; +} + +/* + * Notifier for system down + */ + +static int +wdt_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + /* Turn the WDT off */ + wdt_disable(); + } + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .ioctl = wdt_ioctl, + .open = wdt_open, + .release = wdt_close, +}; + +static struct miscdevice wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +/* + * The WDT needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block wdt_notifier = { + .notifier_call = wdt_notify_sys, +}; + +static int __init +wdt_init(void) +{ + int ret; + + printk(KERN_INFO "WDT driver for the Winbond(TM) W83697HF Super I/O chip initialising.\n"); + + if (wdt_set_heartbeat(timeout)) { + wdt_set_heartbeat(WATCHDOG_TIMEOUT); + printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", + WATCHDOG_TIMEOUT); + } + + if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + wdt_io); + ret = -EIO; + goto out; + } + + w83697hf_init(); + + ret = register_reboot_notifier(&wdt_notifier); + if (ret != 0) { + printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); + goto unreg_regions; + } + + ret = misc_register(&wdt_miscdev); + if (ret != 0) { + printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + goto unreg_reboot; + } + + printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", + timeout, nowayout); + +out: + return ret; +unreg_reboot: + unregister_reboot_notifier(&wdt_notifier); +unreg_regions: + release_region(wdt_io, 1); + goto out; +} + +static void __exit +wdt_exit(void) +{ + misc_deregister(&wdt_miscdev); + unregister_reboot_notifier(&wdt_notifier); + release_region(wdt_io,1); +} + +module_init(wdt_init); +module_exit(wdt_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marcus Junker "); +MODULE_DESCRIPTION("w83697hf WDT driver"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From e0845bf4e1df07e16fa39d96508a1ba4a480ce3e Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 2 Sep 2006 17:59:54 +0200 Subject: [WATCHDOG] Kconfig clean-up * fix typo's according to spellings checker * Fix some leading and trailing spaces Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 3e67e01b0730..00b21db8eee6 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -13,7 +13,7 @@ config WATCHDOG subsequently opening the file and then failing to write to it for longer than 1 minute will result in rebooting the machine. This could be useful for a networked machine that needs to come back - online as fast as possible after a lock-up. There's both a watchdog + on-line as fast as possible after a lock-up. There's both a watchdog implementation entirely in software (which can sometimes fail to reboot the machine) and a driver for hardware watchdog boards, which are more robust and can also keep track of the temperature inside @@ -71,7 +71,7 @@ config 21285_WATCHDOG tristate "DC21285 watchdog" depends on WATCHDOG && FOOTBRIDGE help - The Intel Footbridge chip contains a builtin watchdog circuit. Say Y + The Intel Footbridge chip contains a built-in watchdog circuit. Say Y here if you wish to use this. Alternatively say M to compile the driver as a module, which will be called wdt285. @@ -273,7 +273,7 @@ config IBMASR depends on WATCHDOG && X86 help This is the driver for the IBM Automatic Server Restart watchdog - timer builtin into some eServer xSeries machines. + timer built-in into some eServer xSeries machines. To compile this driver as a module, choose M here: the module will be called ibmasr. @@ -431,17 +431,17 @@ config W83627HF_WDT Most people will say N. config W83697HF_WDT - tristate "W83697HF Watchdog Timer" - depends on WATCHDOG && X86 - ---help--- - This is the driver for the hardware watchdog on the W83697HF chipset - This watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of time. + tristate "W83697HF Watchdog Timer" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog on the W83697HF chipset + This watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of time. - To compile this driver as a module, choose M here: the - module will be called w83697hf_wdt. + To compile this driver as a module, choose M here: the + module will be called w83697hf_wdt. - Most people will say N. + Most people will say N. config W83877F_WDT tristate "W83877F (EMACS) Watchdog Timer" @@ -476,7 +476,7 @@ config MACHZ_WDT depends on WATCHDOG && X86 ---help--- If you are using a ZF Micro MachZ processor, say Y here, otherwise - N. This is the driver for the watchdog timer builtin on that + N. This is the driver for the watchdog timer built-in on that processor using ZF-Logic interface. This watchdog simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. -- cgit v1.2.3 From ab9d441425559aa035ba6327f21e8922e8a13927 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 2 Sep 2006 18:50:20 +0200 Subject: [WATCHDOG] w836?7hf_wdt spinlock fixes. Add io spinlocks to prevent possible race conditions between start and stop operations that are issued from different child processes where the master process opened /dev/watchdog. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83627hf_wdt.c | 8 ++++++++ drivers/char/watchdog/w83697hf_wdt.c | 8 ++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c index b4adc527e687..07d4bff27226 100644 --- a/drivers/char/watchdog/w83627hf_wdt.c +++ b/drivers/char/watchdog/w83627hf_wdt.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ static unsigned long wdt_is_open; static char expect_close; +static spinlock_t io_lock; /* You must set this - there is no sane way to probe for this board. */ static int wdt_io = 0x2E; @@ -110,12 +112,16 @@ w83627hf_init(void) static void wdt_ctrl(int timeout) { + spin_lock(&io_lock); + w83627hf_select_wd_register(); outb_p(0xF6, WDT_EFER); /* Select CRF6 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF6 */ w83627hf_unselect_wd_register(); + + spin_unlock(&io_lock); } static int @@ -303,6 +309,8 @@ wdt_init(void) { int ret; + spin_lock_init(&io_lock); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index ef6612e1b91f..21e822e0eeec 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -44,6 +45,7 @@ static unsigned long wdt_is_open; static char expect_close; +static spinlock_t io_lock; /* You must set this - there is no sane way to probe for this board. */ static int wdt_io = 0x2E; @@ -114,12 +116,16 @@ w83697hf_init(void) static void wdt_ctrl(int timeout) { + spin_lock(&io_lock); + w83697hf_select_wd_register(); outb_p(0xF4, WDT_EFER); /* Select CRF4 */ outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ w83697hf_unselect_wd_register(); + + spin_unlock(&io_lock); } static int @@ -307,6 +313,8 @@ wdt_init(void) { int ret; + spin_lock_init(&io_lock); + printk(KERN_INFO "WDT driver for the Winbond(TM) W83697HF Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { -- cgit v1.2.3 From c310e2b950c949cfc14754baed877eadb1a26f6b Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 2 Sep 2006 19:04:02 +0200 Subject: [WATCHDOG] Kconfig clean up fixed some more trailing spaces. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 00b21db8eee6..ecae59cd7678 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -269,9 +269,9 @@ config IB700_WDT Most people will say N. config IBMASR - tristate "IBM Automatic Server Restart" - depends on WATCHDOG && X86 - help + tristate "IBM Automatic Server Restart" + depends on WATCHDOG && X86 + help This is the driver for the IBM Automatic Server Restart watchdog timer built-in into some eServer xSeries machines. @@ -505,7 +505,6 @@ config SBC_EPX_C3_WATCHDOG To compile this driver as a module, choose M here: the module will be called sbc_epx_c3. - # PowerPC Architecture config 8xx_WDT @@ -535,7 +534,7 @@ config WATCHDOG_RTAS help This driver adds watchdog support for the RTAS watchdog. - To compile this driver as a module, choose M here. The module + To compile this driver as a module, choose M here. The module will be called wdrtas. # MIPS Architecture -- cgit v1.2.3 From 196f29c8e8cd3352d26ed7bdf44f622e14adb931 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 13 Sep 2006 21:27:29 +0200 Subject: [WATCHDOG] use ENOTTY instead of ENOIOCTLCMD in ioctl() Return ENOTTY instead of ENOIOCTLCMD in user-visible ioctl() results The watchdog drivers used to return ENOIOCTLCMD for bad ioctl() commands. ENOIOCTLCMD should not be visible by the user, so use ENOTTY instead. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck Acked-by: Alan Cox Signed-off-by: Andrew Morton --- drivers/char/watchdog/w83697hf_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 21e822e0eeec..32710a97b161 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -233,7 +233,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } default: - return -ENOIOCTLCMD; + return -ENOTTY; } return 0; } -- cgit v1.2.3 From 8de6fc1e2023954ec21d4e84d002839afed4cad3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 1 This is patch 1 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - the note concerning tyan motherboards has been copied from another driver, This doesn't apply here. - the comments concerning CRF6 are wrong as CRF3 is manipulated and CRF6 is never read nor written. - the comments concerning CRF5 are wrong as CRF4 is manipulated and CRF5 is never read nor written. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 32710a97b161..c31121eab3c9 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -89,8 +89,6 @@ w83697hf_unselect_wd_register(void) outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ } -/* tyan motherboards seem to set F5 to 0x4C ? - * So explicitly init to appropriate value. */ static void w83697hf_init(void) { @@ -100,15 +98,15 @@ w83697hf_init(void) outb_p(0xF3, WDT_EFER); /* Select CRF3 */ - t=inb_p(WDT_EFDR); /* read CRF6 */ + t=inb_p(WDT_EFDR); /* read CRF3 */ if (t != 0) { printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); - outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ + outb_p(timeout, WDT_EFDR); /* Write back to CRF3 */ } outb_p(0xF4, WDT_EFER); /* Select CRF4 */ t=inb_p(WDT_EFDR); /* read CRF4 */ t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ - outb_p(t, WDT_EFDR); /* Write back to CRF5 */ + outb_p(t, WDT_EFDR); /* Write back to CRF4 */ w83697hf_unselect_wd_register(); } -- cgit v1.2.3 From b41a9f59d13a4c4c3f0e0b8d9ff15743607096a2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 2 This is patch 2 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - wdt_io is 2 bytes long. We should do a request_region for 2 bytes instead of 1. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index c31121eab3c9..4f81943fe7fa 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -321,7 +321,7 @@ wdt_init(void) WATCHDOG_TIMEOUT); } - if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { + if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", wdt_io); ret = -EIO; @@ -352,7 +352,7 @@ out: unreg_reboot: unregister_reboot_notifier(&wdt_notifier); unreg_regions: - release_region(wdt_io, 1); + release_region(wdt_io, 2); goto out; } @@ -361,7 +361,7 @@ wdt_exit(void) { misc_deregister(&wdt_miscdev); unregister_reboot_notifier(&wdt_notifier); - release_region(wdt_io,1); + release_region(wdt_io, 2); } module_init(wdt_init); -- cgit v1.2.3 From db16525e63f8cf554696045e0e360b81e2263279 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 3 This is patch 3 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Fix identation. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 66 ++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 4f81943fe7fa..12bdcab17b9e 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -6,7 +6,7 @@ * Based on w83627hf_wdt.c advantechwdt.c which is based on wdt.c. * Original copyright messages: * - * (c) Copyright 2003 Pádraig Brady + * (c) Copyright 2003 Pádraig Brady * * (c) Copyright 2000-2001 Marek Michalkiewicz * @@ -96,16 +96,16 @@ w83697hf_init(void) w83697hf_select_wd_register(); - outb_p(0xF3, WDT_EFER); /* Select CRF3 */ + outb_p(0xF3, WDT_EFER); /* Select CRF3 */ t=inb_p(WDT_EFDR); /* read CRF3 */ if (t != 0) { printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); outb_p(timeout, WDT_EFDR); /* Write back to CRF3 */ } - outb_p(0xF4, WDT_EFER); /* Select CRF4 */ - t=inb_p(WDT_EFDR); /* read CRF4 */ - t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ + outb_p(0xF4, WDT_EFER); /* Select CRF4 */ + t=inb_p(WDT_EFDR); /* read CRF4 */ + t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ outb_p(t, WDT_EFDR); /* Write back to CRF4 */ w83697hf_unselect_wd_register(); @@ -187,51 +187,51 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user(argp, &ident, sizeof(ident))) - return -EFAULT; - break; + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, p); + return put_user(0, p); case WDIOC_KEEPALIVE: - wdt_ping(); - break; + wdt_ping(); + break; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, p)) - return -EFAULT; - if (wdt_set_heartbeat(new_timeout)) - return -EINVAL; - wdt_ping(); - /* Fall */ + if (get_user(new_timeout, p)) + return -EFAULT; + if (wdt_set_heartbeat(new_timeout)) + return -EINVAL; + wdt_ping(); + /* Fall */ case WDIOC_GETTIMEOUT: - return put_user(timeout, p); + return put_user(timeout, p); case WDIOC_SETOPTIONS: { - int options, retval = -EINVAL; + int options, retval = -EINVAL; - if (get_user(options, p)) - return -EFAULT; + if (get_user(options, p)) + return -EFAULT; - if (options & WDIOS_DISABLECARD) { - wdt_disable(); - retval = 0; - } + if (options & WDIOS_DISABLECARD) { + wdt_disable(); + retval = 0; + } - if (options & WDIOS_ENABLECARD) { - wdt_ping(); - retval = 0; - } + if (options & WDIOS_ENABLECARD) { + wdt_ping(); + retval = 0; + } - return retval; + return retval; } default: - return -ENOTTY; + return -ENOTTY; } return 0; } @@ -255,7 +255,7 @@ wdt_close(struct inode *inode, struct file *file) if (expect_close == 42) { wdt_disable(); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); wdt_ping(); } expect_close = 0; @@ -313,7 +313,7 @@ wdt_init(void) spin_lock_init(&io_lock); - printk(KERN_INFO "WDT driver for the Winbond(TM) W83697HF Super I/O chip initialising.\n"); + printk (KERN_INFO "WDT driver for the Winbond(TM) W83697HF Super I/O chip initialising.\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); -- cgit v1.2.3 From eb64419e397aaea55b2ef6904e86b6263a80acc7 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 4 This is patch 4 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - limits the watchdog timeout to 1-63 while this device accepts 1-255. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 12bdcab17b9e..94b1655e70ca 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -54,7 +54,7 @@ MODULE_PARM_DESC(wdt_io, "w83697hf WDT io port (default 0x2E)"); static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, 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); @@ -143,7 +143,7 @@ wdt_disable(void) static int wdt_set_heartbeat(int t) { - if ((t < 1) || (t > 63)) + if ((t < 1) || (t > 255)) return -EINVAL; timeout = t; @@ -317,7 +317,7 @@ wdt_init(void) if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); - printk (KERN_INFO PFX "timeout value must be 1<=timeout<=63, using %d\n", + printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", WATCHDOG_TIMEOUT); } -- cgit v1.2.3 From 44d7d3282baa4080b73adca31648e6ef1e191874 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 5 This is patch 5 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Rename the Extended Function Registers to the names used in the data-sheet. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 42 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 94b1655e70ca..c44f281f3565 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -64,29 +64,29 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON * Kernel methods. */ -#define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ -#define WDT_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ -#define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ +#define W83697HF_EFER (wdt_io+0) /* Extended Function Enable Register */ +#define W83697HF_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ +#define W83697HF_EFDR (wdt_io+1) /* Extended Function Data Register */ static void w83697hf_select_wd_register(void) { - outb_p(0x87, WDT_EFER); /* Enter extended function mode */ - outb_p(0x87, WDT_EFER); /* Again according to manual */ + outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ + outb_p(0x87, W83697HF_EFER); /* Again according to manual */ - outb_p(0x29, WDT_EFER); /* select CR29 */ - outb_p(0x20, WDT_EFDR); /* select WDTO */ + outb_p(0x29, W83697HF_EFER); /* select CR29 */ + outb_p(0x20, W83697HF_EFDR); /* select WDTO */ - outb_p(0x07, WDT_EFER); /* point to logical device number reg */ - outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ - outb_p(0x30, WDT_EFER); /* select CR30 */ - outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ + outb_p(0x07, W83697HF_EFER); /* point to logical device number reg */ + outb_p(0x08, W83697HF_EFDR); /* select logical device 8 (GPIO2) */ + outb_p(0x30, W83697HF_EFER); /* select CR30 */ + outb_p(0x01, W83697HF_EFDR); /* set bit 0 to activate GPIO2 */ } static void w83697hf_unselect_wd_register(void) { - outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ + outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ } static void @@ -96,17 +96,17 @@ w83697hf_init(void) w83697hf_select_wd_register(); - outb_p(0xF3, WDT_EFER); /* Select CRF3 */ + outb_p(0xF3, W83697HF_EFER); /* Select CRF3 */ - t=inb_p(WDT_EFDR); /* read CRF3 */ + t=inb_p(W83697HF_EFDR); /* read CRF3 */ if (t != 0) { printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); - outb_p(timeout, WDT_EFDR); /* Write back to CRF3 */ + outb_p(timeout, W83697HF_EFDR); /* Write back to CRF3 */ } - outb_p(0xF4, WDT_EFER); /* Select CRF4 */ - t=inb_p(WDT_EFDR); /* read CRF4 */ - t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ - outb_p(t, WDT_EFDR); /* Write back to CRF4 */ + outb_p(0xF4, W83697HF_EFER); /* Select CRF4 */ + t=inb_p(W83697HF_EFDR); /* read CRF4 */ + t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ + outb_p(t, W83697HF_EFDR); /* Write back to CRF4 */ w83697hf_unselect_wd_register(); } @@ -118,8 +118,8 @@ wdt_ctrl(int timeout) w83697hf_select_wd_register(); - outb_p(0xF4, WDT_EFER); /* Select CRF4 */ - outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ + outb_p(0xF4, W83697HF_EFER); /* Select CRF4 */ + outb_p(timeout, W83697HF_EFDR); /* Write Timeout counter to CRF4 */ w83697hf_unselect_wd_register(); -- cgit v1.2.3 From de710d6871c7f569da007f1074710fadf1708c29 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 6 This is patch 6 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - The driver works for both the w83697hf and the w83697hg chipset's. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index c44f281f3565..ad397f912bd4 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -1,9 +1,10 @@ /* - * w83697hf WDT driver + * w83697hf/hg WDT driver * * (c) Copyright 2006 Marcus Junker * - * Based on w83627hf_wdt.c advantechwdt.c which is based on wdt.c. + * Based on w83627hf_wdt.c which is based on advantechwdt.c + * which is based on wdt.c. * Original copyright messages: * * (c) Copyright 2003 Pádraig Brady @@ -39,7 +40,7 @@ #include #include -#define WATCHDOG_NAME "w83697hf WDT" +#define WATCHDOG_NAME "w83697hf/hg WDT" #define PFX WATCHDOG_NAME ": " #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ @@ -313,7 +314,7 @@ wdt_init(void) spin_lock_init(&io_lock); - printk (KERN_INFO "WDT driver for the Winbond(TM) W83697HF Super I/O chip initialising.\n"); + printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); @@ -369,5 +370,5 @@ module_exit(wdt_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marcus Junker "); -MODULE_DESCRIPTION("w83697hf WDT driver"); +MODULE_DESCRIPTION("w83697hf/hg WDT driver"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From f7be3328b6e8b09b3a910a93ef569cba162ea81d Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 7 This is patch 7 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - add w83697hf_unlock function to enter the chipsets extended function mode. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index ad397f912bd4..b1f225798500 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -69,11 +69,17 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON #define W83697HF_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ #define W83697HF_EFDR (wdt_io+1) /* Extended Function Data Register */ -static void -w83697hf_select_wd_register(void) +static inline void +w83697hf_unlock(void) { outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ outb_p(0x87, W83697HF_EFER); /* Again according to manual */ +} + +static void +w83697hf_select_wd_register(void) +{ + w83697hf_unlock(); outb_p(0x29, W83697HF_EFER); /* select CR29 */ outb_p(0x20, W83697HF_EFDR); /* select WDTO */ -- cgit v1.2.3 From fe851ebade80af9b58599c74d61718657b02cfd3 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 8 This is patch 8 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - add w83697hf_lock function to leave the chipsets extended function mode. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b1f225798500..6a357a818c8a 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -76,6 +76,12 @@ w83697hf_unlock(void) outb_p(0x87, W83697HF_EFER); /* Again according to manual */ } +static inline void +w83697hf_lock(void) +{ + outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ +} + static void w83697hf_select_wd_register(void) { @@ -93,7 +99,7 @@ w83697hf_select_wd_register(void) static void w83697hf_unselect_wd_register(void) { - outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ + w83697hf_lock(); } static void -- cgit v1.2.3 From 0cd544763bacad14d0d15fb16d29999b450cb77f Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 9 This is patch 9 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - add w83697hf_get_reg() and w83697hf_set_reg() functions. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 42 +++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 6a357a818c8a..f62f17238712 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -82,18 +82,34 @@ w83697hf_lock(void) outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ } +/* + * The two functions w83697hf_get_reg() and w83697hf_set_reg() + * must be called with the device unlocked. + */ + +static unsigned char +w83697hf_get_reg(unsigned char reg) +{ + outb_p(reg, W83697HF_EFIR); + return inb_p(W83697HF_EFDR); +} + +static void +w83697hf_set_reg(unsigned char reg, unsigned char data) +{ + outb_p(reg, W83697HF_EFIR); + outb_p(data, W83697HF_EFDR); +} + static void w83697hf_select_wd_register(void) { w83697hf_unlock(); - outb_p(0x29, W83697HF_EFER); /* select CR29 */ - outb_p(0x20, W83697HF_EFDR); /* select WDTO */ + w83697hf_set_reg(0x29, 0x20); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ - outb_p(0x07, W83697HF_EFER); /* point to logical device number reg */ - outb_p(0x08, W83697HF_EFDR); /* select logical device 8 (GPIO2) */ - outb_p(0x30, W83697HF_EFER); /* select CR30 */ - outb_p(0x01, W83697HF_EFDR); /* set bit 0 to activate GPIO2 */ + w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ + w83697hf_set_reg(0x30, 0x01); /* Enable timer/activate GPIO2 via bit 0 */ } static void @@ -109,17 +125,14 @@ w83697hf_init(void) w83697hf_select_wd_register(); - outb_p(0xF3, W83697HF_EFER); /* Select CRF3 */ - - t=inb_p(W83697HF_EFDR); /* read CRF3 */ + t = w83697hf_get_reg(0xF3); /* Read CRF3 */ if (t != 0) { printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); - outb_p(timeout, W83697HF_EFDR); /* Write back to CRF3 */ + w83697hf_set_reg(0xF3, timeout); /* Write new timeout */ } - outb_p(0xF4, W83697HF_EFER); /* Select CRF4 */ - t=inb_p(W83697HF_EFDR); /* read CRF4 */ + t = w83697hf_get_reg(0xF4); /* Read CRF4 */ t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ - outb_p(t, W83697HF_EFDR); /* Write back to CRF4 */ + w83697hf_set_reg(0xF4, t); /* Write back to CRF4 */ w83697hf_unselect_wd_register(); } @@ -131,8 +144,7 @@ wdt_ctrl(int timeout) w83697hf_select_wd_register(); - outb_p(0xF4, W83697HF_EFER); /* Select CRF4 */ - outb_p(timeout, W83697HF_EFDR); /* Write Timeout counter to CRF4 */ + w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ w83697hf_unselect_wd_register(); -- cgit v1.2.3 From c81b2996253a94278057f83a24dfa9053f0dee7a Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 10 This is patch 10 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - check whether the device is really present (we *can* probe for the device now). Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 54 +++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index f62f17238712..4e0bd4e714e3 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -49,9 +49,9 @@ static char expect_close; static spinlock_t io_lock; /* You must set this - there is no sane way to probe for this board. */ -static int wdt_io = 0x2E; +static int wdt_io = 0x2e; module_param(wdt_io, int, 0); -MODULE_PARM_DESC(wdt_io, "w83697hf WDT io port (default 0x2E)"); +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); @@ -331,28 +331,62 @@ static struct notifier_block wdt_notifier = { .notifier_call = wdt_notify_sys, }; +static int +w83697hf_check_wdt(void) +{ + if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { + printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io); + return -EIO; + } + + printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io); + w83697hf_unlock(); + if (w83697hf_get_reg(0x20) == 0x60) { + printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io); + w83697hf_lock(); + return 0; + } + w83697hf_lock(); /* Reprotect in case it was a compatible device */ + + printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); + release_region(wdt_io, 2); + return -EIO; +} + static int __init wdt_init(void) { - int ret; + int ret, autodetect; spin_lock_init(&io_lock); printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); + autodetect = wdt_io == 0; + if (autodetect) + wdt_io = 0x2e; + + if (!w83697hf_check_wdt()) + goto found; + + if (autodetect) { + wdt_io = 0x4e; + if (!w83697hf_check_wdt()) + goto found; + } + + printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); + ret = -EIO; + goto out; + +found: + if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", WATCHDOG_TIMEOUT); } - if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { - printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", - wdt_io); - ret = -EIO; - goto out; - } - w83697hf_init(); ret = register_reboot_notifier(&wdt_notifier); -- cgit v1.2.3 From a7933e05d46f49385841d09028ee07fae2b383f2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 11 This is patch 11 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Add w83697hf_select_wdt() and w83697hf_deselect_wdt() so that the start/stop/ping code can directly talk to the watchdog. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 4e0bd4e714e3..b12f8b800762 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -101,6 +101,19 @@ w83697hf_set_reg(unsigned char reg, unsigned char data) outb_p(data, W83697HF_EFDR); } +static void +w83697hf_select_wdt(void) +{ + w83697hf_unlock(); + w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ +} + +static inline void +w83697hf_deselect_wdt(void) +{ + w83697hf_lock(); +} + static void w83697hf_select_wd_register(void) { @@ -142,11 +155,11 @@ wdt_ctrl(int timeout) { spin_lock(&io_lock); - w83697hf_select_wd_register(); + w83697hf_select_wdt(); w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ - w83697hf_unselect_wd_register(); + w83697hf_deselect_wdt(); spin_unlock(&io_lock); } -- cgit v1.2.3 From d46ab596e251e35a7e27c95e4e4d01921f3e579e Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 12 This is patch 12 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Add w83697hf_write_timeout() to set the watchdog's timeout value. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b12f8b800762..b3dcc81abbbc 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -83,8 +83,8 @@ w83697hf_lock(void) } /* - * The two functions w83697hf_get_reg() and w83697hf_set_reg() - * must be called with the device unlocked. + * The three functions w83697hf_get_reg(), w83697hf_set_reg() and + * w83697hf_write_timeout() must be called with the device unlocked. */ static unsigned char @@ -101,6 +101,12 @@ w83697hf_set_reg(unsigned char reg, unsigned char data) outb_p(data, W83697HF_EFDR); } +static void +w83697hf_write_timeout(int timeout) +{ + w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ +} + static void w83697hf_select_wdt(void) { @@ -157,7 +163,7 @@ wdt_ctrl(int timeout) w83697hf_select_wdt(); - w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ + w83697hf_write_timeout(timeout); w83697hf_deselect_wdt(); -- cgit v1.2.3 From 089d8139f4c19c2f4d6984323e9d8a6e77cc92f7 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 13 This is patch 13 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Remove wdt_ctrl (it has been replaced with the w83697hf_write_timeout() function) and redo/clean-up the start/stop/ping code. - Make sure that the watchdog is enabled or disabled When starting or stoping the device (with a call to w83697hf_set_reg(0x30, ?); ). Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index b3dcc81abbbc..2b3ce434c196 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -156,31 +156,44 @@ w83697hf_init(void) w83697hf_unselect_wd_register(); } -static void -wdt_ctrl(int timeout) +static int +wdt_ping(void) { spin_lock(&io_lock); - w83697hf_select_wdt(); w83697hf_write_timeout(timeout); w83697hf_deselect_wdt(); - spin_unlock(&io_lock); + return 0; } static int -wdt_ping(void) +wdt_enable(void) { - wdt_ctrl(timeout); + spin_lock(&io_lock); + w83697hf_select_wdt(); + + w83697hf_write_timeout(timeout); + w83697hf_set_reg(0x30, 1); /* Enable timer */ + + w83697hf_deselect_wdt(); + spin_unlock(&io_lock); return 0; } static int wdt_disable(void) { - wdt_ctrl(0); + spin_lock(&io_lock); + w83697hf_select_wdt(); + + w83697hf_set_reg(0x30, 0); /* Disable timer */ + w83697hf_write_timeout(0); + + w83697hf_deselect_wdt(); + spin_unlock(&io_lock); return 0; } @@ -267,7 +280,7 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } if (options & WDIOS_ENABLECARD) { - wdt_ping(); + wdt_enable(); retval = 0; } @@ -289,7 +302,7 @@ wdt_open(struct inode *inode, struct file *file) * Activate */ - wdt_ping(); + wdt_enable(); return nonseekable_open(inode, file); } -- cgit v1.2.3 From fa69afd3c224252890cb30864dc648d1399dd9fe Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 14 This is patch 14 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Clean-up initialization code (part 1: remove w83697hf_select_wd_register() and w83697hf_unselect_wd_register() functions). - Make sure that the watchdog device is stopped as soon as we found it. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 2b3ce434c196..1ea43bf2c35d 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -120,29 +120,14 @@ w83697hf_deselect_wdt(void) w83697hf_lock(); } -static void -w83697hf_select_wd_register(void) -{ - w83697hf_unlock(); - - w83697hf_set_reg(0x29, 0x20); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ - - w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ - w83697hf_set_reg(0x30, 0x01); /* Enable timer/activate GPIO2 via bit 0 */ -} - -static void -w83697hf_unselect_wd_register(void) -{ - w83697hf_lock(); -} - static void w83697hf_init(void) { unsigned char t; - w83697hf_select_wd_register(); + w83697hf_select_wdt(); + + w83697hf_set_reg(0x29, 0x20); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ t = w83697hf_get_reg(0xF3); /* Read CRF3 */ if (t != 0) { @@ -153,7 +138,7 @@ w83697hf_init(void) t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ w83697hf_set_reg(0xF4, t); /* Write back to CRF4 */ - w83697hf_unselect_wd_register(); + w83697hf_deselect_wdt(); } static int @@ -412,6 +397,8 @@ wdt_init(void) goto out; found: + w83697hf_init(); + wdt_disable(); /* Disable watchdog until first use */ if (wdt_set_heartbeat(timeout)) { wdt_set_heartbeat(WATCHDOG_TIMEOUT); @@ -419,8 +406,6 @@ found: WATCHDOG_TIMEOUT); } - w83697hf_init(); - ret = register_reboot_notifier(&wdt_notifier); if (ret != 0) { printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", -- cgit v1.2.3 From b7b9868ba6f528d60e5869b4a6aad1fe49838b03 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 15 This is patch 15 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Clean-up initialization code - part 2: * the line reading "set second mode & disable keyboard ..." is plain wrong, the register being manipulated (CRF4) is the counter itself, not the control byte (CRF3) -- looks like it has been copied from another driver. * I think garbage is being written in CRF3 (the control word) as the timeout value is being stored in this register (such as 60 for 60 seconds). * We only want to set pin 119 to WDTO# mode and leave the rest of CR29 like it is. * Set count mode to seconds and not minutes. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 1ea43bf2c35d..78b6540e8747 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -123,20 +123,18 @@ w83697hf_deselect_wdt(void) static void w83697hf_init(void) { - unsigned char t; + unsigned char bbuf; w83697hf_select_wdt(); - w83697hf_set_reg(0x29, 0x20); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ + bbuf = w83697hf_get_reg(0x29); + bbuf &= ~0x60; + bbuf |= 0x20; + w83697hf_set_reg(0x29, bbuf); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ - t = w83697hf_get_reg(0xF3); /* Read CRF3 */ - if (t != 0) { - printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); - w83697hf_set_reg(0xF3, timeout); /* Write new timeout */ - } - t = w83697hf_get_reg(0xF4); /* Read CRF4 */ - t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ - w83697hf_set_reg(0xF4, t); /* Write back to CRF4 */ + bbuf = w83697hf_get_reg(0xF3); + bbuf &= ~0x04; + w83697hf_set_reg(0xF3, bbuf); /* Count mode is seconds */ w83697hf_deselect_wdt(); } -- cgit v1.2.3 From 3fdee8db010d5cbf890ec49332ac4946f3f63720 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - patch 16 This is patch 16 in the series of patches that converts Marcus Junker's w83697hf watchdog driver to Samuel Tardieau's w83697hf/hg watchdog driver. This patch contains following changes: - Add copyright notice for Samuel Tardieu also. This is the last patch in this series. The original description for Samuel's driver was: driver for the Winbond W83697HF/W83697HG watchdog timer The Winbond SuperIO W83697HF/HG includes a watchdog that can count from 1 to 255 seconds (or minutes). This drivers allows the seconds mode to be used. It exposes a standard /dev/watchdog interface. This chip is currently being used on some motherboards designed by VIA. By default, the module looks for a chip at I/O port 0x2e. The chip can be configured to be at 0x4e on some motherboards, the address can be chosen using the wdt_io module parameter. Using 0 will try to autodetect the address. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 78b6540e8747..21052de8a0c6 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -1,6 +1,7 @@ /* * w83697hf/hg WDT driver * + * (c) Copyright 2006 Samuel Tardieu * (c) Copyright 2006 Marcus Junker * * Based on w83627hf_wdt.c which is based on advantechwdt.c @@ -442,6 +443,6 @@ module_init(wdt_init); module_exit(wdt_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marcus Junker "); +MODULE_AUTHOR("Marcus Junker , Samuel Tardieu "); MODULE_DESCRIPTION("w83697hf/hg WDT driver"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From e223f01a822e999b0aea2e720e12d8bb3532da70 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 15 Sep 2006 17:59:07 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - autodetect patch Change the autodetect code so that it is more generic. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/w83697hf_wdt.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/w83697hf_wdt.c b/drivers/char/watchdog/w83697hf_wdt.c index 21052de8a0c6..7768b55487c8 100644 --- a/drivers/char/watchdog/w83697hf_wdt.c +++ b/drivers/char/watchdog/w83697hf_wdt.c @@ -369,33 +369,35 @@ w83697hf_check_wdt(void) return -EIO; } +static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; + static int __init wdt_init(void) { - int ret, autodetect; + int ret, i, found = 0; spin_lock_init(&io_lock); printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); - autodetect = wdt_io == 0; - if (autodetect) - wdt_io = 0x2e; - - if (!w83697hf_check_wdt()) - goto found; - - if (autodetect) { - wdt_io = 0x4e; + if (wdt_io == 0) { + /* we will autodetect the W83697HF/HG watchdog */ + for (i = 0; ((!found) && (w83697hf_ioports[i] != 0)); i++) { + wdt_io = w83697hf_ioports[i]; + if (!w83697hf_check_wdt()) + found++; + } + } else { if (!w83697hf_check_wdt()) - goto found; + found++; } - printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); - ret = -EIO; - goto out; + if (!found) { + printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); + ret = -EIO; + goto out; + } -found: w83697hf_init(); wdt_disable(); /* Disable watchdog until first use */ -- cgit v1.2.3 From ff02cfc76a5040ee125c597baa1cfc9874918ed2 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 7 Sep 2006 11:57:00 +0200 Subject: [WATCHDOG] w83697hf/hg WDT driver - Kconfig patch Update Kconfig for the w83697hf/hg watchdog driver. Signed-off-by: Samuel Tardieu Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index ecae59cd7678..847a26064b68 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -431,12 +431,14 @@ config W83627HF_WDT Most people will say N. config W83697HF_WDT - tristate "W83697HF Watchdog Timer" + tristate "W83697HF/W83697HG Watchdog Timer" depends on WATCHDOG && X86 ---help--- - This is the driver for the hardware watchdog on the W83697HF chipset - This watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of time. + This is the driver for the hardware watchdog on the W83697HF/HG + chipset as used in Dedibox/VIA motherboards (and likely others). + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. To compile this driver as a module, choose M here: the module will be called w83697hf_wdt. -- cgit v1.2.3 From e34477e9906acc137329b654a51fb7d4598813f7 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Fri, 6 Oct 2006 13:41:12 -0700 Subject: [WATCHDOG] ioremap balanced with iounmap for drivers/char/watchdog/s3c2410_wdt.c ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. Signed-off-by: Amol Lad Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/char/watchdog/s3c2410_wdt.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c index b36a04ae9ab8..d54d0efe0756 100644 --- a/drivers/char/watchdog/s3c2410_wdt.c +++ b/drivers/char/watchdog/s3c2410_wdt.c @@ -381,18 +381,21 @@ static int s3c2410wdt_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res == NULL) { printk(KERN_INFO PFX "failed to get irq resource\n"); + iounmap(wdt_base); return -ENOENT; } ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev); if (ret != 0) { printk(KERN_INFO PFX "failed to install irq (%d)\n", ret); + iounmap(wdt_base); return ret; } wdt_clock = clk_get(&pdev->dev, "watchdog"); if (wdt_clock == NULL) { printk(KERN_INFO PFX "failed to find watchdog clock source\n"); + iounmap(wdt_base); return -ENOENT; } @@ -416,6 +419,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) if (ret) { printk (KERN_ERR PFX "cannot register miscdev on minor=%d (%d)\n", WATCHDOG_MINOR, ret); + iounmap(wdt_base); return ret; } @@ -452,6 +456,7 @@ static int s3c2410wdt_remove(struct platform_device *dev) wdt_clock = NULL; } + iounmap(wdt_base); misc_deregister(&s3c2410wdt_miscdev); return 0; } -- cgit v1.2.3 From bcbf25bd0d4afb108a755e1c4e4e2d854a2869d7 Mon Sep 17 00:00:00 2001 From: "Arnaud Patard (Rtp)" Date: Wed, 4 Oct 2006 14:18:29 +0200 Subject: [WATCHDOG] add ich8 support to iTCO_wdt.c Add ICH8 support to the iTCO_wdt driver. Signed-off-by: Arnaud Patard Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/iTCO_wdt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index aaac94db0d8b..639d84f0c024 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -85,6 +85,7 @@ enum iTCO_chipsets { TCO_ICH7, /* ICH7 & ICH7R */ TCO_ICH7M, /* ICH7-M */ TCO_ICH7MDH, /* ICH7-M DH */ + TCO_ICH8, /* ICH8 */ }; static struct { @@ -108,6 +109,7 @@ static struct { {"ICH7 or ICH7R", 2}, {"ICH7-M", 2}, {"ICH7-M DH", 2}, + {"ICH8 or ICH8R", 2}, {NULL,0} }; @@ -135,6 +137,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3 From a8edd74e4404d011ab821d5bf35b27335d26f001 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sun, 8 Oct 2006 21:05:21 +0200 Subject: [WATCHDOG] add ich8 support to iTCO_wdt.c (patch 2) Add ICH8 support to the iTCO_wdt driver. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/iTCO_wdt.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 639d84f0c024..505aae917764 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -35,6 +35,10 @@ * 82801GDH (ICH7DH) : document number 307013-002, 307014-009, * 82801GBM (ICH7-M) : document number 307013-002, 307014-009, * 82801GHM (ICH7-M DH) : document number 307013-002, 307014-009, + * 82801HB (ICH8) : document number 313056-002, 313057-004, + * 82801HR (ICH8R) : document number 313056-002, 313057-004, + * 82801HH (ICH8DH) : document number 313056-002, 313057-004, + * 82801HO (ICH8DO) : document number 313056-002, 313057-004, * 6300ESB (6300ESB) : document number 300641-003 */ @@ -45,7 +49,7 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" #define DRV_VERSION "1.00" -#define DRV_RELDATE "30-Jul-2006" +#define DRV_RELDATE "08-Oct-2006" #define PFX DRV_NAME ": " /* Includes */ @@ -85,7 +89,9 @@ enum iTCO_chipsets { TCO_ICH7, /* ICH7 & ICH7R */ TCO_ICH7M, /* ICH7-M */ TCO_ICH7MDH, /* ICH7-M DH */ - TCO_ICH8, /* ICH8 */ + TCO_ICH8, /* ICH8 & ICH8R */ + TCO_ICH8DH, /* ICH8DH */ + TCO_ICH8DO, /* ICH8DO */ }; static struct { @@ -110,6 +116,8 @@ static struct { {"ICH7-M", 2}, {"ICH7-M DH", 2}, {"ICH8 or ICH8R", 2}, + {"ICH8DH", 2}, + {"ICH8DO", 2}, {NULL,0} }; @@ -138,6 +146,8 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7M }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH7MDH }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8 }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DH }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TCO_ICH8DO }, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3 From 73f5e28b336772c4b08ee82e5bf28ab872898ee1 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 9 Oct 2006 21:58:54 +0200 Subject: r8169: PCI ID for Corega Gigabit network card Fix for http://bugzilla.kernel.org/show_bug.cgi?id=7239. Signed-off-by: Andrew Morton Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4c47c5b10ba0..c7309e98f89d 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -214,6 +214,7 @@ static struct pci_device_id rtl8169_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_2 }, { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, + { PCI_DEVICE(0x1259, 0xc107), 0, 0, RTL_CFG_0 }, { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, -- cgit v1.2.3 From 80fc9f532d8c05d4cb12d55660624ce53a378349 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 11 Oct 2006 01:43:58 -0400 Subject: Input: add missing exports to fix modular build Signed-off-by: Dmitry Torokhov --- drivers/char/random.c | 1 + lib/kobject.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index 07f47a0208a7..eb6b13f4211a 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -645,6 +645,7 @@ void add_input_randomness(unsigned int type, unsigned int code, add_timer_randomness(&input_timer_state, (type << 4) ^ code ^ (code >> 4) ^ value); } +EXPORT_SYMBOL_GPL(add_input_randomness); void add_interrupt_randomness(int irq) { diff --git a/lib/kobject.c b/lib/kobject.c index 1699eb9161f3..7dd5c0e9d996 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -119,6 +119,7 @@ char *kobject_get_path(struct kobject *kobj, gfp_t gfp_mask) return path; } +EXPORT_SYMBOL_GPL(kobject_get_path); /** * kobject_init - initialize object. -- cgit v1.2.3 From 817e6ba3623de9cdc66c6aba90eae30b5588ff11 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 11 Oct 2006 01:44:28 -0400 Subject: Input: i8042 - supress ACK/NAKs when blinking during panic This allows using SysRq and not fill logs with complaints from atkbd. Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 09b06e605b50..7e3141f37e32 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -106,6 +106,7 @@ static unsigned char i8042_ctr; static unsigned char i8042_mux_present; static unsigned char i8042_kbd_irq_registered; static unsigned char i8042_aux_irq_registered; +static unsigned char i8042_suppress_kbd_ack; static struct platform_device *i8042_platform_device; static irqreturn_t i8042_interrupt(int irq, void *dev_id); @@ -316,7 +317,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) unsigned char str, data; unsigned int dfl; unsigned int port_no; - int ret; + int ret = 1; spin_lock_irqsave(&i8042_lock, flags); str = i8042_read_status(); @@ -378,10 +379,16 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) dfl & SERIO_PARITY ? ", bad parity" : "", dfl & SERIO_TIMEOUT ? ", timeout" : ""); + if (unlikely(i8042_suppress_kbd_ack)) + if (port_no == I8042_KBD_PORT_NO && + (data == 0xfa || data == 0xfe)) { + i8042_suppress_kbd_ack = 0; + goto out; + } + if (likely(port->exists)) serio_interrupt(port->serio, data, dfl); - ret = 1; out: return IRQ_RETVAL(ret); } @@ -842,11 +849,13 @@ static long i8042_panic_blink(long count) led ^= 0x01 | 0x04; while (i8042_read_status() & I8042_STR_IBF) DELAY; + i8042_suppress_kbd_ack = 1; i8042_write_data(0xed); /* set leds */ DELAY; while (i8042_read_status() & I8042_STR_IBF) DELAY; DELAY; + i8042_suppress_kbd_ack = 1; i8042_write_data(led); DELAY; last_blink = count; -- cgit v1.2.3 From 86255d9d0bede79140f4912482447963f00818c0 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 11 Oct 2006 01:44:46 -0400 Subject: Input: atkbd - supress "too many keys" error message Many users seems to be annoyed by this warning so kill the message and implement a counter exported as a sysfs attribute so we still know what is going on. Make atkbd use attribute groups while we are at it. Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/atkbd.c | 54 ++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index b6ef9eaad1dc..cbb93669d1ce 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -221,6 +221,7 @@ struct atkbd { unsigned long xl_bit; unsigned int last; unsigned long time; + unsigned long err_count; struct work_struct event_work; struct mutex event_mutex; @@ -234,11 +235,13 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t #define ATKBD_DEFINE_ATTR(_name) \ static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \ -static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \ +static ssize_t atkbd_do_show_##_name(struct device *d, \ + struct device_attribute *attr, char *b) \ { \ return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ } \ -static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s) \ +static ssize_t atkbd_do_set_##_name(struct device *d, \ + struct device_attribute *attr, const char *b, size_t s) \ { \ return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ } \ @@ -251,6 +254,32 @@ ATKBD_DEFINE_ATTR(set); ATKBD_DEFINE_ATTR(softrepeat); ATKBD_DEFINE_ATTR(softraw); +#define ATKBD_DEFINE_RO_ATTR(_name) \ +static ssize_t atkbd_show_##_name(struct atkbd *, char *); \ +static ssize_t atkbd_do_show_##_name(struct device *d, \ + struct device_attribute *attr, char *b) \ +{ \ + return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \ +} \ +static struct device_attribute atkbd_attr_##_name = \ + __ATTR(_name, S_IRUGO, atkbd_do_show_##_name, NULL); + +ATKBD_DEFINE_RO_ATTR(err_count); + +static struct attribute *atkbd_attributes[] = { + &atkbd_attr_extra.attr, + &atkbd_attr_scroll.attr, + &atkbd_attr_set.attr, + &atkbd_attr_softrepeat.attr, + &atkbd_attr_softraw.attr, + &atkbd_attr_err_count.attr, + NULL +}; + +static struct attribute_group atkbd_attribute_group = { + .attrs = atkbd_attributes, +}; + static const unsigned int xl_table[] = { ATKBD_RET_BAT, ATKBD_RET_ERR, ATKBD_RET_ACK, ATKBD_RET_NAK, ATKBD_RET_HANJA, ATKBD_RET_HANGEUL, @@ -396,7 +425,10 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, add_release_event = 1; break; case ATKBD_RET_ERR: + atkbd->err_count++; +#ifdef ATKBD_DEBUG printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); +#endif goto out; } @@ -786,12 +818,7 @@ static void atkbd_disconnect(struct serio *serio) synchronize_sched(); /* Allow atkbd_interrupt()s to complete. */ flush_scheduled_work(); - device_remove_file(&serio->dev, &atkbd_attr_extra); - device_remove_file(&serio->dev, &atkbd_attr_scroll); - device_remove_file(&serio->dev, &atkbd_attr_set); - device_remove_file(&serio->dev, &atkbd_attr_softrepeat); - device_remove_file(&serio->dev, &atkbd_attr_softraw); - + sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); input_unregister_device(atkbd->dev); serio_close(serio); serio_set_drvdata(serio, NULL); @@ -961,11 +988,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) atkbd_set_keycode_table(atkbd); atkbd_set_device_attrs(atkbd); - device_create_file(&serio->dev, &atkbd_attr_extra); - device_create_file(&serio->dev, &atkbd_attr_scroll); - device_create_file(&serio->dev, &atkbd_attr_set); - device_create_file(&serio->dev, &atkbd_attr_softrepeat); - device_create_file(&serio->dev, &atkbd_attr_softraw); + sysfs_create_group(&serio->dev.kobj, &atkbd_attribute_group); atkbd_enable(atkbd); @@ -1259,6 +1282,11 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co return count; } +static ssize_t atkbd_show_err_count(struct atkbd *atkbd, char *buf) +{ + return sprintf(buf, "%lu\n", atkbd->err_count); +} + static int __init atkbd_init(void) { -- cgit v1.2.3 From 88aa0103e408616e433c209e80169ab8d6eda99e Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Wed, 11 Oct 2006 01:45:31 -0400 Subject: Input: serio - add lockdep annotations Signed-off-by: Jiri Kosina Acked-by: Peter Zijlstra Signed-off-by: Dmitry Torokhov --- drivers/input/serio/libps2.c | 3 ++- drivers/input/serio/serio.c | 6 +++++- include/linux/serio.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index dcb16b5cbec0..e5b1b60757bb 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c @@ -189,7 +189,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) return -1; } - mutex_lock_nested(&ps2dev->cmd_mutex, SINGLE_DEPTH_NESTING); + mutex_lock(&ps2dev->cmd_mutex); serio_pause_rx(ps2dev->serio); ps2dev->flags = command == PS2_CMD_GETID ? PS2_FLAG_WAITID : 0; @@ -296,6 +296,7 @@ EXPORT_SYMBOL(ps2_schedule_command); void ps2_init(struct ps2dev *ps2dev, struct serio *serio) { mutex_init(&ps2dev->cmd_mutex); + lockdep_set_subclass(&ps2dev->cmd_mutex, serio->depth); init_waitqueue_head(&ps2dev->wait); ps2dev->serio = serio; } diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 960fae3c3cea..480fdc5d20b3 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -538,8 +538,12 @@ static void serio_init_port(struct serio *serio) "serio%ld", (long)atomic_inc_return(&serio_no) - 1); serio->dev.bus = &serio_bus; serio->dev.release = serio_release_port; - if (serio->parent) + if (serio->parent) { serio->dev.parent = &serio->parent->dev; + serio->depth = serio->parent->depth + 1; + } else + serio->depth = 0; + lockdep_set_subclass(&serio->lock, serio->depth); } /* diff --git a/include/linux/serio.h b/include/linux/serio.h index 3a697cc6ecae..b99c5ca9708d 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h @@ -41,6 +41,7 @@ struct serio { void (*stop)(struct serio *); struct serio *parent, *child; + unsigned int depth; /* level of nesting in serio hierarchy */ struct serio_driver *drv; /* accessed from interrupt, must be protected by serio->lock and serio->sem */ struct mutex drv_mutex; /* protects serio->drv so attributes can pin driver */ -- cgit v1.2.3 From 80060362aaefec507ac2d7a7bd156716d7a7ca91 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 10 Oct 2006 03:40:44 -0400 Subject: [WATCHDOG] watchdog/iTCO_wdt: fix bug related to gcc uninit warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc emits the following warning: drivers/char/watchdog/iTCO_wdt.c: In function â€iTCO_wdt_ioctl’: drivers/char/watchdog/iTCO_wdt.c:429: warning: â€time_left’ may be used uninitialized in this function This indicates a condition near enough to a bug, to want to fix. iTCO_wdt_get_timeleft() stores a value in 'time_left' iff iTCO_version==(1 or 2). This driver only supports versions 1 or 2, so this is ok. However, since (a) the return value of iTCO_wdt_get_timeleft() is handled anyway, (b) it fixes the warning, and (c) it future-proofs the driver, we go ahead and add the obvious return value. Signed-off-by: Jeff Garzik Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/char/watchdog/iTCO_wdt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index 505aae917764..b6f29cb8bd39 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -368,7 +368,8 @@ static int iTCO_wdt_get_timeleft (int *time_left) spin_unlock(&iTCO_wdt_private.io_lock); *time_left = (val8 * 6) / 10; - } + } else + return -EINVAL; return 0; } @@ -439,7 +440,6 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, { int new_options, retval = -EINVAL; int new_heartbeat; - int time_left; void __user *argp = (void __user *)arg; int __user *p = argp; static struct watchdog_info ident = { @@ -499,6 +499,8 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, case WDIOC_GETTIMELEFT: { + int time_left; + if (iTCO_wdt_get_timeleft(&time_left)) return -EINVAL; -- cgit v1.2.3 From 0a66045bcfd3a7ba5d1253f9f305b78bf636ac57 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 12 Oct 2006 01:06:23 -0400 Subject: Input: serio core - handle errors returned by device_bind_driver() Signed-off-by: Dmitry Torokhov --- drivers/input/serio/serio.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 480fdc5d20b3..211943f85cb6 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c @@ -118,6 +118,8 @@ static int serio_match_port(const struct serio_device_id *ids, struct serio *ser static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) { + int error; + down_write(&serio_bus.subsys.rwsem); if (serio_match_port(drv->id_table, serio)) { @@ -126,9 +128,19 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) serio->dev.driver = NULL; goto out; } - device_bind_driver(&serio->dev); + error = device_bind_driver(&serio->dev); + if (error) { + printk(KERN_WARNING + "serio: device_bind_driver() failed " + "for %s (%s) and %s, error: %d\n", + serio->phys, serio->name, + drv->description, error); + serio_disconnect_driver(serio); + serio->dev.driver = NULL; + goto out; + } } -out: + out: up_write(&serio_bus.subsys.rwsem); } -- cgit v1.2.3 From 23de1510e2468ea349354889097e018d4e8770c5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 12 Oct 2006 01:06:34 -0400 Subject: Input: gameport core - handle errors returned by device_bind_driver() Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/gameport.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 3f47ae55c6f3..a0af97efe6ac 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c @@ -191,6 +191,8 @@ static void gameport_run_poll_handler(unsigned long d) static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv) { + int error; + down_write(&gameport_bus.subsys.rwsem); gameport->dev.driver = &drv->driver; @@ -198,8 +200,20 @@ static void gameport_bind_driver(struct gameport *gameport, struct gameport_driv gameport->dev.driver = NULL; goto out; } - device_bind_driver(&gameport->dev); -out: + + error = device_bind_driver(&gameport->dev); + if (error) { + printk(KERN_WARNING + "gameport: device_bind_driver() failed " + "for %s (%s) and %s, error: %d\n", + gameport->phys, gameport->name, + drv->description, error); + drv->disconnect(gameport); + gameport->dev.driver = NULL; + goto out; + } + + out: up_write(&gameport_bus.subsys.rwsem); } -- cgit v1.2.3 From b435fdcda126db42343b8055d04a0a27c229717b Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 12 Oct 2006 01:06:53 -0400 Subject: Input: fm801-gp - handle errors from pci_enable_device() Signed-off-by: Jeff Garzik Signed-off-by: Dmitry Torokhov --- drivers/input/gameport/fm801-gp.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 90de5afe03c2..1dec00e20dbc 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c @@ -82,17 +82,19 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device { struct fm801_gp *gp; struct gameport *port; + int error; gp = kzalloc(sizeof(struct fm801_gp), GFP_KERNEL); port = gameport_allocate_port(); if (!gp || !port) { printk(KERN_ERR "fm801-gp: Memory allocation failed\n"); - kfree(gp); - gameport_free_port(port); - return -ENOMEM; + error = -ENOMEM; + goto err_out_free; } - pci_enable_device(pci); + error = pci_enable_device(pci); + if (error) + goto err_out_free; port->open = fm801_gp_open; #ifdef HAVE_COOKED @@ -108,9 +110,8 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device if (!gp->res_port) { printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n", port->io, port->io + 0x0f); - gameport_free_port(port); - kfree(gp); - return -EBUSY; + error = -EBUSY; + goto err_out_disable_dev; } pci_set_drvdata(pci, gp); @@ -119,6 +120,13 @@ static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device gameport_register_port(port); return 0; + + err_out_disable_dev: + pci_disable_device(pci); + err_out_free: + gameport_free_port(port); + kfree(gp); + return error; } static void __devexit fm801_gp_remove(struct pci_dev *pci) -- cgit v1.2.3 From 733b736c91dd2c556f35dffdcf77e667cf10cefc Mon Sep 17 00:00:00 2001 From: Arnaud Patard Date: Thu, 12 Oct 2006 22:33:31 +0200 Subject: r8169: fix infinite loop during hotplug Bug reported for PCMCIA. Signed-off-by: Arnaud Patard Signed-off-by: Francois Romieu --- drivers/net/r8169.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index c7309e98f89d..c2c9a86e445c 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2702,6 +2702,7 @@ static void rtl8169_down(struct net_device *dev) struct rtl8169_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->mmio_addr; unsigned int poll_locked = 0; + unsigned int intrmask; rtl8169_delete_timer(dev); @@ -2740,8 +2741,11 @@ core_down: * 2) dev->change_mtu * -> rtl8169_poll can not be issued again and re-enable the * interruptions. Let's simply issue the IRQ down sequence again. + * + * No loop if hotpluged or major error (0xffff). */ - if (RTL_R16(IntrMask)) + intrmask = RTL_R16(IntrMask); + if (intrmask && (intrmask != 0xffff)) goto core_down; rtl8169_tx_clear(tp); -- cgit v1.2.3 From bdcff3458f5448fac585a6174ad9342f361b5135 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Tue, 26 Sep 2006 17:49:30 +0200 Subject: [WATCHDOG] Atmel AT91RM9200 rename. The new Atmel AT91SAM9261 and AT91SAM9260 processors use a different internal watchdog peripheral. This watchdog driver is therefore AT91RM9200-specific. This patch renames at91_wdt.c to at91rm9200_wdt.c, and changes the name of the configuration option. Signed-off-by: Andrew Victor Signed-off-by: Wim Van Sebroeck --- arch/arm/configs/at91rm9200dk_defconfig | 2 +- arch/arm/configs/at91rm9200ek_defconfig | 2 +- arch/arm/configs/csb337_defconfig | 2 +- arch/arm/configs/csb637_defconfig | 2 +- arch/arm/configs/kafa_defconfig | 2 +- arch/arm/configs/onearm_defconfig | 2 +- drivers/char/watchdog/Kconfig | 2 +- drivers/char/watchdog/Makefile | 2 +- drivers/char/watchdog/at91_wdt.c | 287 -------------------------------- drivers/char/watchdog/at91rm9200_wdt.c | 287 ++++++++++++++++++++++++++++++++ 10 files changed, 295 insertions(+), 295 deletions(-) delete mode 100644 drivers/char/watchdog/at91_wdt.c create mode 100644 drivers/char/watchdog/at91rm9200_wdt.c (limited to 'drivers') diff --git a/arch/arm/configs/at91rm9200dk_defconfig b/arch/arm/configs/at91rm9200dk_defconfig index c82e4667f45e..b43041476e02 100644 --- a/arch/arm/configs/at91rm9200dk_defconfig +++ b/arch/arm/configs/at91rm9200dk_defconfig @@ -577,7 +577,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/at91rm9200ek_defconfig b/arch/arm/configs/at91rm9200ek_defconfig index b983fc59aa42..d96fc8386e2f 100644 --- a/arch/arm/configs/at91rm9200ek_defconfig +++ b/arch/arm/configs/at91rm9200ek_defconfig @@ -558,7 +558,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/csb337_defconfig b/arch/arm/configs/csb337_defconfig index a2d6fd398f16..20e68250d835 100644 --- a/arch/arm/configs/csb337_defconfig +++ b/arch/arm/configs/csb337_defconfig @@ -615,7 +615,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/csb637_defconfig b/arch/arm/configs/csb637_defconfig index 2a1ac6c60abc..df8595ac031f 100644 --- a/arch/arm/configs/csb637_defconfig +++ b/arch/arm/configs/csb637_defconfig @@ -615,7 +615,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/arch/arm/configs/kafa_defconfig b/arch/arm/configs/kafa_defconfig index 54fcd75779da..a4cdafc1548a 100644 --- a/arch/arm/configs/kafa_defconfig +++ b/arch/arm/configs/kafa_defconfig @@ -560,7 +560,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # CONFIG_NVRAM is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set diff --git a/arch/arm/configs/onearm_defconfig b/arch/arm/configs/onearm_defconfig index cb1d94f9049e..9b9f2155af35 100644 --- a/arch/arm/configs/onearm_defconfig +++ b/arch/arm/configs/onearm_defconfig @@ -607,7 +607,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set -CONFIG_AT91_WATCHDOG=y +CONFIG_AT91RM9200_WATCHDOG=y # # USB-based Watchdog Cards diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 847a26064b68..529f0a706909 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -60,7 +60,7 @@ config SOFT_WATCHDOG # ARM Architecture -config AT91_WATCHDOG +config AT91RM9200_WATCHDOG tristate "AT91RM9200 watchdog" depends on WATCHDOG && ARCH_AT91RM9200 help diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index ee3474190e23..36440497047c 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o # ARM Architecture -obj-$(CONFIG_AT91_WATCHDOG) += at91_wdt.o +obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o diff --git a/drivers/char/watchdog/at91_wdt.c b/drivers/char/watchdog/at91_wdt.c deleted file mode 100644 index 4e7a1145e78f..000000000000 --- a/drivers/char/watchdog/at91_wdt.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Watchdog driver for Atmel AT91RM9200 (Thunder) - * - * Copyright (C) 2003 SAN People (Pty) Ltd - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define WDT_DEFAULT_TIME 5 /* seconds */ -#define WDT_MAX_TIME 256 /* seconds */ - -static int wdt_time = WDT_DEFAULT_TIME; -static int nowayout = WATCHDOG_NOWAYOUT; - -module_param(wdt_time, int, 0); -MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); - -#ifdef CONFIG_WATCHDOG_NOWAYOUT -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -#endif - - -static unsigned long at91wdt_busy; - -/* ......................................................................... */ - -/* - * Disable the watchdog. - */ -static void inline at91_wdt_stop(void) -{ - at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); -} - -/* - * Enable and reset the watchdog. - */ -static void inline at91_wdt_start(void) -{ - at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); -} - -/* - * Reload the watchdog timer. (ie, pat the watchdog) - */ -static void inline at91_wdt_reload(void) -{ - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); -} - -/* ......................................................................... */ - -/* - * Watchdog device is opened, and watchdog starts running. - */ -static int at91_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &at91wdt_busy)) - return -EBUSY; - - at91_wdt_start(); - return nonseekable_open(inode, file); -} - -/* - * Close the watchdog device. - * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also - * disabled. - */ -static int at91_wdt_close(struct inode *inode, struct file *file) -{ - if (!nowayout) - at91_wdt_stop(); /* Disable the watchdog when file is closed */ - - clear_bit(0, &at91wdt_busy); - return 0; -} - -/* - * Change the watchdog time interval. - */ -static int at91_wdt_settimeout(int new_time) -{ - /* - * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz - * - * Since WDV is a 16-bit counter, the maximum period is - * 65536 / 0.256 = 256 seconds. - */ - if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) - return -EINVAL; - - /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ - wdt_time = new_time; - return 0; -} - -static struct watchdog_info at91_wdt_info = { - .identity = "at91 watchdog", - .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, -}; - -/* - * Handle commands from user-space. - */ -static int at91_wdt_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - void __user *argp = (void __user *)arg; - int __user *p = argp; - int new_value; - - switch(cmd) { - case WDIOC_KEEPALIVE: - at91_wdt_reload(); /* pat the watchdog */ - return 0; - - case WDIOC_GETSUPPORT: - return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; - - case WDIOC_SETTIMEOUT: - if (get_user(new_value, p)) - return -EFAULT; - - if (at91_wdt_settimeout(new_value)) - return -EINVAL; - - /* Enable new time value */ - at91_wdt_start(); - - /* Return current value */ - return put_user(wdt_time, p); - - case WDIOC_GETTIMEOUT: - return put_user(wdt_time, p); - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, p); - - case WDIOC_SETOPTIONS: - if (get_user(new_value, p)) - return -EFAULT; - - if (new_value & WDIOS_DISABLECARD) - at91_wdt_stop(); - if (new_value & WDIOS_ENABLECARD) - at91_wdt_start(); - return 0; - - default: - return -ENOTTY; - } -} - -/* - * Pat the watchdog whenever device is written to. - */ -static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - at91_wdt_reload(); /* pat the watchdog */ - return len; -} - -/* ......................................................................... */ - -static const struct file_operations at91wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = at91_wdt_ioctl, - .open = at91_wdt_open, - .release = at91_wdt_close, - .write = at91_wdt_write, -}; - -static struct miscdevice at91wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &at91wdt_fops, -}; - -static int __init at91wdt_probe(struct platform_device *pdev) -{ - int res; - - if (at91wdt_miscdev.dev) - return -EBUSY; - at91wdt_miscdev.dev = &pdev->dev; - - res = misc_register(&at91wdt_miscdev); - if (res) - return res; - - printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); - return 0; -} - -static int __exit at91wdt_remove(struct platform_device *pdev) -{ - int res; - - res = misc_deregister(&at91wdt_miscdev); - if (!res) - at91wdt_miscdev.dev = NULL; - - return res; -} - -static void at91wdt_shutdown(struct platform_device *pdev) -{ - at91_wdt_stop(); -} - -#ifdef CONFIG_PM - -static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) -{ - at91_wdt_stop(); - return 0; -} - -static int at91wdt_resume(struct platform_device *pdev) -{ - if (at91wdt_busy) - at91_wdt_start(); - return 0; -} - -#else -#define at91wdt_suspend NULL -#define at91wdt_resume NULL -#endif - -static struct platform_driver at91wdt_driver = { - .probe = at91wdt_probe, - .remove = __exit_p(at91wdt_remove), - .shutdown = at91wdt_shutdown, - .suspend = at91wdt_suspend, - .resume = at91wdt_resume, - .driver = { - .name = "at91_wdt", - .owner = THIS_MODULE, - }, -}; - -static int __init at91_wdt_init(void) -{ - /* Check that the heartbeat value is within range; if not reset to the default */ - if (at91_wdt_settimeout(wdt_time)) { - at91_wdt_settimeout(WDT_DEFAULT_TIME); - pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); - } - - return platform_driver_register(&at91wdt_driver); -} - -static void __exit at91_wdt_exit(void) -{ - platform_driver_unregister(&at91wdt_driver); -} - -module_init(at91_wdt_init); -module_exit(at91_wdt_exit); - -MODULE_AUTHOR("Andrew Victor"); -MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/drivers/char/watchdog/at91rm9200_wdt.c b/drivers/char/watchdog/at91rm9200_wdt.c new file mode 100644 index 000000000000..4e7a1145e78f --- /dev/null +++ b/drivers/char/watchdog/at91rm9200_wdt.c @@ -0,0 +1,287 @@ +/* + * Watchdog driver for Atmel AT91RM9200 (Thunder) + * + * Copyright (C) 2003 SAN People (Pty) Ltd + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define WDT_DEFAULT_TIME 5 /* seconds */ +#define WDT_MAX_TIME 256 /* seconds */ + +static int wdt_time = WDT_DEFAULT_TIME; +static int nowayout = WATCHDOG_NOWAYOUT; + +module_param(wdt_time, int, 0); +MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); + +#ifdef CONFIG_WATCHDOG_NOWAYOUT +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +#endif + + +static unsigned long at91wdt_busy; + +/* ......................................................................... */ + +/* + * Disable the watchdog. + */ +static void inline at91_wdt_stop(void) +{ + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); +} + +/* + * Enable and reset the watchdog. + */ +static void inline at91_wdt_start(void) +{ + at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + +/* + * Reload the watchdog timer. (ie, pat the watchdog) + */ +static void inline at91_wdt_reload(void) +{ + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + +/* ......................................................................... */ + +/* + * Watchdog device is opened, and watchdog starts running. + */ +static int at91_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &at91wdt_busy)) + return -EBUSY; + + at91_wdt_start(); + return nonseekable_open(inode, file); +} + +/* + * Close the watchdog device. + * If CONFIG_WATCHDOG_NOWAYOUT is NOT defined then the watchdog is also + * disabled. + */ +static int at91_wdt_close(struct inode *inode, struct file *file) +{ + if (!nowayout) + at91_wdt_stop(); /* Disable the watchdog when file is closed */ + + clear_bit(0, &at91wdt_busy); + return 0; +} + +/* + * Change the watchdog time interval. + */ +static int at91_wdt_settimeout(int new_time) +{ + /* + * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz + * + * Since WDV is a 16-bit counter, the maximum period is + * 65536 / 0.256 = 256 seconds. + */ + if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) + return -EINVAL; + + /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ + wdt_time = new_time; + return 0; +} + +static struct watchdog_info at91_wdt_info = { + .identity = "at91 watchdog", + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, +}; + +/* + * Handle commands from user-space. + */ +static int at91_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int __user *p = argp; + int new_value; + + switch(cmd) { + case WDIOC_KEEPALIVE: + at91_wdt_reload(); /* pat the watchdog */ + return 0; + + case WDIOC_GETSUPPORT: + return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; + + case WDIOC_SETTIMEOUT: + if (get_user(new_value, p)) + return -EFAULT; + + if (at91_wdt_settimeout(new_value)) + return -EINVAL; + + /* Enable new time value */ + at91_wdt_start(); + + /* Return current value */ + return put_user(wdt_time, p); + + case WDIOC_GETTIMEOUT: + return put_user(wdt_time, p); + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, p); + + case WDIOC_SETOPTIONS: + if (get_user(new_value, p)) + return -EFAULT; + + if (new_value & WDIOS_DISABLECARD) + at91_wdt_stop(); + if (new_value & WDIOS_ENABLECARD) + at91_wdt_start(); + return 0; + + default: + return -ENOTTY; + } +} + +/* + * Pat the watchdog whenever device is written to. + */ +static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + at91_wdt_reload(); /* pat the watchdog */ + return len; +} + +/* ......................................................................... */ + +static const struct file_operations at91wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = at91_wdt_ioctl, + .open = at91_wdt_open, + .release = at91_wdt_close, + .write = at91_wdt_write, +}; + +static struct miscdevice at91wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &at91wdt_fops, +}; + +static int __init at91wdt_probe(struct platform_device *pdev) +{ + int res; + + if (at91wdt_miscdev.dev) + return -EBUSY; + at91wdt_miscdev.dev = &pdev->dev; + + res = misc_register(&at91wdt_miscdev); + if (res) + return res; + + printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); + return 0; +} + +static int __exit at91wdt_remove(struct platform_device *pdev) +{ + int res; + + res = misc_deregister(&at91wdt_miscdev); + if (!res) + at91wdt_miscdev.dev = NULL; + + return res; +} + +static void at91wdt_shutdown(struct platform_device *pdev) +{ + at91_wdt_stop(); +} + +#ifdef CONFIG_PM + +static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) +{ + at91_wdt_stop(); + return 0; +} + +static int at91wdt_resume(struct platform_device *pdev) +{ + if (at91wdt_busy) + at91_wdt_start(); + return 0; +} + +#else +#define at91wdt_suspend NULL +#define at91wdt_resume NULL +#endif + +static struct platform_driver at91wdt_driver = { + .probe = at91wdt_probe, + .remove = __exit_p(at91wdt_remove), + .shutdown = at91wdt_shutdown, + .suspend = at91wdt_suspend, + .resume = at91wdt_resume, + .driver = { + .name = "at91_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init at91_wdt_init(void) +{ + /* Check that the heartbeat value is within range; if not reset to the default */ + if (at91_wdt_settimeout(wdt_time)) { + at91_wdt_settimeout(WDT_DEFAULT_TIME); + pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); + } + + return platform_driver_register(&at91wdt_driver); +} + +static void __exit at91_wdt_exit(void) +{ + platform_driver_unregister(&at91wdt_driver); +} + +module_init(at91_wdt_init); +module_exit(at91_wdt_exit); + +MODULE_AUTHOR("Andrew Victor"); +MODULE_DESCRIPTION("Watchdog driver for Atmel AT91RM9200"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.2.3 From cbf40d3f04c2c76a58f1183bb4a9a82fefb842e3 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sat, 14 Oct 2006 20:18:47 +0200 Subject: [WATCHDOG] remove experimental on iTCO_wdt.c The iTCO_wdt.c driver has been tested enough. So we can remove the experimental classification. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 529f0a706909..0187b1185323 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -316,13 +316,16 @@ config I8XX_TCO To compile this driver as a module, choose M here: the module will be called i8xx_tco. + Note: This driver will be removed in the near future. Please + use the Intel TCO Timer/Watchdog driver. + config ITCO_WDT - tristate "Intel TCO Timer/Watchdog (EXPERIMENTAL)" - depends on WATCHDOG && (X86 || IA64) && PCI && EXPERIMENTAL + tristate "Intel TCO Timer/Watchdog" + depends on WATCHDOG && (X86 || IA64) && PCI ---help--- Hardware driver for the intel TCO timer based watchdog devices. These drivers are included in the Intel 82801 I/O Controller - Hub family 'from ICH0 up to ICH7) and in the Intel 6300ESB + Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB controller hub. The TCO (Total Cost of Ownership) timer is a watchdog timer @@ -590,7 +593,7 @@ config SH_WDT_MMAP help If you say Y here, user applications will be able to mmap the WDT/CPG registers. -# + # SPARC64 Architecture config WATCHDOG_CP1XXX -- cgit v1.2.3 From 36bd262b3f2ac723dadd20ce35539c8c738877f1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 15 Oct 2006 13:50:02 +0100 Subject: [ARM] Fix Zaurii keyboard/touchscreen drivers The Zaurii drivers were partially fixed up for the IRQ register changes, but unfortunately missed some bits, resulting in build errors. Fix these. Signed-off-by: Russell King --- drivers/input/keyboard/corgikbd.c | 2 +- drivers/input/keyboard/locomokbd.c | 2 +- drivers/input/keyboard/spitzkbd.c | 2 +- drivers/input/touchscreen/corgi_ts.c | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index cb70970625b5..befdd6006b50 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c @@ -207,7 +207,7 @@ static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) static void corgikbd_timer_callback(unsigned long data) { struct corgikbd *corgikbd_data = (struct corgikbd *) data; - corgikbd_scankeyboard(corgikbd_data, NULL); + corgikbd_scankeyboard(corgikbd_data); } /* diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index fd33c9cc3272..5788dbc317bb 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c @@ -186,7 +186,7 @@ static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) static void locomokbd_timer_callback(unsigned long data) { struct locomokbd *locomokbd = (struct locomokbd *) data; - locomokbd_scankeyboard(locomokbd, NULL); + locomokbd_scankeyboard(locomokbd); } static int locomokbd_probe(struct locomo_dev *dev) diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c index 8b18c009e3e0..28b2748e82d0 100644 --- a/drivers/input/keyboard/spitzkbd.c +++ b/drivers/input/keyboard/spitzkbd.c @@ -257,7 +257,7 @@ static void spitzkbd_timer_callback(unsigned long data) { struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; - spitzkbd_scankeyboard(spitzkbd_data, NULL); + spitzkbd_scankeyboard(spitzkbd_data); } /* diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c index ca79b2246195..66121f6a89ad 100644 --- a/drivers/input/touchscreen/corgi_ts.c +++ b/drivers/input/touchscreen/corgi_ts.c @@ -219,7 +219,7 @@ static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) static void corgi_ts_timer(unsigned long data) { struct corgi_ts *corgits_data = (struct corgi_ts *) data; - ts_interrupt_main(corgits_data, 1, NULL); + ts_interrupt_main(corgits_data, 1); } static irqreturn_t ts_interrupt(int irq, void *dev_id) @@ -237,7 +237,7 @@ static int corgits_suspend(struct platform_device *dev, pm_message_t state) if (corgi_ts->pendown) { del_timer_sync(&corgi_ts->timer); corgi_ts->tc.pressure = 0; - new_data(corgi_ts, NULL); + new_data(corgi_ts); corgi_ts->pendown = 0; } corgi_ts->power_mode = PWR_MODE_SUSPEND; -- cgit v1.2.3 From 789fc0adbaf3a3ca95a3894aedacfc01863e8ae3 Mon Sep 17 00:00:00 2001 From: Sven Anders & Marcus Junker Date: Thu, 24 Aug 2006 17:11:50 +0200 Subject: [WATCHDOG] NS pc87413-wdt Watchdog driver New watchdog driver for the NS pc87413-wdt Watchdog Timer. Signed-off-by: Sven Anders Signed-off-by: Marcus Junker Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 14 + drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/pc87413_wdt.c | 610 ++++++++++++++++++++++++++++++++++++ 3 files changed, 625 insertions(+) create mode 100644 drivers/char/watchdog/pc87413_wdt.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index 0187b1185323..d3e99982b69a 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -363,6 +363,20 @@ config SCx200_WDT If compiled as a module, it will be called scx200_wdt. +config PC87413_WDT + tristate "NS PC87413 watchdog" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog on the PC87413 chipset + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. + + To compile this driver as a module, choose M here: the + module will be called pc87413_wdt. + + Most people will say N. + config 60XX_WDT tristate "SBC-60XX Watchdog Timer" depends on WATCHDOG && X86 diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 36440497047c..e6a9f6f1d4b7 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o +obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_SBC8360_WDT) += sbc8360.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c new file mode 100644 index 000000000000..a6d42cf385e6 --- /dev/null +++ b/drivers/char/watchdog/pc87413_wdt.c @@ -0,0 +1,610 @@ +/* + * NS pc87413-wdt Watchdog Timer driver for Linux 2.6.x.x + * + * This code is based on wdt.c with original copyright + * + * (C) Copyright 2006 Marcus Junker, + * and Sven Anders, + * + * 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. + * + * Neither Marcus Junker, Sven Anders nor ANDURAS AG + * admit liability nor provide warranty for any of this software. + * This material is provided "AS-IS" and at no charge. + * + * Release 1.00. + * + */ + + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define WATCHDOG_NAME "pc87413 WDT" +#define PFX WATCHDOG_NAME ": " +#define DPFX WATCHDOG_NAME " - DEBUG: " + +#define WDT_INDEX_IO_PORT (io+0) /* */ +#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) +#define SWC_LDN 0x04 +#define SIOCFG2 0x22 /* Serial IO register */ +#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ +#define WDTO 0x11 /* Watchdog timeout register */ +#define WDCFG 0x12 /* Watchdog config register */ + +#define WD_TIMEOUT 1 /* minutes (1 ... 255) */ + + +static int pc87413_is_open=0; + +/* + * You must set these - there is no sane way to probe for this board. + * You can use pc87413=x to set these now. + */ + + + +/** + * module_params + * + * Setup options. The board isn't really probe-able so we have to + * get the user to tell us the configuration. + */ + +static int io=0x2E; /* Normally used addres on Portwell Boards */ +module_param(io, int, 0); +MODULE_PARM_DESC(wdt_io, WATCHDOG_NAME " io port (default 0x2E)"); + +static int timeout = WD_TIMEOUT; /* in minutes */ +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes. 1<= timeout <=63, default=" __MODULE_STRING(WD_TIMEOUT) "."); + + +/****************************************** + * Helper functions + ******************************************/ + +static void +pc87413_select_wdt_out (void) +{ + + unsigned int cr_data=0; + + /* Select multiple pin,pin55,as WDT output */ + + outb_p(SIOCFG2, WDT_INDEX_IO_PORT); + + cr_data = inb (WDT_DATA_IO_PORT); + + cr_data |= 0x80; /* Set Bit7 to 1*/ + outb_p(SIOCFG2, WDT_INDEX_IO_PORT); + + outb_p(cr_data, WDT_DATA_IO_PORT); + + + #ifdef DEBUG + printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n", cr_data); + #endif +} + +static void +pc87413_enable_swc(void) +{ + + unsigned int cr_data=0; + + /* Step 2: Enable SWC functions */ + + outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */ + outb_p(SWC_LDN, WDT_DATA_IO_PORT); + + outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */ + cr_data = inb (WDT_DATA_IO_PORT); + cr_data |= 0x01; /* Set Bit0 to 1 */ + outb_p(0x30, WDT_INDEX_IO_PORT); + outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */ + + #ifdef DEBUG + printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n"); + #endif +} + +static unsigned int +pc87413_get_swc_base(void) +{ + unsigned int swc_base_addr = 0; + unsigned char addr_l, addr_h = 0; + + /* Step 3: Read SWC I/O Base Address */ + + outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */ + addr_h = inb (WDT_DATA_IO_PORT); + + outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */ + + addr_l = inb (WDT_DATA_IO_PORT); + + + swc_base_addr = (addr_h << 8) + addr_l; + + #ifdef DEBUG + printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d, res %d\n", addr_l, addr_h, swc_base_addr); + #endif + + return swc_base_addr; +} + +static void +pc87413_swc_bank3(unsigned int swc_base_addr) +{ + /* Step 4: Select Bank3 of SWC */ + + outb_p (inb (swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); + + #ifdef DEBUG + printk(KERN_INFO DPFX "Select Bank3 of SWC\n"); + #endif + +} + +static void +pc87413_programm_wdto (unsigned int swc_base_addr, char pc87413_time) +{ + /* Step 5: Programm WDTO, Twd. */ + + outb_p (pc87413_time, swc_base_addr + WDTO); + + #ifdef DEBUG + printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time); + #endif +} + +static void +pc87413_enable_wden (unsigned int swc_base_addr) +{ + /* Step 6: Enable WDEN */ + + outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL); + + #ifdef DEBUG + printk(KERN_INFO DPFX "Enable WDEN\n"); + #endif +} + +static void +pc87413_enable_sw_wd_tren (unsigned int swc_base_addr) +{ + /* Enable SW_WD_TREN */ + + outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG); + + #ifdef DEBUG + printk(KERN_INFO DPFX "Enable SW_WD_TREN\n"); + #endif +} + +static void +pc87413_disable_sw_wd_tren (unsigned int swc_base_addr) +{ + /* Disable SW_WD_TREN */ + + outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG); + + #ifdef DEBUG + printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n"); + #endif +} + + +static void +pc87413_enable_sw_wd_trg (unsigned int swc_base_addr) +{ + + /* Enable SW_WD_TRG */ + + outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL); + + #ifdef DEBUG + printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n"); + #endif +} + +static void +pc87413_disable_sw_wd_trg (unsigned int swc_base_addr) +{ + + /* Disable SW_WD_TRG */ + + outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL); + + #ifdef DEBUG + printk(KERN_INFO DPFX "Disable SW_WD_TRG\n"); + #endif +} + + + +static void +pc87413_disable(void) +{ + unsigned int swc_base_addr; + + pc87413_select_wdt_out(); + pc87413_enable_swc(); + swc_base_addr = pc87413_get_swc_base(); + pc87413_swc_bank3(swc_base_addr); + pc87413_disable_sw_wd_tren(swc_base_addr); + pc87413_disable_sw_wd_trg(swc_base_addr); + pc87413_programm_wdto(swc_base_addr, 0); +} + + +static void +pc87413_refresh(char pc87413_time) +{ + unsigned int swc_base_addr; + + pc87413_select_wdt_out(); + pc87413_enable_swc(); + swc_base_addr = pc87413_get_swc_base(); + pc87413_swc_bank3(swc_base_addr); + pc87413_disable_sw_wd_tren(swc_base_addr); + pc87413_disable_sw_wd_trg(swc_base_addr); + pc87413_programm_wdto(swc_base_addr, pc87413_time); + pc87413_enable_wden(swc_base_addr); + pc87413_enable_sw_wd_tren(swc_base_addr); + pc87413_enable_sw_wd_trg(swc_base_addr); +} + + +static void +pc87413_enable(char pc87413_time) +{ + unsigned int swc_base_addr; + + pc87413_select_wdt_out(); + pc87413_enable_swc(); + swc_base_addr = pc87413_get_swc_base(); + pc87413_swc_bank3(swc_base_addr); + pc87413_programm_wdto(swc_base_addr, pc87413_time); + pc87413_enable_wden(swc_base_addr); + pc87413_enable_sw_wd_tren(swc_base_addr); + pc87413_enable_sw_wd_trg(swc_base_addr); + +} + + +/******************************************* + * Kernel methods. + *******************************************/ + + +/** + * pc87413_status: + * + * Extract the status information from a WDT watchdog device. There are + * several board variants so we have to know which bits are valid. Some + * bits default to one and some to zero in order to be maximally painful. + * + * we then map the bits onto the status ioctl flags. + */ + +static int pc87413_status(void) +{ + /* Not supported */ + + return 1; +} + +static long long pc87413_llseek(struct file *file, long long offset, int origin) +{ + return -ESPIPE; +} + +/** + * pc87413_write: + * @file: file handle to the watchdog + * @buf: buffer to write (unused as data does not matter here + * @count: count of bytes + * @ppos: pointer to the position to write. No seeks allowed + * + * A write to a watchdog device is defined as a keepalive signal. Any + * write of data will do, as we we don't define content meaning. + */ + +static ssize_t +pc87413_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) +{ + if (count) { + pc87413_refresh (WD_TIMEOUT); + #ifdef DEBUG + printk(KERN_INFO DPFX "Write\n"); + #endif + } + return count; +} + +/* + * Read reports the temperature in degrees Fahrenheit. + */ +static ssize_t +pc87413_read(struct file *file, char *buf, size_t count, loff_t *ptr) +{ + +// char timeout; +// +// outb_p(0x08, WDT_EFER); /* Select locical device 8 */ +// outb_p(0x0F6, WDT_EFER); /* Select CRF6 */ +// timeout = inb(WDT_EFDR); /* Read Timeout counter from CRF6 */ + + +// if(copy_to_user(buf,&timeout,1)) +// return -EFAULT; + return 1; + + +} + + /** + * pc87413_ioctl: + * @inode: inode of the device + * @file: file handle to the device + * @cmd: watchdog command + * @arg: argument pointer + * + * The watchdog API defines a common set of functions for all watchdogs + * according to their available features. We only actually usefully support + * querying capabilities and current status. + */ + +static int +pc87413_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + static struct watchdog_info ident= + { + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "pc87413(HF/F)" + }; + + ident.options=1; /* Mask down to the card we have */ + + switch(cmd) + { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + case WDIOC_GETSTATUS: + return put_user(pc87413_status(),(int *)arg); + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + pc87413_refresh(WD_TIMEOUT); + #ifdef DEBUG + printk(KERN_INFO DPFX "keepalive\n"); + #endif + return 0; + } +} + +/** + * pc87413_open: + * @inode: inode of device + * @file: file handle to device + * + * One of our two misc devices has been opened. The watchdog device is + * single open and on opening we load the counters. Counter zero is a + * 100Hz cascade, into counter 1 which downcounts to reboot. When the + * counter triggers counter 2 downcounts the length of the reset pulse + * which set set to be as long as possible. + */ + +static int +pc87413_open(struct inode *inode, struct file *file) +{ + switch(MINOR(inode->i_rdev)) + { + case WATCHDOG_MINOR: + if(pc87413_is_open) + return -EBUSY; + /* + * Activate + */ + + pc87413_is_open=1; + pc87413_refresh(WD_TIMEOUT); + #ifdef DEBUG + printk(KERN_INFO DPFX "Open\n"); + #endif + return 0; + case TEMP_MINOR: + return 0; + default: + return -ENODEV; + } +} + +/** + * pc87413_close: + * @inode: inode to board + * @file: file handle to board + * + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. + */ + +static int +pc87413_release(struct inode *inode, struct file *file) +{ + if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) + { +#ifndef CONFIG_WATCHDOG_NOWAYOUT + pc87413_disable(); +#endif + pc87413_is_open=0; + #ifdef DEBUG + printk(KERN_INFO DPFX "Release\n"); + #endif + } + return 0; +} + +/** + * notify_sys: + * @this: our notifier block + * @code: the event being reported + * @unused: unused + * + * Our notifier is called on system shutdowns. We want to turn the card + * off at reboot otherwise the machine will reboot again during memory + * test or worse yet during the following fsck. This would suck, in fact + * trust me - if it happens it does suck. + */ + +static int +pc87413_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if(code==SYS_DOWN || code==SYS_HALT) + { + /* Turn the card off */ + pc87413_disable(); + } + return NOTIFY_DONE; +} + + +/***************************************************** + * Kernel Interfaces + *****************************************************/ + + +static struct file_operations pc87413_fops = { + .owner = THIS_MODULE, + .llseek = pc87413_llseek, + .read = pc87413_read, + .write = pc87413_write, + .ioctl = pc87413_ioctl, + .open = pc87413_open, + .release = pc87413_release, +}; + +static struct miscdevice pc87413_miscdev= +{ + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &pc87413_fops +}; + +/* + * The WDT card needs to learn about soft shutdowns in order to + * turn the timebomb registers off. + */ + +static struct notifier_block pc87413_notifier= +{ + pc87413_notify_sys, + NULL, + 0 +}; + + +/** + * pc87413_exit: + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +static void +pc87413_exit(void) +{ + pc87413_disable(); + misc_deregister(&pc87413_miscdev); + unregister_reboot_notifier(&pc87413_notifier); + /* release_region(io,2); */ +} + + +/** + * pc87413_init: + * + * Set up the WDT watchdog board. All we have to do is grab the + * resources we require and bitch if anyone beat us to them. + * The open() function will actually kick the board off. + */ + +static int +pc87413_init(void) +{ + int ret; + + printk(KERN_INFO PFX "Version 1.00 at io 0x%X\n", WDT_INDEX_IO_PORT); + + + /* request_region(io, 2, "pc87413"); */ + + + ret = register_reboot_notifier(&pc87413_notifier); + if (ret != 0) { + printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); + } + + + + ret = misc_register(&pc87413_miscdev); + + if (ret != 0) { + printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&pc87413_notifier); + return ret; + } + + printk (KERN_INFO PFX "initialized. timeout=%d min \n", timeout); + + + pc87413_enable(WD_TIMEOUT); + + return 0; +} + + +module_init(pc87413_init); +module_exit(pc87413_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Marcus Junker , Sven Anders "); +MODULE_DESCRIPTION("PC87413 WDT driver"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); + -- cgit v1.2.3 From 18088748d2a493ce9f6adf0be7f833b04041807e Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Wed, 4 Oct 2006 14:56:44 +0200 Subject: [AGPGART] uninorth: Add module param 'aperture' for aperture size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In contrast to most if not all PC BIOSes, OpenFirmware (OF) on PowerMacs with UniNorth bridges does not allow changing the aperture size. The size set up by OF is usually 16 MB, which is too low for graphics intensive environments. Hence, add a module parameter that allows changing the aperture size at driver initialization time. When the parameter is not specified, the default is 32 MB. Signed-off-by: Michel Dänzer Acked-by: Benjamin Herrenschmidt Signed-off-by: Dave Jones --- drivers/char/agp/uninorth-agp.c | 54 ++++++++++++++++++++++++++--------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 91b71e750ee1..dffc19382f7e 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -27,32 +27,42 @@ static int uninorth_rev; static int is_u3; +static char __devinitdata *aperture = NULL; static int uninorth_fetch_size(void) { - int i; - u32 temp; - struct aper_size_info_32 *values; - - pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_BASE, &temp); - temp &= ~(0xfffff000); - values = A_SIZE_32(agp_bridge->driver->aperture_sizes); - - for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { - if (temp == values[i].size_value) { - agp_bridge->previous_size = - agp_bridge->current_size = (void *) (values + i); - agp_bridge->aperture_size_idx = i; - return values[i].size; + int i, size = 0; + struct aper_size_info_32 *values = + A_SIZE_32(agp_bridge->driver->aperture_sizes); + + if (aperture) { + char *save = aperture; + + size = memparse(aperture, &aperture) >> 20; + aperture = save; + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) + if (size == values[i].size) + break; + + if (i == agp_bridge->driver->num_aperture_sizes) { + printk(KERN_ERR PFX "Invalid aperture size, using" + " default\n"); + size = 0; + aperture = NULL; } } - agp_bridge->previous_size = - agp_bridge->current_size = (void *) (values + 1); - agp_bridge->aperture_size_idx = 1; - return values[1].size; + if (!size) { + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) + if (values[i].size == 32) + break; + } - return 0; + agp_bridge->previous_size = + agp_bridge->current_size = (void *)(values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; } static void uninorth_tlbflush(struct agp_memory *mem) @@ -683,5 +693,11 @@ static void __exit agp_uninorth_cleanup(void) module_init(agp_uninorth_init); module_exit(agp_uninorth_cleanup); +module_param(aperture, charp, 0); +MODULE_PARM_DESC(aperture, + "Aperture size, must be power of two between 4MB and an\n" + "\t\tupper limit specific to the UniNorth revision.\n" + "\t\tDefault: 32M"); + MODULE_AUTHOR("Ben Herrenschmidt & Paul Mackerras"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 3f5306927d800306ebba542438cfdf1a1c418376 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 17:31:19 +0200 Subject: [Bluetooth] Use work queue to trigger URB submission The bcm203x firmware loading driver uses a timer to trigger the URB submission. It is better to use a work queue instead. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bcm203x.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bcm203x.c b/drivers/bluetooth/bcm203x.c index 67cdda43f229..516751754aa9 100644 --- a/drivers/bluetooth/bcm203x.c +++ b/drivers/bluetooth/bcm203x.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include @@ -43,7 +42,7 @@ #define BT_DBG(D...) #endif -#define VERSION "1.0" +#define VERSION "1.1" static int ignore = 0; @@ -72,7 +71,7 @@ struct bcm203x_data { unsigned long state; - struct timer_list timer; + struct work_struct work; struct urb *urb; unsigned char *buffer; @@ -105,7 +104,7 @@ static void bcm203x_complete(struct urb *urb) data->state = BCM203X_SELECT_MEMORY; - mod_timer(&data->timer, jiffies + (HZ / 10)); + schedule_work(&data->work); break; case BCM203X_SELECT_MEMORY: @@ -158,9 +157,9 @@ static void bcm203x_complete(struct urb *urb) } } -static void bcm203x_timer(unsigned long user_data) +static void bcm203x_work(void *user_data) { - struct bcm203x_data *data = (struct bcm203x_data *) user_data; + struct bcm203x_data *data = user_data; if (usb_submit_urb(data->urb, GFP_ATOMIC) < 0) BT_ERR("Can't submit URB"); @@ -247,13 +246,11 @@ static int bcm203x_probe(struct usb_interface *intf, const struct usb_device_id release_firmware(firmware); - init_timer(&data->timer); - data->timer.function = bcm203x_timer; - data->timer.data = (unsigned long) data; + INIT_WORK(&data->work, bcm203x_work, (void *) data); usb_set_intfdata(intf, data); - mod_timer(&data->timer, jiffies + HZ); + schedule_work(&data->work); return 0; } -- cgit v1.2.3 From 9d90dafdb1f0e3c2b69fa8d3fbe99649127c8fa4 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:28:44 +0100 Subject: [PATCH] rio: fix array checking Found by an analysis tool and reported to the list. Fix is simple enough Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/rio/rioctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c index 052e8120a471..7ce77619707c 100644 --- a/drivers/char/rio/rioctrl.c +++ b/drivers/char/rio/rioctrl.c @@ -662,7 +662,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } - if (portStats.port >= RIO_PORTS) { + if (portStats.port < 0 || portStats.port >= RIO_PORTS) { p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return -ENXIO; } @@ -702,7 +702,7 @@ int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su p->RIOError.Error = COPYIN_FAILED; return -EFAULT; } - if (portStats.port >= RIO_PORTS) { + if (portStats.port < 0 || portStats.port >= RIO_PORTS) { p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE; return -ENXIO; } -- cgit v1.2.3 From 3a42bb223f61fbd755d6e61b9b50b9681d68fcae Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:31:02 +0100 Subject: [PATCH] ide: add sanity checking to ide taskfile ioctl Without this the user can feed in bogus values and get very bogus results. Security impact is minimal as this ioctl isn't available to unpriviledged processes anyway. Reported to the l/k list and found with an auditing tool. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/ide/ide-taskfile.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 1d0470c1f957..30175c7688e8 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -524,8 +524,8 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) task_ioreg_t *hobsptr = args.hobRegister; int err = 0; int tasksize = sizeof(struct ide_task_request_s); - int taskin = 0; - int taskout = 0; + unsigned int taskin = 0; + unsigned int taskout = 0; u8 io_32bit = drive->io_32bit; char __user *buf = (char __user *)arg; @@ -538,8 +538,13 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) return -EFAULT; } - taskout = (int) req_task->out_size; - taskin = (int) req_task->in_size; + taskout = req_task->out_size; + taskin = req_task->in_size; + + if (taskin > 65536 || taskout > 65536) { + err = -EINVAL; + goto abort; + } if (taskout) { int outtotal = tasksize; -- cgit v1.2.3 From 8741ca71a3f626a56595b88200ebf952ce77ceef Mon Sep 17 00:00:00 2001 From: Andrey Mirkin Date: Mon, 16 Oct 2006 12:08:43 +0400 Subject: [PATCH] scsi: megaraid_{mm,mbox}: 64-bit DMA capability fix It is known that 2 LSI Logic MegaRAID SATA RAID Controllers (150-4 and 150-6) don't support 64-bit DMA. Unfortunately currently this check is wrong and driver sets 64-bit DMA mode for these devices. Signed-off-by: Andrey Mirkin Acked-by: Vasily Averin Signed-off-by: Linus Torvalds --- drivers/scsi/megaraid/megaraid_mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c0edb662d863..7bac86dda88f 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -884,7 +884,7 @@ megaraid_init_mbox(adapter_t *adapter) if (((magic64 == HBA_SIGNATURE_64_BIT) && ((adapter->pdev->subsystem_device != - PCI_SUBSYS_ID_MEGARAID_SATA_150_6) || + PCI_SUBSYS_ID_MEGARAID_SATA_150_6) && (adapter->pdev->subsystem_device != PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) || (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && -- cgit v1.2.3 From d986a27413aad10574f7211524de6a529870d134 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:26:01 -0700 Subject: RDMA/amso1100: pci_module_init() conversion pci_module_init() convertion in amso1100 driver. Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index dc1ebeac35c7..9e7bd94b958a 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c @@ -1243,7 +1243,7 @@ static struct pci_driver c2_pci_driver = { static int __init c2_init_module(void) { - return pci_module_init(&c2_pci_driver); + return pci_register_driver(&c2_pci_driver); } static void __exit c2_exit_module(void) -- cgit v1.2.3 From fb7711e71ea7cd0d3e77e969df59162388c8a1f9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 10 Oct 2006 14:26:02 -0700 Subject: RDMA/amso1100: Fix a NULL dereference in error path This patch fixes a NULL dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: Steve Wise Acked-by: Tom Tucker Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_rnic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index e37c5688c214..30409e179606 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -150,8 +150,8 @@ static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props) (struct c2wr_rnic_query_rep *) (unsigned long) (vq_req->reply_msg); if (!reply) err = -ENOMEM; - - err = c2_errno(reply); + else + err = c2_errno(reply); if (err) goto bail2; -- cgit v1.2.3 From 6ef93dddfe11a72ab98a37ac4ef20ad681b008b0 Mon Sep 17 00:00:00 2001 From: Robert Walsh Date: Tue, 10 Oct 2006 14:55:45 -0700 Subject: IB/ipath: Initialize diagpkt file on device init only Don't attempt to set up the diagpkt device in the module init code. Instead, wait until a piece of hardware is initialized. Fixes a problem when loading the ib_ipath module when no InfiniPath hardware is present: modprobe would go into the D state and stay there. Signed-off-by: Robert Walsh Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_diag.c | 65 +++++++++++++++++------------- drivers/infiniband/hw/ipath/ipath_driver.c | 10 ----- drivers/infiniband/hw/ipath/ipath_kernel.h | 3 -- 3 files changed, 38 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_diag.c b/drivers/infiniband/hw/ipath/ipath_diag.c index 29958b6e0214..28c087b824c2 100644 --- a/drivers/infiniband/hw/ipath/ipath_diag.c +++ b/drivers/infiniband/hw/ipath/ipath_diag.c @@ -67,19 +67,54 @@ static struct file_operations diag_file_ops = { .release = ipath_diag_release }; +static ssize_t ipath_diagpkt_write(struct file *fp, + const char __user *data, + size_t count, loff_t *off); + +static struct file_operations diagpkt_file_ops = { + .owner = THIS_MODULE, + .write = ipath_diagpkt_write, +}; + +static atomic_t diagpkt_count = ATOMIC_INIT(0); +static struct cdev *diagpkt_cdev; +static struct class_device *diagpkt_class_dev; + int ipath_diag_add(struct ipath_devdata *dd) { char name[16]; + int ret = 0; + + if (atomic_inc_return(&diagpkt_count) == 1) { + ret = ipath_cdev_init(IPATH_DIAGPKT_MINOR, + "ipath_diagpkt", &diagpkt_file_ops, + &diagpkt_cdev, &diagpkt_class_dev); + + if (ret) { + ipath_dev_err(dd, "Couldn't create ipath_diagpkt " + "device: %d", ret); + goto done; + } + } snprintf(name, sizeof(name), "ipath_diag%d", dd->ipath_unit); - return ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name, - &diag_file_ops, &dd->diag_cdev, - &dd->diag_class_dev); + ret = ipath_cdev_init(IPATH_DIAG_MINOR_BASE + dd->ipath_unit, name, + &diag_file_ops, &dd->diag_cdev, + &dd->diag_class_dev); + if (ret) + ipath_dev_err(dd, "Couldn't create %s device: %d", + name, ret); + +done: + return ret; } void ipath_diag_remove(struct ipath_devdata *dd) { + if (atomic_dec_and_test(&diagpkt_count)) + ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev); + ipath_cdev_cleanup(&dd->diag_cdev, &dd->diag_class_dev); } @@ -275,30 +310,6 @@ bail: return ret; } -static ssize_t ipath_diagpkt_write(struct file *fp, - const char __user *data, - size_t count, loff_t *off); - -static struct file_operations diagpkt_file_ops = { - .owner = THIS_MODULE, - .write = ipath_diagpkt_write, -}; - -static struct cdev *diagpkt_cdev; -static struct class_device *diagpkt_class_dev; - -int __init ipath_diagpkt_add(void) -{ - return ipath_cdev_init(IPATH_DIAGPKT_MINOR, - "ipath_diagpkt", &diagpkt_file_ops, - &diagpkt_cdev, &diagpkt_class_dev); -} - -void __exit ipath_diagpkt_remove(void) -{ - ipath_cdev_cleanup(&diagpkt_cdev, &diagpkt_class_dev); -} - /** * ipath_diagpkt_write - write an IB packet * @fp: the diag data device file pointer diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 12cefa658f3b..b4ffaa7bcbb7 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -2005,18 +2005,8 @@ static int __init infinipath_init(void) goto bail_group; } - ret = ipath_diagpkt_add(); - if (ret < 0) { - printk(KERN_ERR IPATH_DRV_NAME ": Unable to create " - "diag data device: error %d\n", -ret); - goto bail_ipathfs; - } - goto bail; -bail_ipathfs: - ipath_exit_ipathfs(); - bail_group: ipath_driver_remove_group(&ipath_driver.driver); diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 7c436697d0e4..06d5020a2f60 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -869,9 +869,6 @@ int ipath_device_create_group(struct device *, struct ipath_devdata *); void ipath_device_remove_group(struct device *, struct ipath_devdata *); int ipath_expose_reset(struct device *); -int ipath_diagpkt_add(void); -void ipath_diagpkt_remove(void); - int ipath_init_ipathfs(void); void ipath_exit_ipathfs(void); int ipathfs_add_device(struct ipath_devdata *); -- cgit v1.2.3 From 4d99bfac9d5ce53b383d3c8279b917050be4e06c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 16 Oct 2006 19:59:43 +0200 Subject: [PATCH] CONFIG_TELCLOCK depends on X86 The telecom clock driver for MPBL0010 ATCA SBC depends on X86 Signed-off-by: Geert Uytterhoeven Acked-by: Mark Gross Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0e6f35fcc2eb..39a9f8cc6412 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -1046,7 +1046,7 @@ source "drivers/char/tpm/Kconfig" config TELCLOCK tristate "Telecom clock driver for MPBL0010 ATCA SBC" - depends on EXPERIMENTAL + depends on EXPERIMENTAL && X86 default n help The telecom clock device is specific to the MPBL0010 ATCA computer and -- cgit v1.2.3 From 3693ec670b3bb4d11295856bea3592dd8f37f9a5 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 26 Sep 2006 13:22:41 -0500 Subject: [PATCH] bcm43xx: fix race condition in periodic work handler There is a potential race condition in the periodic_work_handler routine of bcm43xx-softmac. In addition to fixing this condition, the size of code is reduced by moving the mutex lock outside the if. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index bad3452ea893..0f047d42158f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3164,12 +3164,12 @@ static void bcm43xx_periodic_work_handler(void *d) u32 savedirqs = 0; int badness; + mutex_lock(&bcm->mutex); badness = estimate_periodic_work_badness(bcm->periodic_state); if (badness > BADNESS_LIMIT) { /* Periodic work will take a long time, so we want it to * be preemtible. */ - mutex_lock(&bcm->mutex); netif_tx_disable(bcm->net_dev); spin_lock_irqsave(&bcm->irq_lock, flags); bcm43xx_mac_suspend(bcm); @@ -3182,7 +3182,6 @@ static void bcm43xx_periodic_work_handler(void *d) /* Periodic work should take short time, so we want low * locking overhead. */ - mutex_lock(&bcm->mutex); spin_lock_irqsave(&bcm->irq_lock, flags); } -- cgit v1.2.3 From 7c28ad2d83ecc637237fe684659a6afbce0bb2a8 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 27 Sep 2006 15:26:33 +0300 Subject: [PATCH] softmac: Fix WX and association related races This fixes some race conditions in the WirelessExtension handling and association handling code. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 2 +- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 2 +- include/net/ieee80211softmac.h | 35 ++++++------ net/ieee80211/softmac/ieee80211softmac_assoc.c | 56 ++++++++++--------- net/ieee80211/softmac/ieee80211softmac_io.c | 9 +++- net/ieee80211/softmac/ieee80211softmac_module.c | 1 + net/ieee80211/softmac/ieee80211softmac_wx.c | 71 +++++++++++++++---------- 7 files changed, 97 insertions(+), 79 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index c3f90c8563d9..2ddbec6bf15b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -242,7 +242,7 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) //TODO break; case BCM43xx_LED_ASSOC: - if (bcm->softmac->associated) + if (bcm->softmac->associnfo.associated) turn_on = 1; break; #ifdef CONFIG_BCM43XX_DEBUG diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 9b7b15cf6561..d27016f8c736 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -847,7 +847,7 @@ static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_d unsigned long flags; wstats = &bcm->stats.wstats; - if (!mac->associated) { + if (!mac->associnfo.associated) { wstats->miss.beacon = 0; // bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? wstats->discard.retries = 0; diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h index 425b3a57ac74..617b672b1132 100644 --- a/include/net/ieee80211softmac.h +++ b/include/net/ieee80211softmac.h @@ -63,13 +63,11 @@ struct ieee80211softmac_wpa { /* * Information about association - * - * Do we need a lock for this? - * We only ever use this structure inlined - * into our global struct. I've used its lock, - * but maybe we need a local one here? */ struct ieee80211softmac_assoc_info { + + struct mutex mutex; + /* * This is the requested ESSID. It is written * only by the WX handlers. @@ -99,12 +97,13 @@ struct ieee80211softmac_assoc_info { * * bssfixed is used for SIOCSIWAP. */ - u8 static_essid:1, - short_preamble_available:1, - associating:1, - assoc_wait:1, - bssvalid:1, - bssfixed:1; + u8 static_essid; + u8 short_preamble_available; + u8 associating; + u8 associated; + u8 assoc_wait; + u8 bssvalid; + u8 bssfixed; /* Scan retries remaining */ int scan_retry; @@ -229,12 +228,10 @@ struct ieee80211softmac_device { /* private stuff follows */ /* this lock protects this structure */ spinlock_t lock; - - /* couple of flags */ - u8 scanning:1, /* protects scanning from being done multiple times at once */ - associated:1, - running:1; - + + u8 running; /* SoftMAC started? */ + u8 scanning; + struct ieee80211softmac_scaninfo *scaninfo; struct ieee80211softmac_assoc_info associnfo; struct ieee80211softmac_bss_info bssinfo; @@ -250,7 +247,7 @@ struct ieee80211softmac_device { /* we need to keep a list of network structs we copied */ struct list_head network_list; - + /* This must be the last item so that it points to the data * allocated beyond this structure by alloc_ieee80211 */ u8 priv[0]; @@ -295,7 +292,7 @@ static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device { struct ieee80211softmac_txrates *txrates = &mac->txrates; - if (!mac->associated) + if (!mac->associnfo.associated) return txrates->mgt_mcast_rate; /* We are associated, sending unicast frame */ diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index 589f6d2c548a..cf51c87a971d 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -48,7 +48,7 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft dprintk(KERN_INFO PFX "sent association request!\n"); spin_lock_irqsave(&mac->lock, flags); - mac->associated = 0; /* just to make sure */ + mac->associnfo.associated = 0; /* just to make sure */ /* Set a timer for timeout */ /* FIXME: make timeout configurable */ @@ -62,24 +62,22 @@ ieee80211softmac_assoc_timeout(void *d) { struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_network *n; - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); /* we might race against ieee80211softmac_handle_assoc_response, * so make sure only one of us does something */ - if (!mac->associnfo.associating) { - spin_unlock_irqrestore(&mac->lock, flags); - return; - } + if (!mac->associnfo.associating) + goto out; mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associated = 0; + mac->associnfo.associated = 0; n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); - spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "assoc request timed out!\n"); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); +out: + mutex_unlock(&mac->associnfo.mutex); } void @@ -93,7 +91,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) netif_carrier_off(mac->dev); - mac->associated = 0; + mac->associnfo.associated = 0; mac->associnfo.bssvalid = 0; mac->associnfo.associating = 0; ieee80211softmac_init_bss(mac); @@ -107,7 +105,7 @@ ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reas { struct ieee80211softmac_network *found; - if (mac->associnfo.bssvalid && mac->associated) { + if (mac->associnfo.bssvalid && mac->associnfo.associated) { found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); if (found) ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); @@ -196,17 +194,18 @@ ieee80211softmac_assoc_work(void *d) int bssvalid; unsigned long flags; + mutex_lock(&mac->associnfo.mutex); + + if (!mac->associnfo.associating) + goto out; + /* ieee80211_disassoc might clear this */ bssvalid = mac->associnfo.bssvalid; /* meh */ - if (mac->associated) + if (mac->associnfo.associated) ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); - spin_lock_irqsave(&mac->lock, flags); - mac->associnfo.associating = 1; - spin_unlock_irqrestore(&mac->lock, flags); - /* try to find the requested network in our list, if we found one already */ if (bssvalid || mac->associnfo.bssfixed) found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); @@ -260,10 +259,8 @@ ieee80211softmac_assoc_work(void *d) if (!found) { if (mac->associnfo.scan_retry > 0) { - spin_lock_irqsave(&mac->lock, flags); mac->associnfo.scan_retry--; - spin_unlock_irqrestore(&mac->lock, flags); - + /* We know of no such network. Let's scan. * NB: this also happens if we had no memory to copy the network info... * Maybe we can hope to have more memory after scanning finishes ;) @@ -272,19 +269,17 @@ ieee80211softmac_assoc_work(void *d) ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); if (ieee80211softmac_start_scan(mac)) dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); - return; + goto out; } else { - spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 0; - mac->associated = 0; - spin_unlock_irqrestore(&mac->lock, flags); + mac->associnfo.associated = 0; dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); /* reset the retry counter for the next user request since we * break out and don't reschedule ourselves after this point. */ mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); - return; + goto out; } } @@ -297,7 +292,7 @@ ieee80211softmac_assoc_work(void *d) /* copy the ESSID for displaying it */ mac->associnfo.associate_essid.len = found->essid.len; memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); - + /* we found a network! authenticate (if necessary) and associate to it. */ if (found->authenticating) { dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); @@ -305,7 +300,7 @@ ieee80211softmac_assoc_work(void *d) mac->associnfo.assoc_wait = 1; ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); } - return; + goto out; } if (!found->authenticated && !found->authenticating) { /* This relies on the fact that _auth_req only queues the work, @@ -321,11 +316,14 @@ ieee80211softmac_assoc_work(void *d) mac->associnfo.assoc_wait = 0; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); } - return; + goto out; } /* finally! now we can start associating */ mac->associnfo.assoc_wait = 0; ieee80211softmac_assoc(mac, found); + +out: + mutex_unlock(&mac->associnfo.mutex); } /* call this to do whatever is necessary when we're associated */ @@ -341,7 +339,7 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac, mac->bssinfo.supported_rates = net->supported_rates; ieee80211softmac_recalc_txrates(mac); - mac->associated = 1; + mac->associnfo.associated = 1; mac->associnfo.short_preamble_available = (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; @@ -421,7 +419,7 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); mac->associnfo.associating = 0; mac->associnfo.bssvalid = 0; - mac->associated = 0; + mac->associnfo.associated = 0; ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); } diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index 82bfddbf33a2..e8419cfb058f 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -475,8 +475,13 @@ int ieee80211softmac_handle_beacon(struct net_device *dev, { struct ieee80211softmac_device *mac = ieee80211_priv(dev); - if (mac->associated && memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) - ieee80211softmac_process_erp(mac, network->erp_value); + /* This might race, but we don't really care and it's not worth + * adding heavyweight locking in this fastpath. + */ + if (mac->associnfo.associated) { + if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) + ieee80211softmac_process_erp(mac, network->erp_value); + } return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index addea1cf73ae..33aff4f4a471 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -57,6 +57,7 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) INIT_LIST_HEAD(&softmac->network_list); INIT_LIST_HEAD(&softmac->events); + mutex_init(&softmac->associnfo.mutex); INIT_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work, softmac); INIT_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout, softmac); softmac->start_scan = ieee80211softmac_start_scan_implementation; diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index 2aa779d18f38..23068a830f7d 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -73,13 +73,14 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, struct ieee80211softmac_network *n; struct ieee80211softmac_auth_queue_item *authptr; int length = 0; - unsigned long flags; + + mutex_lock(&sm->associnfo.mutex); /* Check if we're already associating to this or another network * If it's another network, cancel and start over with our new network * If it's our network, ignore the change, we're already doing it! */ - if((sm->associnfo.associating || sm->associated) && + if((sm->associnfo.associating || sm->associnfo.associated) && (data->essid.flags && data->essid.length)) { /* Get the associating network */ n = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); @@ -87,10 +88,9 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, !memcmp(n->essid.data, extra, n->essid.len)) { dprintk(KERN_INFO PFX "Already associating or associated to "MAC_FMT"\n", MAC_ARG(sm->associnfo.bssid)); - return 0; + goto out; } else { dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); - spin_lock_irqsave(&sm->lock,flags); /* Cancel assoc work */ cancel_delayed_work(&sm->associnfo.work); /* We don't have to do this, but it's a little cleaner */ @@ -98,14 +98,13 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, cancel_delayed_work(&authptr->work); sm->associnfo.bssvalid = 0; sm->associnfo.bssfixed = 0; - spin_unlock_irqrestore(&sm->lock,flags); flush_scheduled_work(); + sm->associnfo.associating = 0; + sm->associnfo.associated = 0; } } - spin_lock_irqsave(&sm->lock, flags); - sm->associnfo.static_essid = 0; sm->associnfo.assoc_wait = 0; @@ -121,10 +120,12 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, * If applicable, we have already copied the data in */ sm->associnfo.req_essid.len = length; + sm->associnfo.associating = 1; /* queue lower level code to do work (if necessary) */ schedule_work(&sm->associnfo.work); +out: + mutex_unlock(&sm->associnfo.mutex); - spin_unlock_irqrestore(&sm->lock, flags); return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); @@ -136,10 +137,8 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - unsigned long flags; - /* avoid getting inconsistent information */ - spin_lock_irqsave(&sm->lock, flags); + mutex_lock(&sm->associnfo.mutex); /* If all fails, return ANY (empty) */ data->essid.length = 0; data->essid.flags = 0; /* active */ @@ -152,12 +151,13 @@ ieee80211softmac_wx_get_essid(struct net_device *net_dev, } /* If we're associating/associated, return that */ - if (sm->associated || sm->associnfo.associating) { + if (sm->associnfo.associated || sm->associnfo.associating) { data->essid.length = sm->associnfo.associate_essid.len; data->essid.flags = 1; /* active */ memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); } - spin_unlock_irqrestore(&sm->lock, flags); + mutex_unlock(&sm->associnfo.mutex); + return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); @@ -322,15 +322,15 @@ ieee80211softmac_wx_get_wap(struct net_device *net_dev, { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); int err = 0; - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); if (mac->associnfo.bssvalid) memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); else memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); data->ap_addr.sa_family = ARPHRD_ETHER; - spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); @@ -342,28 +342,27 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - unsigned long flags; /* sanity check */ if (data->ap_addr.sa_family != ARPHRD_ETHER) { return -EINVAL; } - spin_lock_irqsave(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is not to be fixed any longer, * and we should reassociate to the best AP. */ mac->associnfo.bssfixed = 0; /* force reassociation */ mac->associnfo.bssvalid = 0; - if (mac->associated) + if (mac->associnfo.associated) schedule_work(&mac->associnfo.work); } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { /* the bssid we have is no longer fixed */ mac->associnfo.bssfixed = 0; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { - if (mac->associnfo.associating || mac->associated) { + if (mac->associnfo.associating || mac->associnfo.associated) { /* bssid unchanged and associated or associating - just return */ goto out; } @@ -378,7 +377,8 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } out: - spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return 0; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); @@ -394,7 +394,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, int err = 0; char *buf; int i; - + + mutex_lock(&mac->associnfo.mutex); spin_lock_irqsave(&mac->lock, flags); /* bleh. shouldn't be locked for that kmalloc... */ @@ -432,6 +433,8 @@ ieee80211softmac_wx_set_genie(struct net_device *dev, out: spin_unlock_irqrestore(&mac->lock, flags); + mutex_unlock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); @@ -446,7 +449,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, unsigned long flags; int err = 0; int space = wrqu->data.length; - + + mutex_lock(&mac->associnfo.mutex); spin_lock_irqsave(&mac->lock, flags); wrqu->data.length = 0; @@ -459,6 +463,8 @@ ieee80211softmac_wx_get_genie(struct net_device *dev, err = -E2BIG; } spin_unlock_irqrestore(&mac->lock, flags); + mutex_lock(&mac->associnfo.mutex); + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); @@ -473,10 +479,13 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, struct iw_mlme *mlme = (struct iw_mlme *)extra; u16 reason = cpu_to_le16(mlme->reason_code); struct ieee80211softmac_network *net; + int err = -EINVAL; + + mutex_lock(&mac->associnfo.mutex); if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) { printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n"); - return -EINVAL; + goto out; } switch (mlme->cmd) { @@ -484,14 +493,22 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data); if (!net) { printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n"); - return -EINVAL; + goto out; } return ieee80211softmac_deauth_req(mac, net, reason); case IW_MLME_DISASSOC: ieee80211softmac_send_disassoc_req(mac, reason); - return 0; + mac->associnfo.associated = 0; + mac->associnfo.associating = 0; + err = 0; + goto out; default: - return -EOPNOTSUPP; + err = -EOPNOTSUPP; } + +out: + mutex_unlock(&mac->associnfo.mutex); + + return err; } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); -- cgit v1.2.3 From 16bfa676a7cc64695f7e9694c380ebd26c461ae5 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 28 Sep 2006 00:10:55 -0500 Subject: [PATCH] bcm43xx-softmac: check returned value from pci_enable_device Linus's tree now has a configuration option that prints a warning whenever the returned value of any routine is ignored. This patch fixes the only such warning for bcm43xx. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 0f047d42158f..7776b5c42ac7 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4207,7 +4207,11 @@ static int bcm43xx_resume(struct pci_dev *pdev) dprintk(KERN_INFO PFX "Resuming...\n"); pci_set_power_state(pdev, 0); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR PFX "Failure with pci_enable_device!\n"); + return err; + } pci_restore_state(pdev); bcm43xx_chipset_attach(bcm); -- cgit v1.2.3 From 8da81e52b743edac0bfbb7d0c1286f919b2f209b Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 2 Oct 2006 23:48:54 -0500 Subject: [PATCH] bcm43xx-softmac: Fix system hang for x86-64 with >1GB RAM The bcm43xx-softmac software currently fails when running on x86_64 systems with more than 1GB RAM and one of the card variants with 30-bit DMA addressing. This patch uses the address extension bits in the hardware to set the correct DMA mask for the specific card in use. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 28 +++++++++++++++++++++++----- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 17 +++++++++++++++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 25 ++++++------------------- 3 files changed, 46 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c index 76e3aed4b471..978ed099e285 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c @@ -705,11 +705,30 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) struct bcm43xx_dmaring *ring; int err = -ENOMEM; int dma64 = 0; - u32 sbtmstatehi; + u64 mask = bcm43xx_get_supported_dma_mask(bcm); + int nobits; - sbtmstatehi = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (sbtmstatehi & BCM43xx_SBTMSTATEHIGH_DMA64BIT) + if (mask == DMA_64BIT_MASK) { dma64 = 1; + nobits = 64; + } else if (mask == DMA_32BIT_MASK) + nobits = 32; + else + nobits = 30; + err = pci_set_dma_mask(bcm->pci_dev, mask); + err |= pci_set_consistent_dma_mask(bcm->pci_dev, mask); + if (err) { +#ifdef CONFIG_BCM43XX_PIO + printk(KERN_WARNING PFX "DMA not supported on this device." + " Falling back to PIO.\n"); + bcm->__using_pio = 1; + return -ENOSYS; +#else + printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " + "Please recompile the driver with PIO support.\n"); + return -ENODEV; +#endif /* CONFIG_BCM43XX_PIO */ + } /* setup TX DMA channels. */ ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); @@ -755,8 +774,7 @@ int bcm43xx_dma_init(struct bcm43xx_private *bcm) dma->rx_ring3 = ring; } - dprintk(KERN_INFO PFX "%s DMA initialized\n", - dma64 ? "64-bit" : "32-bit"); + dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", nobits); err = 0; out: return err; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index e04bcaddd1d0..ea16078cfe98 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -314,6 +314,23 @@ int bcm43xx_dma_tx(struct bcm43xx_private *bcm, struct ieee80211_txb *txb); void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); +/* Helper function that returns the dma mask for this device. */ +static inline +u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm) +{ + int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) & + BCM43xx_SBTMSTATEHIGH_DMA64BIT; + u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0); + u32 mask = BCM43xx_DMA32_TXADDREXT_MASK; + + if (dma64) + return DMA_64BIT_MASK; + bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask); + if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask) + return DMA_32BIT_MASK; + return DMA_30BIT_MASK; +} + #else /* CONFIG_BCM43XX_DMA */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 7776b5c42ac7..a94c6d8826f8 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2925,10 +2925,13 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, bcm43xx_write16(bcm, 0x043C, 0x000C); if (active_wlcore) { - if (bcm43xx_using_pio(bcm)) + if (bcm43xx_using_pio(bcm)) { err = bcm43xx_pio_init(bcm); - else + } else { err = bcm43xx_dma_init(bcm); + if (err == -ENOSYS) + err = bcm43xx_pio_init(bcm); + } if (err) goto err_chip_cleanup; } @@ -3992,8 +3995,6 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, struct net_device *net_dev, struct pci_dev *pci_dev) { - int err; - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); bcm->ieee = netdev_priv(net_dev); bcm->softmac = ieee80211_priv(net_dev); @@ -4011,22 +4012,8 @@ static int bcm43xx_init_private(struct bcm43xx_private *bcm, (void (*)(unsigned long))bcm43xx_interrupt_tasklet, (unsigned long)bcm); tasklet_disable_nosync(&bcm->isr_tasklet); - if (modparam_pio) { + if (modparam_pio) bcm->__using_pio = 1; - } else { - err = pci_set_dma_mask(pci_dev, DMA_30BIT_MASK); - err |= pci_set_consistent_dma_mask(pci_dev, DMA_30BIT_MASK); - if (err) { -#ifdef CONFIG_BCM43XX_PIO - printk(KERN_WARNING PFX "DMA not supported. Falling back to PIO.\n"); - bcm->__using_pio = 1; -#else - printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " - "Recompile the driver with PIO support, please.\n"); - return -ENODEV; -#endif /* CONFIG_BCM43XX_PIO */ - } - } bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; /* default to sw encryption for now */ -- cgit v1.2.3 From 431aca5a18f15f61cc51c466073928c4f9565fe4 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Tue, 10 Oct 2006 16:46:30 -0400 Subject: [PATCH] airo.c: check returned values create_proc_entry() can fail and return NULL in setup_proc_entry(), the result must be checked before dereferencing. (Coverity ID 1443) init_wifidev() & setup_proc_entry() can also fail in _init_airo_card(). This adds the checks & cleanup code and removes some whitespace. Signed-off-by: Florin Malita Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 98 +++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 0a33c8a56e13..9d5427a6e609 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -2897,6 +2897,8 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, goto err_out_map; } ai->wifidev = init_wifidev(ai, dev); + if (!ai->wifidev) + goto err_out_reg; set_bit(FLAG_REGISTERED,&ai->flags); airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x", @@ -2908,11 +2910,18 @@ static struct net_device *_init_airo_card( unsigned short irq, int port, for( i = 0; i < MAX_FIDS; i++ ) ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); - setup_proc_entry( dev, dev->priv ); /* XXX check for failure */ + if (setup_proc_entry(dev, dev->priv) < 0) + goto err_out_wifi; + netif_start_queue(dev); SET_MODULE_OWNER(dev); return dev; +err_out_wifi: + unregister_netdev(ai->wifidev); + free_netdev(ai->wifidev); +err_out_reg: + unregister_netdev(dev); err_out_map: if (test_bit(FLAG_MPI,&ai->flags) && pci) { pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma); @@ -4495,91 +4504,128 @@ static int setup_proc_entry( struct net_device *dev, apriv->proc_entry = create_proc_entry(apriv->proc_name, S_IFDIR|airo_perm, airo_entry); - apriv->proc_entry->uid = proc_uid; - apriv->proc_entry->gid = proc_gid; - apriv->proc_entry->owner = THIS_MODULE; + if (!apriv->proc_entry) + goto fail; + apriv->proc_entry->uid = proc_uid; + apriv->proc_entry->gid = proc_gid; + apriv->proc_entry->owner = THIS_MODULE; /* Setup the StatsDelta */ entry = create_proc_entry("StatsDelta", S_IFREG | (S_IRUGO&proc_perm), apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_stats_delta; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_statsdelta_ops); /* Setup the Stats */ entry = create_proc_entry("Stats", S_IFREG | (S_IRUGO&proc_perm), apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_stats; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_stats_ops); /* Setup the Status */ entry = create_proc_entry("Status", S_IFREG | (S_IRUGO&proc_perm), apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_status; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_status_ops); /* Setup the Config */ entry = create_proc_entry("Config", S_IFREG | proc_perm, apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_config; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_config_ops); /* Setup the SSID */ entry = create_proc_entry("SSID", S_IFREG | proc_perm, apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_ssid; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_SSID_ops); /* Setup the APList */ entry = create_proc_entry("APList", S_IFREG | proc_perm, apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_aplist; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_APList_ops); /* Setup the BSSList */ entry = create_proc_entry("BSSList", S_IFREG | proc_perm, apriv->proc_entry); + if (!entry) + goto fail_bsslist; entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_BSSList_ops); /* Setup the WepKey */ entry = create_proc_entry("WepKey", S_IFREG | proc_perm, apriv->proc_entry); - entry->uid = proc_uid; - entry->gid = proc_gid; + if (!entry) + goto fail_wepkey; + entry->uid = proc_uid; + entry->gid = proc_gid; entry->data = dev; - entry->owner = THIS_MODULE; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_wepkey_ops); return 0; + +fail_wepkey: + remove_proc_entry("BSSList", apriv->proc_entry); +fail_bsslist: + remove_proc_entry("APList", apriv->proc_entry); +fail_aplist: + remove_proc_entry("SSID", apriv->proc_entry); +fail_ssid: + remove_proc_entry("Config", apriv->proc_entry); +fail_config: + remove_proc_entry("Status", apriv->proc_entry); +fail_status: + remove_proc_entry("Stats", apriv->proc_entry); +fail_stats: + remove_proc_entry("StatsDelta", apriv->proc_entry); +fail_stats_delta: + remove_proc_entry(apriv->proc_name, airo_entry); +fail: + return -ENOMEM; } static int takedown_proc_entry( struct net_device *dev, -- cgit v1.2.3 From 7e4e8d99c2288a490a0806b9cb40016913312cfe Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Tue, 10 Oct 2006 14:45:44 -0700 Subject: [PATCH] orinoco: fix WE-21 buffer overflow This patch fixes the Orinoco driver overflow issue with WE-21. Cc: Valdis Kletnieks Cc: Pavel Roskin Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/orinoco.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index b779c7dcc1a8..336cabac13b3 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -2457,6 +2457,7 @@ void free_orinocodev(struct net_device *dev) /* Wireless extensions */ /********************************************************************/ +/* Return : < 0 -> error code ; >= 0 -> length */ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, char buf[IW_ESSID_MAX_SIZE+1]) { @@ -2501,9 +2502,9 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, len = le16_to_cpu(essidbuf.len); BUG_ON(len > IW_ESSID_MAX_SIZE); - memset(buf, 0, IW_ESSID_MAX_SIZE+1); + memset(buf, 0, IW_ESSID_MAX_SIZE); memcpy(buf, p, len); - buf[len] = '\0'; + err = len; fail_unlock: orinoco_unlock(priv, &flags); @@ -3027,17 +3028,18 @@ static int orinoco_ioctl_getessid(struct net_device *dev, if (netif_running(dev)) { err = orinoco_hw_get_essid(priv, &active, essidbuf); - if (err) + if (err < 0) return err; + erq->length = err; } else { if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1); + memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE); + erq->length = strlen(priv->desired_essid); orinoco_unlock(priv, &flags); } erq->flags = 1; - erq->length = strlen(essidbuf); return 0; } @@ -3075,10 +3077,10 @@ static int orinoco_ioctl_getnick(struct net_device *dev, if (orinoco_lock(priv, &flags) != 0) return -EBUSY; - memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1); + memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE); orinoco_unlock(priv, &flags); - nrq->length = strlen(nickbuf); + nrq->length = strlen(priv->nick); return 0; } -- cgit v1.2.3 From 683f8c9e00d2aa911382186ca891bd221efaea74 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 10 Oct 2006 14:45:45 -0700 Subject: [PATCH] zd1201: Possible NULL dereference If we enter the if(!zd) and set free to 1, we dereference zd in the exit code. Signed-off-by: Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/zd1201.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 30057a335a7b..36b29ff05814 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -193,10 +193,8 @@ static void zd1201_usbrx(struct urb *urb) struct sk_buff *skb; unsigned char type; - if (!zd) { - free = 1; - goto exit; - } + if (!zd) + return; switch(urb->status) { case -EILSEQ: -- cgit v1.2.3 From 53077944f119808df3d1c6be07241f17a87e7c28 Mon Sep 17 00:00:00 2001 From: Jean Tourrilhes Date: Tue, 10 Oct 2006 14:45:46 -0700 Subject: [PATCH] wireless: More WE-21 potential overflows... After the Orinoco issue, I did an audit of other drivers for the same issue. Three drivers were NULL terminating the ESSID, which could cause an overflow in WE-21 when the ESSID has maximum size. Signed-off-by: Jean Tourrilhes Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 1 - drivers/net/wireless/atmel.c | 2 -- drivers/net/wireless/ray_cs.c | 1 - 3 files changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 9d5427a6e609..e0710fa9702e 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5970,7 +5970,6 @@ static int airo_get_essid(struct net_device *dev, /* Get the current SSID */ memcpy(extra, status_rid.SSID, status_rid.SSIDlen); - extra[status_rid.SSIDlen] = '\0'; /* If none, we may want to get the one that was set */ /* Push it out ! */ diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 31eed85de60f..0c07b8b7250d 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1678,11 +1678,9 @@ static int atmel_get_essid(struct net_device *dev, /* Get the current SSID */ if (priv->new_SSID_size != 0) { memcpy(extra, priv->new_SSID, priv->new_SSID_size); - extra[priv->new_SSID_size] = '\0'; dwrq->length = priv->new_SSID_size; } else { memcpy(extra, priv->SSID, priv->SSID_size); - extra[priv->SSID_size] = '\0'; dwrq->length = priv->SSID_size; } diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 0b381d77015c..7fbfc9e41d07 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -1198,7 +1198,6 @@ static int ray_get_essid(struct net_device *dev, /* Get the essid that was set */ memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); - extra[IW_ESSID_MAX_SIZE] = '\0'; /* Push it out ! */ dwrq->length = strlen(extra); -- cgit v1.2.3 From 5bb85f18087b10a908bd793e9fd3ccd63aebb724 Mon Sep 17 00:00:00 2001 From: Dave Kleikamp Date: Tue, 10 Oct 2006 14:45:46 -0700 Subject: [PATCH] airo: check if need to freeze The airo driver used to break out of while loop if there were any signals pending. Since it no longer checks for signals, it at least needs to check if it needs to be frozen. Signed-off-by: Dave Kleikamp Cc: Jean Tourrilhes Cc: Sukadev Bhattiprolu Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/airo.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index e0710fa9702e..efcdaf1c5f73 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -3098,7 +3098,8 @@ static int airo_thread(void *data) { set_bit(JOB_AUTOWEP, &ai->jobs); break; } - if (!kthread_should_stop()) { + if (!kthread_should_stop() && + !freezing(current)) { unsigned long wake_at; if (!ai->expires || !ai->scan_timeout) { wake_at = max(ai->expires, @@ -3110,7 +3111,8 @@ static int airo_thread(void *data) { schedule_timeout(wake_at - jiffies); continue; } - } else if (!kthread_should_stop()) { + } else if (!kthread_should_stop() && + !freezing(current)) { schedule(); continue; } -- cgit v1.2.3 From 1f5c23e2c10d642a23aa3ebb449670a5184b6aab Mon Sep 17 00:00:00 2001 From: Arthur Kepner Date: Mon, 16 Oct 2006 20:22:35 -0700 Subject: IB/mthca: Use mmiowb after doorbell ring We discovered a problem when running IPoIB applications on multiple CPUs on an Altix system. Many messages such as: ib_mthca 0002:01:00.0: SQ 000014 full (19941644 head, 19941707 tail, 64 max, 0 nreq) appear in syslog, and the driver wedges up. Apparently this is because writes to the doorbells from different CPUs reach the device out of order. The following patch adds mmiowb() calls after doorbell rings to ensure the doorbell writes are ordered. Signed-off-by: Arthur Kepner Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cq.c | 7 +++++++ drivers/infiniband/hw/mthca/mthca_qp.c | 19 +++++++++++++++++++ drivers/infiniband/hw/mthca/mthca_srq.c | 8 ++++++++ 3 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index e393681ba7d4..149b36901239 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -39,6 +39,8 @@ #include #include +#include + #include #include "mthca_dev.h" @@ -210,6 +212,11 @@ static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq, mthca_write64(doorbell, dev->kar + MTHCA_CQ_DOORBELL, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + /* + * Make sure doorbells don't leak out of CQ spinlock + * and reach the HCA out of order: + */ + mmiowb(); } } diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 5e5c58b9920b..6a7822e0fc19 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -39,6 +39,8 @@ #include #include +#include + #include #include #include @@ -1732,6 +1734,11 @@ out: mthca_write64(doorbell, dev->kar + MTHCA_SEND_DOORBELL, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + /* + * Make sure doorbells don't leak out of SQ spinlock + * and reach the HCA out of order: + */ + mmiowb(); } qp->sq.next_ind = ind; @@ -1851,6 +1858,12 @@ out: qp->rq.next_ind = ind; qp->rq.head += nreq; + /* + * Make sure doorbells don't leak out of RQ spinlock and reach + * the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&qp->rq.lock, flags); return err; } @@ -2112,6 +2125,12 @@ out: MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); } + /* + * Make sure doorbells don't leak out of SQ spinlock and reach + * the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&qp->sq.lock, flags); return err; } diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 92a72f521528..f5d7677d1079 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -35,6 +35,8 @@ #include #include +#include + #include "mthca_dev.h" #include "mthca_cmd.h" #include "mthca_memfree.h" @@ -595,6 +597,12 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); } + /* + * Make sure doorbells don't leak out of SRQ spinlock and + * reach the HCA out of order: + */ + mmiowb(); + spin_unlock_irqrestore(&srq->lock, flags); return err; } -- cgit v1.2.3 From 107d5a72f2c6a6819b66eebcb0281c7a67b6baaa Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Tue, 17 Oct 2006 00:09:24 -0700 Subject: [PATCH] ioc4: Remove SN2 feature and config dependencies The SGI PCI-RT card, based on the SGI IOC4 chip, will be made available on Altix XE (x86_64) platforms in the near future. As such dependencies on SN2-specific features and config dependencies need to be removed. This patch updates the Kconfig files to remove the config dependency, and updates the IOC4 bus speed detection routine to use universally available time interfaces instead of mmtimer. Signed-off-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/sn/Kconfig | 13 ++++++------- drivers/sn/ioc4.c | 36 +++++++++++++++++------------------- 2 files changed, 23 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig index a34731625877..34d4fde51a79 100644 --- a/drivers/sn/Kconfig +++ b/drivers/sn/Kconfig @@ -7,16 +7,15 @@ menu "SN Devices" config SGI_IOC4 tristate "SGI IOC4 Base IO support" - depends on MMTIMER default m ---help--- - This option enables basic support for the SGI IOC4-based Base IO - controller card. This option does not enable any specific - functions on such a card, but provides necessary infrastructure - for other drivers to utilize. + This option enables basic support for the IOC4 chip on certain + SGI IO controller cards (IO9, IO10, and PCI-RT). This option + does not enable any specific functions on such a card, but provides + necessary infrastructure for other drivers to utilize. - If you have an SGI Altix with an IOC4-based - I/O controller say Y. Otherwise say N. + If you have an SGI Altix with an IOC4-based card say Y. + Otherwise say N. config SGI_IOC3 tristate "SGI IOC3 Base IO support" diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c index 8562821e6498..83d2e90c581c 100644 --- a/drivers/sn/ioc4.c +++ b/drivers/sn/ioc4.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (C) 2005-2006 Silicon Graphics, Inc. All Rights Reserved. */ /* This file contains the master driver module for use by SGI IOC4 subdrivers. @@ -29,9 +29,9 @@ #include #include #include -#include -#include +#include #include +#include #include #include #include @@ -43,7 +43,7 @@ /* Tweakable values */ /* PCI bus speed detection/calibration */ -#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */ +#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */ #define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */ #define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */ #define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */ @@ -143,11 +143,11 @@ ioc4_unregister_submodule(struct ioc4_submodule *is) static void ioc4_clock_calibrate(struct ioc4_driver_data *idd) { - extern unsigned long sn_rtc_cycles_per_second; union ioc4_int_out int_out; union ioc4_gpcr gpcr; unsigned int state, last_state = 1; - uint64_t start = 0, end, period; + struct timespec start_ts, end_ts; + uint64_t start, end, period; unsigned int count = 0; /* Enable output */ @@ -175,30 +175,28 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) if (!last_state && state) { count++; if (count == IOC4_CALIBRATE_END) { - end = rtc_time(); + ktime_get_ts(&end_ts); break; } else if (count == IOC4_CALIBRATE_DISCARD) - start = rtc_time(); + ktime_get_ts(&start_ts); } last_state = state; } while (1); /* Calculation rearranged to preserve intermediate precision. * Logically: - * 1. "end - start" gives us number of RTC cycles over all the - * square wave cycles measured. - * 2. Divide by number of square wave cycles to get number of - * RTC cycles per square wave cycle. + * 1. "end - start" gives us the measurement period over all + * the square wave cycles. + * 2. Divide by number of square wave cycles to get the period + * of a square wave cycle. * 3. Divide by 2*(int_out.fields.count+1), which is the formula * by which the IOC4 generates the square wave, to get the - * number of RTC cycles per IOC4 INT_OUT count. - * 4. Divide by sn_rtc_cycles_per_second to get seconds per - * count. - * 5. Multiply by 1E9 to get nanoseconds per count. + * period of an IOC4 INT_OUT count. */ - period = ((end - start) * 1000000000) / - (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1) - * sn_rtc_cycles_per_second); + end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec; + start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec; + period = (end - start) / + (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)); /* Bounds check the result. */ if (period > IOC4_CALIBRATE_LOW_LIMIT || -- cgit v1.2.3 From 59f148005cfd3d41537a4b872c266213d5fe4dc6 Mon Sep 17 00:00:00 2001 From: Brent Casavant Date: Tue, 17 Oct 2006 00:09:25 -0700 Subject: [PATCH] ioc4: Enable build on non-SN2 The SGI PCI-RT card, based on the SGI IOC4 chip, will be made available on Altix XE (x86_64) platforms in the near future. As such it is now a misnomer for the IOC4 base device driver to live under drivers/sn, and would complicate builds for non-SN2. This patch moves the IOC4 base driver code from drivers/sn to drivers/misc, and updates the associated Makefiles and Kconfig files to allow building on non-SN2 configs. Due to the resulting change in link order, it is now necessary to use late_initcall() for IOC4 subdriver initialization. [akpm@osdl.org: __udivdi3 fix] [akpm@osdl.org: fix default in Kconfig] Acked-by: Pat Gefre Acked-by: Jeremy Higdon Signed-off-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/Kconfig | 6 +- drivers/ide/pci/sgiioc4.c | 2 +- drivers/misc/Kconfig | 11 + drivers/misc/Makefile | 1 + drivers/misc/ioc4.c | 473 ++++++++++++++++++++++++++++++++++++++++++ drivers/serial/ioc4_serial.c | 2 +- drivers/sn/Kconfig | 12 -- drivers/sn/Makefile | 1 - drivers/sn/ioc4.c | 474 ------------------------------------------- 9 files changed, 491 insertions(+), 491 deletions(-) create mode 100644 drivers/misc/ioc4.c delete mode 100644 drivers/sn/ioc4.c (limited to 'drivers') diff --git a/drivers/Kconfig b/drivers/Kconfig index 263e86ddc1a4..f39463418904 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -14,6 +14,10 @@ source "drivers/pnp/Kconfig" source "drivers/block/Kconfig" +# misc before ide - BLK_DEV_SGIIOC4 depends on SGI_IOC4 + +source "drivers/misc/Kconfig" + source "drivers/ide/Kconfig" source "drivers/scsi/Kconfig" @@ -52,8 +56,6 @@ source "drivers/w1/Kconfig" source "drivers/hwmon/Kconfig" -source "drivers/misc/Kconfig" - source "drivers/mfd/Kconfig" source "drivers/media/Kconfig" diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index f3fe287fbd89..244f7eb7006d 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -774,7 +774,7 @@ ioc4_ide_exit(void) ioc4_unregister_submodule(&ioc4_ide_submodule); } -module_init(ioc4_ide_init); +late_initcall(ioc4_ide_init); /* Call only after IDE init is done */ module_exit(ioc4_ide_exit); MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon"); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index fa7acc2c5c6d..b6c045dc97b4 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -28,6 +28,17 @@ config IBM_ASM If unsure, say N. +config SGI_IOC4 + tristate "SGI IOC4 Base IO support" + ---help--- + This option enables basic support for the IOC4 chip on certain + SGI IO controller cards (IO9, IO10, and PCI-RT). This option + does not enable any specific functions on such a card, but provides + necessary infrastructure for other drivers to utilize. + + If you have an SGI Altix with an IOC4-based card say Y. + Otherwise say N. + config TIFM_CORE tristate "TI Flash Media interface support (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 9a91c1ee8497..c9e98ab021c5 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o +obj-$(CONFIG_SGI_IOC4) += ioc4.o diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c new file mode 100644 index 000000000000..1c3c14a3839c --- /dev/null +++ b/drivers/misc/ioc4.c @@ -0,0 +1,473 @@ +/* + * 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. + * + * Copyright (C) 2005-2006 Silicon Graphics, Inc. All Rights Reserved. + */ + +/* This file contains the master driver module for use by SGI IOC4 subdrivers. + * + * It allocates any resources shared between multiple subdevices, and + * provides accessor functions (where needed) and the like for those + * resources. It also provides a mechanism for the subdevice modules + * to support loading and unloading. + * + * Non-shared resources (e.g. external interrupt A_INT_OUT register page + * alias, serial port and UART registers) are handled by the subdevice + * modules themselves. + * + * This is all necessary because IOC4 is not implemented as a multi-function + * PCI device, but an amalgamation of disparate registers for several + * types of device (ATA, serial, external interrupts). The normal + * resource management in the kernel doesn't have quite the right interfaces + * to handle this situation (e.g. multiple modules can't claim the same + * PCI ID), thus this IOC4 master module. + */ + +#include +#include +#include +#include +#include +#include +#include + +/*************** + * Definitions * + ***************/ + +/* Tweakable values */ + +/* PCI bus speed detection/calibration */ +#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */ +#define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */ +#define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */ +#define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */ +#define IOC4_CALIBRATE_HIGH_MHZ 75 /* Upper bound on bus speed sanity */ +#define IOC4_CALIBRATE_DEFAULT_MHZ 66 /* Assumed if sanity check fails */ + +/************************ + * Submodule management * + ************************/ + +static DEFINE_MUTEX(ioc4_mutex); + +static LIST_HEAD(ioc4_devices); +static LIST_HEAD(ioc4_submodules); + +/* Register an IOC4 submodule */ +int +ioc4_register_submodule(struct ioc4_submodule *is) +{ + struct ioc4_driver_data *idd; + + mutex_lock(&ioc4_mutex); + list_add(&is->is_list, &ioc4_submodules); + + /* Initialize submodule for each IOC4 */ + if (!is->is_probe) + goto out; + + list_for_each_entry(idd, &ioc4_devices, idd_list) { + if (is->is_probe(idd)) { + printk(KERN_WARNING + "%s: IOC4 submodule %s probe failed " + "for pci_dev %s", + __FUNCTION__, module_name(is->is_owner), + pci_name(idd->idd_pdev)); + } + } + out: + mutex_unlock(&ioc4_mutex); + return 0; +} + +/* Unregister an IOC4 submodule */ +void +ioc4_unregister_submodule(struct ioc4_submodule *is) +{ + struct ioc4_driver_data *idd; + + mutex_lock(&ioc4_mutex); + list_del(&is->is_list); + + /* Remove submodule for each IOC4 */ + if (!is->is_remove) + goto out; + + list_for_each_entry(idd, &ioc4_devices, idd_list) { + if (is->is_remove(idd)) { + printk(KERN_WARNING + "%s: IOC4 submodule %s remove failed " + "for pci_dev %s.\n", + __FUNCTION__, module_name(is->is_owner), + pci_name(idd->idd_pdev)); + } + } + out: + mutex_unlock(&ioc4_mutex); +} + +/********************* + * Device management * + *********************/ + +#define IOC4_CALIBRATE_LOW_LIMIT \ + (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ) +#define IOC4_CALIBRATE_HIGH_LIMIT \ + (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ) +#define IOC4_CALIBRATE_DEFAULT \ + (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ) + +#define IOC4_CALIBRATE_END \ + (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD) + +#define IOC4_INT_OUT_MODE_TOGGLE 0x7 /* Toggle INT_OUT every COUNT+1 ticks */ + +/* Determines external interrupt output clock period of the PCI bus an + * IOC4 is attached to. This value can be used to determine the PCI + * bus speed. + * + * IOC4 has a design feature that various internal timers are derived from + * the PCI bus clock. This causes IOC4 device drivers to need to take the + * bus speed into account when setting various register values (e.g. INT_OUT + * register COUNT field, UART divisors, etc). Since this information is + * needed by several subdrivers, it is determined by the main IOC4 driver, + * even though the following code utilizes external interrupt registers + * to perform the speed calculation. + */ +static void +ioc4_clock_calibrate(struct ioc4_driver_data *idd) +{ + union ioc4_int_out int_out; + union ioc4_gpcr gpcr; + unsigned int state, last_state = 1; + struct timespec start_ts, end_ts; + uint64_t start, end, period; + unsigned int count = 0; + + /* Enable output */ + gpcr.raw = 0; + gpcr.fields.dir = IOC4_GPCR_DIR_0; + gpcr.fields.int_out_en = 1; + writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw); + + /* Reset to power-on state */ + writel(0, &idd->idd_misc_regs->int_out.raw); + mmiowb(); + + /* Set up square wave */ + int_out.raw = 0; + int_out.fields.count = IOC4_CALIBRATE_COUNT; + int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE; + int_out.fields.diag = 0; + writel(int_out.raw, &idd->idd_misc_regs->int_out.raw); + mmiowb(); + + /* Check square wave period averaged over some number of cycles */ + do { + int_out.raw = readl(&idd->idd_misc_regs->int_out.raw); + state = int_out.fields.int_out; + if (!last_state && state) { + count++; + if (count == IOC4_CALIBRATE_END) { + ktime_get_ts(&end_ts); + break; + } else if (count == IOC4_CALIBRATE_DISCARD) + ktime_get_ts(&start_ts); + } + last_state = state; + } while (1); + + /* Calculation rearranged to preserve intermediate precision. + * Logically: + * 1. "end - start" gives us the measurement period over all + * the square wave cycles. + * 2. Divide by number of square wave cycles to get the period + * of a square wave cycle. + * 3. Divide by 2*(int_out.fields.count+1), which is the formula + * by which the IOC4 generates the square wave, to get the + * period of an IOC4 INT_OUT count. + */ + end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec; + start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec; + period = (end - start) / + (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)); + + /* Bounds check the result. */ + if (period > IOC4_CALIBRATE_LOW_LIMIT || + period < IOC4_CALIBRATE_HIGH_LIMIT) { + printk(KERN_INFO + "IOC4 %s: Clock calibration failed. Assuming" + "PCI clock is %d ns.\n", + pci_name(idd->idd_pdev), + IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR); + period = IOC4_CALIBRATE_DEFAULT; + } else { + u64 ns = period; + + do_div(ns, IOC4_EXTINT_COUNT_DIVISOR); + printk(KERN_DEBUG + "IOC4 %s: PCI clock is %lld ns.\n", + pci_name(idd->idd_pdev), ns); + } + + /* Remember results. We store the extint clock period rather + * than the PCI clock period so that greater precision is + * retained. Divide by IOC4_EXTINT_COUNT_DIVISOR to get + * PCI clock period. + */ + idd->count_period = period; +} + +/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT. + * Each brings out different combinations of IOC4 signals, thus. + * the IOC4 subdrivers need to know to which we're attached. + * + * We look for the presence of a SCSI (IO9) or SATA (IO10) controller + * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. + * If neither is present, it's a PCI-RT. + */ +static unsigned int +ioc4_variant(struct ioc4_driver_data *idd) +{ + struct pci_dev *pdev = NULL; + int found = 0; + + /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */ + do { + pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP12160, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO9; + + /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ + pdev = NULL; + do { + pdev = pci_get_device(PCI_VENDOR_ID_VITESSE, + PCI_DEVICE_ID_VITESSE_VSC7174, pdev); + if (pdev && + idd->idd_pdev->bus->number == pdev->bus->number && + 3 == PCI_SLOT(pdev->devfn)) + found = 1; + pci_dev_put(pdev); + } while (pdev && !found); + if (NULL != pdev) + return IOC4_VARIANT_IO10; + + /* PCI-RT: No SCSI/SATA controller will be present */ + return IOC4_VARIANT_PCI_RT; +} + +/* Adds a new instance of an IOC4 card */ +static int +ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) +{ + struct ioc4_driver_data *idd; + struct ioc4_submodule *is; + uint32_t pcmd; + int ret; + + /* Enable IOC4 and take ownership of it */ + if ((ret = pci_enable_device(pdev))) { + printk(KERN_WARNING + "%s: Failed to enable IOC4 device for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + goto out; + } + pci_set_master(pdev); + + /* Set up per-IOC4 data */ + idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL); + if (!idd) { + printk(KERN_WARNING + "%s: Failed to allocate IOC4 data for pci_dev %s.\n", + __FUNCTION__, pci_name(pdev)); + ret = -ENODEV; + goto out_idd; + } + idd->idd_pdev = pdev; + idd->idd_pci_id = pci_id; + + /* Map IOC4 misc registers. These are shared between subdevices + * so the main IOC4 module manages them. + */ + idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0); + if (!idd->idd_bar0) { + printk(KERN_WARNING + "%s: Unable to find IOC4 misc resource " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(idd->idd_pdev)); + ret = -ENODEV; + goto out_pci; + } + if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs), + "ioc4_misc")) { + printk(KERN_WARNING + "%s: Unable to request IOC4 misc region " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(idd->idd_pdev)); + ret = -ENODEV; + goto out_pci; + } + idd->idd_misc_regs = ioremap(idd->idd_bar0, + sizeof(struct ioc4_misc_regs)); + if (!idd->idd_misc_regs) { + printk(KERN_WARNING + "%s: Unable to remap IOC4 misc region " + "for pci_dev %s.\n", + __FUNCTION__, pci_name(idd->idd_pdev)); + ret = -ENODEV; + goto out_misc_region; + } + + /* Failsafe portion of per-IOC4 initialization */ + + /* Detect card variant */ + idd->idd_variant = ioc4_variant(idd); + printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev), + idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" : + idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" : + idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown"); + + /* Initialize IOC4 */ + pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd); + pci_write_config_dword(idd->idd_pdev, PCI_COMMAND, + pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR); + + /* Determine PCI clock */ + ioc4_clock_calibrate(idd); + + /* Disable/clear all interrupts. Need to do this here lest + * one submodule request the shared IOC4 IRQ, but interrupt + * is generated by a different subdevice. + */ + /* Disable */ + writel(~0, &idd->idd_misc_regs->other_iec.raw); + writel(~0, &idd->idd_misc_regs->sio_iec); + /* Clear (i.e. acknowledge) */ + writel(~0, &idd->idd_misc_regs->other_ir.raw); + writel(~0, &idd->idd_misc_regs->sio_ir); + + /* Track PCI-device specific data */ + idd->idd_serial_data = NULL; + pci_set_drvdata(idd->idd_pdev, idd); + + mutex_lock(&ioc4_mutex); + list_add_tail(&idd->idd_list, &ioc4_devices); + + /* Add this IOC4 to all submodules */ + list_for_each_entry(is, &ioc4_submodules, is_list) { + if (is->is_probe && is->is_probe(idd)) { + printk(KERN_WARNING + "%s: IOC4 submodule 0x%s probe failed " + "for pci_dev %s.\n", + __FUNCTION__, module_name(is->is_owner), + pci_name(idd->idd_pdev)); + } + } + mutex_unlock(&ioc4_mutex); + + return 0; + +out_misc_region: + release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); +out_pci: + kfree(idd); +out_idd: + pci_disable_device(pdev); +out: + return ret; +} + +/* Removes a particular instance of an IOC4 card. */ +static void +ioc4_remove(struct pci_dev *pdev) +{ + struct ioc4_submodule *is; + struct ioc4_driver_data *idd; + + idd = pci_get_drvdata(pdev); + + /* Remove this IOC4 from all submodules */ + mutex_lock(&ioc4_mutex); + list_for_each_entry(is, &ioc4_submodules, is_list) { + if (is->is_remove && is->is_remove(idd)) { + printk(KERN_WARNING + "%s: IOC4 submodule 0x%s remove failed " + "for pci_dev %s.\n", + __FUNCTION__, module_name(is->is_owner), + pci_name(idd->idd_pdev)); + } + } + mutex_unlock(&ioc4_mutex); + + /* Release resources */ + iounmap(idd->idd_misc_regs); + if (!idd->idd_bar0) { + printk(KERN_WARNING + "%s: Unable to get IOC4 misc mapping for pci_dev %s. " + "Device removal may be incomplete.\n", + __FUNCTION__, pci_name(idd->idd_pdev)); + } + release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); + + /* Disable IOC4 and relinquish */ + pci_disable_device(pdev); + + /* Remove and free driver data */ + mutex_lock(&ioc4_mutex); + list_del(&idd->idd_list); + mutex_unlock(&ioc4_mutex); + kfree(idd); +} + +static struct pci_device_id ioc4_id_table[] = { + {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID, + PCI_ANY_ID, 0x0b4000, 0xFFFFFF}, + {0} +}; + +static struct pci_driver ioc4_driver = { + .name = "IOC4", + .id_table = ioc4_id_table, + .probe = ioc4_probe, + .remove = ioc4_remove, +}; + +MODULE_DEVICE_TABLE(pci, ioc4_id_table); + +/********************* + * Module management * + *********************/ + +/* Module load */ +static int __devinit +ioc4_init(void) +{ + return pci_register_driver(&ioc4_driver); +} + +/* Module unload */ +static void __devexit +ioc4_exit(void) +{ + pci_unregister_driver(&ioc4_driver); +} + +module_init(ioc4_init); +module_exit(ioc4_exit); + +MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. "); +MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ioc4_register_submodule); +EXPORT_SYMBOL(ioc4_unregister_submodule); diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 98ce88d80207..ff4fa25f9fd1 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2935,7 +2935,7 @@ static void __devexit ioc4_serial_exit(void) uart_unregister_driver(&ioc4_uart_rs422); } -module_init(ioc4_serial_init); +late_initcall(ioc4_serial_init); /* Call only after tty init is done */ module_exit(ioc4_serial_exit); MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) "); diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig index 34d4fde51a79..c66ba9ad833d 100644 --- a/drivers/sn/Kconfig +++ b/drivers/sn/Kconfig @@ -5,18 +5,6 @@ menu "SN Devices" depends on SGI_SN -config SGI_IOC4 - tristate "SGI IOC4 Base IO support" - default m - ---help--- - This option enables basic support for the IOC4 chip on certain - SGI IO controller cards (IO9, IO10, and PCI-RT). This option - does not enable any specific functions on such a card, but provides - necessary infrastructure for other drivers to utilize. - - If you have an SGI Altix with an IOC4-based card say Y. - Otherwise say N. - config SGI_IOC3 tristate "SGI IOC3 Base IO support" default m diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile index 2cda011597c0..693db8bb8d9c 100644 --- a/drivers/sn/Makefile +++ b/drivers/sn/Makefile @@ -3,5 +3,4 @@ # # -obj-$(CONFIG_SGI_IOC4) += ioc4.o obj-$(CONFIG_SGI_IOC3) += ioc3.o diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c deleted file mode 100644 index 83d2e90c581c..000000000000 --- a/drivers/sn/ioc4.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - * 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. - * - * Copyright (C) 2005-2006 Silicon Graphics, Inc. All Rights Reserved. - */ - -/* This file contains the master driver module for use by SGI IOC4 subdrivers. - * - * It allocates any resources shared between multiple subdevices, and - * provides accessor functions (where needed) and the like for those - * resources. It also provides a mechanism for the subdevice modules - * to support loading and unloading. - * - * Non-shared resources (e.g. external interrupt A_INT_OUT register page - * alias, serial port and UART registers) are handled by the subdevice - * modules themselves. - * - * This is all necessary because IOC4 is not implemented as a multi-function - * PCI device, but an amalgamation of disparate registers for several - * types of device (ATA, serial, external interrupts). The normal - * resource management in the kernel doesn't have quite the right interfaces - * to handle this situation (e.g. multiple modules can't claim the same - * PCI ID), thus this IOC4 master module. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/*************** - * Definitions * - ***************/ - -/* Tweakable values */ - -/* PCI bus speed detection/calibration */ -#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */ -#define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */ -#define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */ -#define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */ -#define IOC4_CALIBRATE_HIGH_MHZ 75 /* Upper bound on bus speed sanity */ -#define IOC4_CALIBRATE_DEFAULT_MHZ 66 /* Assumed if sanity check fails */ - -/************************ - * Submodule management * - ************************/ - -static DEFINE_MUTEX(ioc4_mutex); - -static LIST_HEAD(ioc4_devices); -static LIST_HEAD(ioc4_submodules); - -/* Register an IOC4 submodule */ -int -ioc4_register_submodule(struct ioc4_submodule *is) -{ - struct ioc4_driver_data *idd; - - mutex_lock(&ioc4_mutex); - list_add(&is->is_list, &ioc4_submodules); - - /* Initialize submodule for each IOC4 */ - if (!is->is_probe) - goto out; - - list_for_each_entry(idd, &ioc4_devices, idd_list) { - if (is->is_probe(idd)) { - printk(KERN_WARNING - "%s: IOC4 submodule %s probe failed " - "for pci_dev %s", - __FUNCTION__, module_name(is->is_owner), - pci_name(idd->idd_pdev)); - } - } - out: - mutex_unlock(&ioc4_mutex); - return 0; -} - -/* Unregister an IOC4 submodule */ -void -ioc4_unregister_submodule(struct ioc4_submodule *is) -{ - struct ioc4_driver_data *idd; - - mutex_lock(&ioc4_mutex); - list_del(&is->is_list); - - /* Remove submodule for each IOC4 */ - if (!is->is_remove) - goto out; - - list_for_each_entry(idd, &ioc4_devices, idd_list) { - if (is->is_remove(idd)) { - printk(KERN_WARNING - "%s: IOC4 submodule %s remove failed " - "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), - pci_name(idd->idd_pdev)); - } - } - out: - mutex_unlock(&ioc4_mutex); -} - -/********************* - * Device management * - *********************/ - -#define IOC4_CALIBRATE_LOW_LIMIT \ - (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ) -#define IOC4_CALIBRATE_HIGH_LIMIT \ - (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ) -#define IOC4_CALIBRATE_DEFAULT \ - (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ) - -#define IOC4_CALIBRATE_END \ - (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD) - -#define IOC4_INT_OUT_MODE_TOGGLE 0x7 /* Toggle INT_OUT every COUNT+1 ticks */ - -/* Determines external interrupt output clock period of the PCI bus an - * IOC4 is attached to. This value can be used to determine the PCI - * bus speed. - * - * IOC4 has a design feature that various internal timers are derived from - * the PCI bus clock. This causes IOC4 device drivers to need to take the - * bus speed into account when setting various register values (e.g. INT_OUT - * register COUNT field, UART divisors, etc). Since this information is - * needed by several subdrivers, it is determined by the main IOC4 driver, - * even though the following code utilizes external interrupt registers - * to perform the speed calculation. - */ -static void -ioc4_clock_calibrate(struct ioc4_driver_data *idd) -{ - union ioc4_int_out int_out; - union ioc4_gpcr gpcr; - unsigned int state, last_state = 1; - struct timespec start_ts, end_ts; - uint64_t start, end, period; - unsigned int count = 0; - - /* Enable output */ - gpcr.raw = 0; - gpcr.fields.dir = IOC4_GPCR_DIR_0; - gpcr.fields.int_out_en = 1; - writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw); - - /* Reset to power-on state */ - writel(0, &idd->idd_misc_regs->int_out.raw); - mmiowb(); - - /* Set up square wave */ - int_out.raw = 0; - int_out.fields.count = IOC4_CALIBRATE_COUNT; - int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE; - int_out.fields.diag = 0; - writel(int_out.raw, &idd->idd_misc_regs->int_out.raw); - mmiowb(); - - /* Check square wave period averaged over some number of cycles */ - do { - int_out.raw = readl(&idd->idd_misc_regs->int_out.raw); - state = int_out.fields.int_out; - if (!last_state && state) { - count++; - if (count == IOC4_CALIBRATE_END) { - ktime_get_ts(&end_ts); - break; - } else if (count == IOC4_CALIBRATE_DISCARD) - ktime_get_ts(&start_ts); - } - last_state = state; - } while (1); - - /* Calculation rearranged to preserve intermediate precision. - * Logically: - * 1. "end - start" gives us the measurement period over all - * the square wave cycles. - * 2. Divide by number of square wave cycles to get the period - * of a square wave cycle. - * 3. Divide by 2*(int_out.fields.count+1), which is the formula - * by which the IOC4 generates the square wave, to get the - * period of an IOC4 INT_OUT count. - */ - end = end_ts.tv_sec * NSEC_PER_SEC + end_ts.tv_nsec; - start = start_ts.tv_sec * NSEC_PER_SEC + start_ts.tv_nsec; - period = (end - start) / - (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)); - - /* Bounds check the result. */ - if (period > IOC4_CALIBRATE_LOW_LIMIT || - period < IOC4_CALIBRATE_HIGH_LIMIT) { - printk(KERN_INFO - "IOC4 %s: Clock calibration failed. Assuming" - "PCI clock is %d ns.\n", - pci_name(idd->idd_pdev), - IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR); - period = IOC4_CALIBRATE_DEFAULT; - } else { - printk(KERN_DEBUG - "IOC4 %s: PCI clock is %ld ns.\n", - pci_name(idd->idd_pdev), - period / IOC4_EXTINT_COUNT_DIVISOR); - } - - /* Remember results. We store the extint clock period rather - * than the PCI clock period so that greater precision is - * retained. Divide by IOC4_EXTINT_COUNT_DIVISOR to get - * PCI clock period. - */ - idd->count_period = period; -} - -/* There are three variants of IOC4 cards: IO9, IO10, and PCI-RT. - * Each brings out different combinations of IOC4 signals, thus. - * the IOC4 subdrivers need to know to which we're attached. - * - * We look for the presence of a SCSI (IO9) or SATA (IO10) controller - * on the same PCI bus at slot number 3 to differentiate IO9 from IO10. - * If neither is present, it's a PCI-RT. - */ -static unsigned int -ioc4_variant(struct ioc4_driver_data *idd) -{ - struct pci_dev *pdev = NULL; - int found = 0; - - /* IO9: Look for a QLogic ISP 12160 at the same bus and slot 3. */ - do { - pdev = pci_get_device(PCI_VENDOR_ID_QLOGIC, - PCI_DEVICE_ID_QLOGIC_ISP12160, pdev); - if (pdev && - idd->idd_pdev->bus->number == pdev->bus->number && - 3 == PCI_SLOT(pdev->devfn)) - found = 1; - pci_dev_put(pdev); - } while (pdev && !found); - if (NULL != pdev) - return IOC4_VARIANT_IO9; - - /* IO10: Look for a Vitesse VSC 7174 at the same bus and slot 3. */ - pdev = NULL; - do { - pdev = pci_get_device(PCI_VENDOR_ID_VITESSE, - PCI_DEVICE_ID_VITESSE_VSC7174, pdev); - if (pdev && - idd->idd_pdev->bus->number == pdev->bus->number && - 3 == PCI_SLOT(pdev->devfn)) - found = 1; - pci_dev_put(pdev); - } while (pdev && !found); - if (NULL != pdev) - return IOC4_VARIANT_IO10; - - /* PCI-RT: No SCSI/SATA controller will be present */ - return IOC4_VARIANT_PCI_RT; -} - -/* Adds a new instance of an IOC4 card */ -static int -ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) -{ - struct ioc4_driver_data *idd; - struct ioc4_submodule *is; - uint32_t pcmd; - int ret; - - /* Enable IOC4 and take ownership of it */ - if ((ret = pci_enable_device(pdev))) { - printk(KERN_WARNING - "%s: Failed to enable IOC4 device for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - goto out; - } - pci_set_master(pdev); - - /* Set up per-IOC4 data */ - idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL); - if (!idd) { - printk(KERN_WARNING - "%s: Failed to allocate IOC4 data for pci_dev %s.\n", - __FUNCTION__, pci_name(pdev)); - ret = -ENODEV; - goto out_idd; - } - idd->idd_pdev = pdev; - idd->idd_pci_id = pci_id; - - /* Map IOC4 misc registers. These are shared between subdevices - * so the main IOC4 module manages them. - */ - idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0); - if (!idd->idd_bar0) { - printk(KERN_WARNING - "%s: Unable to find IOC4 misc resource " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); - ret = -ENODEV; - goto out_pci; - } - if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs), - "ioc4_misc")) { - printk(KERN_WARNING - "%s: Unable to request IOC4 misc region " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); - ret = -ENODEV; - goto out_pci; - } - idd->idd_misc_regs = ioremap(idd->idd_bar0, - sizeof(struct ioc4_misc_regs)); - if (!idd->idd_misc_regs) { - printk(KERN_WARNING - "%s: Unable to remap IOC4 misc region " - "for pci_dev %s.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); - ret = -ENODEV; - goto out_misc_region; - } - - /* Failsafe portion of per-IOC4 initialization */ - - /* Detect card variant */ - idd->idd_variant = ioc4_variant(idd); - printk(KERN_INFO "IOC4 %s: %s card detected.\n", pci_name(pdev), - idd->idd_variant == IOC4_VARIANT_IO9 ? "IO9" : - idd->idd_variant == IOC4_VARIANT_PCI_RT ? "PCI-RT" : - idd->idd_variant == IOC4_VARIANT_IO10 ? "IO10" : "unknown"); - - /* Initialize IOC4 */ - pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd); - pci_write_config_dword(idd->idd_pdev, PCI_COMMAND, - pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR); - - /* Determine PCI clock */ - ioc4_clock_calibrate(idd); - - /* Disable/clear all interrupts. Need to do this here lest - * one submodule request the shared IOC4 IRQ, but interrupt - * is generated by a different subdevice. - */ - /* Disable */ - writel(~0, &idd->idd_misc_regs->other_iec.raw); - writel(~0, &idd->idd_misc_regs->sio_iec); - /* Clear (i.e. acknowledge) */ - writel(~0, &idd->idd_misc_regs->other_ir.raw); - writel(~0, &idd->idd_misc_regs->sio_ir); - - /* Track PCI-device specific data */ - idd->idd_serial_data = NULL; - pci_set_drvdata(idd->idd_pdev, idd); - - mutex_lock(&ioc4_mutex); - list_add_tail(&idd->idd_list, &ioc4_devices); - - /* Add this IOC4 to all submodules */ - list_for_each_entry(is, &ioc4_submodules, is_list) { - if (is->is_probe && is->is_probe(idd)) { - printk(KERN_WARNING - "%s: IOC4 submodule 0x%s probe failed " - "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), - pci_name(idd->idd_pdev)); - } - } - mutex_unlock(&ioc4_mutex); - - return 0; - -out_misc_region: - release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); -out_pci: - kfree(idd); -out_idd: - pci_disable_device(pdev); -out: - return ret; -} - -/* Removes a particular instance of an IOC4 card. */ -static void -ioc4_remove(struct pci_dev *pdev) -{ - struct ioc4_submodule *is; - struct ioc4_driver_data *idd; - - idd = pci_get_drvdata(pdev); - - /* Remove this IOC4 from all submodules */ - mutex_lock(&ioc4_mutex); - list_for_each_entry(is, &ioc4_submodules, is_list) { - if (is->is_remove && is->is_remove(idd)) { - printk(KERN_WARNING - "%s: IOC4 submodule 0x%s remove failed " - "for pci_dev %s.\n", - __FUNCTION__, module_name(is->is_owner), - pci_name(idd->idd_pdev)); - } - } - mutex_unlock(&ioc4_mutex); - - /* Release resources */ - iounmap(idd->idd_misc_regs); - if (!idd->idd_bar0) { - printk(KERN_WARNING - "%s: Unable to get IOC4 misc mapping for pci_dev %s. " - "Device removal may be incomplete.\n", - __FUNCTION__, pci_name(idd->idd_pdev)); - } - release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs)); - - /* Disable IOC4 and relinquish */ - pci_disable_device(pdev); - - /* Remove and free driver data */ - mutex_lock(&ioc4_mutex); - list_del(&idd->idd_list); - mutex_unlock(&ioc4_mutex); - kfree(idd); -} - -static struct pci_device_id ioc4_id_table[] = { - {PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID, - PCI_ANY_ID, 0x0b4000, 0xFFFFFF}, - {0} -}; - -static struct pci_driver ioc4_driver = { - .name = "IOC4", - .id_table = ioc4_id_table, - .probe = ioc4_probe, - .remove = ioc4_remove, -}; - -MODULE_DEVICE_TABLE(pci, ioc4_id_table); - -/********************* - * Module management * - *********************/ - -/* Module load */ -static int __devinit -ioc4_init(void) -{ - return pci_register_driver(&ioc4_driver); -} - -/* Module unload */ -static void __devexit -ioc4_exit(void) -{ - pci_unregister_driver(&ioc4_driver); -} - -module_init(ioc4_init); -module_exit(ioc4_exit); - -MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. "); -MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(ioc4_register_submodule); -EXPORT_SYMBOL(ioc4_unregister_submodule); -- cgit v1.2.3 From 623a43952abfad2d48f287d1fab07b2089d07554 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Tue, 17 Oct 2006 00:09:27 -0700 Subject: [PATCH] synclink: remove PAGE_SIZE reference Remove reference to PAGE_SIZE that causes errors if PAGE_SIZE != 4096 Signed-off-by: Paul Fulghum Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index f2864cc64240..06784adcc35c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -133,8 +133,8 @@ static MGSL_PARAMS default_params = { }; #define SHARED_MEM_ADDRESS_SIZE 0x40000 -#define BUFFERLISTSIZE (PAGE_SIZE) -#define DMABUFFERSIZE (PAGE_SIZE) +#define BUFFERLISTSIZE 4096 +#define DMABUFFERSIZE 4096 #define MAXRXFRAMES 7 typedef struct _DMABUFFERENTRY -- cgit v1.2.3 From e24650c2e744f99541125a5b023f0d02cad19d14 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 17 Oct 2006 00:09:38 -0700 Subject: [PATCH] md: fix /proc/mdstat refcounting I have seen mdadm oops after successfully unloading md module. This patch privents from unloading md module while mdadm is polling /proc/mdstat. Cc: Neil Brown Signed-off-by: Akinbou Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 57fa64f93e5f..f7f19088f3be 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4912,6 +4912,7 @@ static unsigned int mdstat_poll(struct file *filp, poll_table *wait) } static struct file_operations md_seq_fops = { + .owner = THIS_MODULE, .open = md_seq_open, .read = seq_read, .llseek = seq_lseek, -- cgit v1.2.3 From f9b2e97bea228739b74b541033b1119c5707200b Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Tue, 17 Oct 2006 00:09:47 -0700 Subject: [PATCH] w1 kconfig fix Remove dependency of w1 subsytem from connector, only w1_con must depend on it. With attached patch applied to vanilla 2.6.19-git things works fine. Signed-off-by: Evgeniy Polyakov Cc: Cc: Greg KH Cc: Roman Zippel Cc: "Randy.Dunlap" Cc: Adrian Bunk Acked-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig index 27c9d05d03ef..c287a9ae4fdd 100644 --- a/drivers/w1/Kconfig +++ b/drivers/w1/Kconfig @@ -2,7 +2,6 @@ menu "Dallas's 1-wire bus" config W1 tristate "Dallas's 1-wire support" - depends on CONNECTOR ---help--- Dallas' 1-wire bus is useful to connect slow 1-pin devices such as iButtons and thermal sensors. -- cgit v1.2.3 From c430169e0c9f42f2cd27e0a6161e7ff4dc7e608d Mon Sep 17 00:00:00 2001 From: Francisco Larramendi Date: Tue, 17 Oct 2006 00:09:53 -0700 Subject: [PATCH] rtc-max6902: month conversion fix Fix October-only BCD-to-binary conversion bug: 0x08 -> 7 0x09 -> 8 0x10 -> 15 (!) 0x11 -> 19 Fixes http://bugzilla.kernel.org/show_bug.cgi?id=7361 Cc: Raphael Assenat Cc: Alessandro Zummo Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-max6902.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 0b20dfacbf59..d94170728075 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -136,7 +136,7 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt) dt->tm_min = BCD2BIN(chip->buf[2]); dt->tm_hour = BCD2BIN(chip->buf[3]); dt->tm_mday = BCD2BIN(chip->buf[4]); - dt->tm_mon = BCD2BIN(chip->buf[5] - 1); + dt->tm_mon = BCD2BIN(chip->buf[5]) - 1; dt->tm_wday = BCD2BIN(chip->buf[6]); dt->tm_year = BCD2BIN(chip->buf[7]); -- cgit v1.2.3 From 1fec74a9cda95772887c82ede5c0ac60f5be857e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 17 Oct 2006 00:09:58 -0700 Subject: [PATCH] acpi_processor_latency_notifier(): UP warning fix drivers/acpi/processor_idle.c:1112: warning: 'smp_callback' defined but not used Cc: Len Brown Cc: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/processor_idle.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 526387dc3799..e67144cf3c8b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1108,6 +1108,7 @@ static const struct file_operations acpi_processor_power_fops = { .release = single_release, }; +#ifdef CONFIG_SMP static void smp_callback(void *v) { /* we already woke the CPU up, nothing more to do */ @@ -1129,6 +1130,7 @@ static int acpi_processor_latency_notify(struct notifier_block *b, static struct notifier_block acpi_processor_latency_notifier = { .notifier_call = acpi_processor_latency_notify, }; +#endif int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) @@ -1146,7 +1148,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, "ACPI: processor limited to max C-state %d\n", max_cstate); first_run++; +#ifdef CONFIG_SMP register_latency_notifier(&acpi_processor_latency_notifier); +#endif } if (!pr) @@ -1218,7 +1222,9 @@ int acpi_processor_power_exit(struct acpi_processor *pr, * copies of pm_idle before proceeding. */ cpu_idle_wait(); +#ifdef CONFIG_SMP unregister_latency_notifier(&acpi_processor_latency_notifier); +#endif } return 0; -- cgit v1.2.3 From a4bb2cf1c3d30e7498e5561b22246b5bcbfe2e15 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 17 Oct 2006 00:10:00 -0700 Subject: [PATCH] drivers/char/specialix.c: fix the baud conversion Correct the following bugs introduced by commit 67cc0161ecc9ebee6eba4af6cbfdba028090b1b9: - remove one remaining and now incorrect baud_table[] usage - "baud +=" is no longer correct The former bug was spotted by the Coverity checker. Rolf Eike Beer spotted a bug in the initial version of my patch. Signed-off-by: Adrian Bunk Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/specialix.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index d0b88d0e87fd..7e1bd9562c2a 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -183,11 +183,6 @@ static int sx_poll = HZ; static struct tty_driver *specialix_driver; -static unsigned long baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 0, -}; - static struct specialix_board sx_board[SX_NBOARD] = { { 0, SX_IOBASE1, 9, }, { 0, SX_IOBASE2, 11, }, @@ -1090,9 +1085,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p if (baud == 38400) { if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - baud ++; + baud = 57600; if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - baud += 2; + baud = 115200; } if (!baud) { @@ -1150,11 +1145,9 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p sx_out(bp, CD186x_RBPRL, tmp & 0xff); sx_out(bp, CD186x_TBPRL, tmp & 0xff); spin_unlock_irqrestore(&bp->lock, flags); - if (port->custom_divisor) { + if (port->custom_divisor) baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; - baud = ( baud + 5 ) / 10; - } else - baud = (baud_table[baud] + 5) / 10; /* Estimated CPS */ + baud = (baud + 5) / 10; /* Estimated CPS */ /* Two timer ticks seems enough to wakeup something like SLIP driver */ tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO; -- cgit v1.2.3 From 48d1a7ea6373337985f27dc1c707649469df5827 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 17 Oct 2006 00:10:05 -0700 Subject: [PATCH] sx: fix user-visible typo (devic) Signed-off-by: Alexey Dobriyan Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/sx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/sx.c b/drivers/char/sx.c index 5fec626598cd..cc10af08cb05 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -2602,7 +2602,7 @@ static void __exit sx_exit (void) } } if (misc_deregister(&sx_fw_device) < 0) { - printk (KERN_INFO "sx: couldn't deregister firmware loader devic\n"); + printk (KERN_INFO "sx: couldn't deregister firmware loader device\n"); } sx_dprintk (SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n", sx_initialized); if (sx_initialized) -- cgit v1.2.3 From 12fda16814bba05a84a49a1da25a069d6c249758 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:20 -0700 Subject: [PATCH] drivers/led: handle sysfs errors Signed-off-by: Jeff Garzik Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/led-class.c | 26 +++++++++++++++++++++----- drivers/leds/ledtrig-timer.c | 16 ++++++++++++++-- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index aecbbe2e89a9..3c1711210e38 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -91,6 +91,8 @@ EXPORT_SYMBOL_GPL(led_classdev_resume); */ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) { + int rc; + led_cdev->class_dev = class_device_create(leds_class, NULL, 0, parent, "%s", led_cdev->name); if (unlikely(IS_ERR(led_cdev->class_dev))) @@ -99,8 +101,10 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) class_set_devdata(led_cdev->class_dev, led_cdev); /* register the attributes */ - class_device_create_file(led_cdev->class_dev, - &class_device_attr_brightness); + rc = class_device_create_file(led_cdev->class_dev, + &class_device_attr_brightness); + if (rc) + goto err_out; /* add to the list of leds */ write_lock(&leds_list_lock); @@ -110,16 +114,28 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) #ifdef CONFIG_LEDS_TRIGGERS rwlock_init(&led_cdev->trigger_lock); - led_trigger_set_default(led_cdev); + rc = class_device_create_file(led_cdev->class_dev, + &class_device_attr_trigger); + if (rc) + goto err_out_led_list; - class_device_create_file(led_cdev->class_dev, - &class_device_attr_trigger); + led_trigger_set_default(led_cdev); #endif printk(KERN_INFO "Registered led device: %s\n", led_cdev->class_dev->class_id); return 0; + +#ifdef CONFIG_LEDS_TRIGGERS +err_out_led_list: + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_brightness); + list_del(&led_cdev->node); +#endif +err_out: + class_device_unregister(led_cdev->class_dev); + return rc; } EXPORT_SYMBOL_GPL(led_classdev_register); diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 179c2876b541..29a8818a32ec 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c @@ -123,6 +123,7 @@ static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, static void timer_trig_activate(struct led_classdev *led_cdev) { struct timer_trig_data *timer_data; + int rc; timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); if (!timer_data) @@ -134,10 +135,21 @@ static void timer_trig_activate(struct led_classdev *led_cdev) timer_data->timer.function = led_timer_function; timer_data->timer.data = (unsigned long) led_cdev; - class_device_create_file(led_cdev->class_dev, + rc = class_device_create_file(led_cdev->class_dev, &class_device_attr_delay_on); - class_device_create_file(led_cdev->class_dev, + if (rc) goto err_out; + rc = class_device_create_file(led_cdev->class_dev, &class_device_attr_delay_off); + if (rc) goto err_out_delayon; + + return; + +err_out_delayon: + class_device_remove_file(led_cdev->class_dev, + &class_device_attr_delay_on); +err_out: + led_cdev->trigger_data = NULL; + kfree(timer_data); } static void timer_trig_deactivate(struct led_classdev *led_cdev) -- cgit v1.2.3 From 6b5f29675c6a1041aefc147271508bd56cf2b761 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:22 -0700 Subject: [PATCH] I2O: handle a few sysfs errors Signed-off-by: Jeff Garzik Cc: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/bus-osm.c | 12 ++++++++++-- drivers/message/i2o/exec-osm.c | 17 ++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c index ac06f10c54ec..d96c687aee93 100644 --- a/drivers/message/i2o/bus-osm.c +++ b/drivers/message/i2o/bus-osm.c @@ -80,18 +80,26 @@ static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan); * @dev: device to verify if it is a I2O Bus Adapter device * * Because we want all Bus Adapters always return 0. + * Except when we fail. Then we are sad. * - * Returns 0. + * Returns 0, except when we fail to excel. */ static int i2o_bus_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(get_device(dev)); + int rc; - device_create_file(dev, &dev_attr_scan); + rc = device_create_file(dev, &dev_attr_scan); + if (rc) + goto err_out; osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid); return 0; + +err_out: + put_device(dev); + return rc; }; /** diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 7bd4d85d0b42..91f95d172ca5 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -325,13 +325,24 @@ static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL); static int i2o_exec_probe(struct device *dev) { struct i2o_device *i2o_dev = to_i2o_device(dev); + int rc; - i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff); + if (rc) goto err_out; - device_create_file(dev, &dev_attr_vendor_id); - device_create_file(dev, &dev_attr_product_id); + rc = device_create_file(dev, &dev_attr_vendor_id); + if (rc) goto err_evtreg; + rc = device_create_file(dev, &dev_attr_product_id); + if (rc) goto err_vid; return 0; + +err_vid: + device_remove_file(dev, &dev_attr_vendor_id); +err_evtreg: + i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0); +err_out: + return rc; }; /** -- cgit v1.2.3 From 6a15f46c1272afd3010259067451bf0df04f6511 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:25 -0700 Subject: [PATCH] rtc: fix printk of 64-bit res on 32-bit platform With 64-bit resources on 32-bit platforms, the resource address might be larger than a void*. Fix printk to work regardless of resource size. Signed-off-by: Jeff Garzik Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-v3020.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c index 09b714f1cdc3..3b58d3d5d38a 100644 --- a/drivers/rtc/rtc-v3020.c +++ b/drivers/rtc/rtc-v3020.c @@ -195,9 +195,9 @@ static int rtc_probe(struct platform_device *pdev) * are all disabled */ v3020_set_reg(chip, V3020_STATUS_0, 0x0); - dev_info(&pdev->dev, "Chip available at physical address 0x%p," + dev_info(&pdev->dev, "Chip available at physical address 0x%llx," "data connected to D%d\n", - (void*)pdev->resource[0].start, + (unsigned long long)pdev->resource[0].start, chip->leftshift); platform_set_drvdata(pdev, chip); -- cgit v1.2.3 From ea6f94dfe9db4d19a39e774cfafa5c9428a9fdbc Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 17 Oct 2006 00:10:27 -0700 Subject: [PATCH] rd: memory leak on rd_init() failure If RAM disk driver initialization fails due to blk_alloc_queue() faulure, the gendisk structs stored in rd_disks[] will not be freed completely. This patch resolves that memory leak case by doing alloc_disk() and blk_alloc_queue() at the same time. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/rd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/rd.c b/drivers/block/rd.c index a3f64bfe6b58..485aa87e9bcd 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -432,6 +432,12 @@ static int __init rd_init(void) rd_disks[i] = alloc_disk(1); if (!rd_disks[i]) goto out; + + rd_queue[i] = blk_alloc_queue(GFP_KERNEL); + if (!rd_queue[i]) { + put_disk(rd_disks[i]); + goto out; + } } if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) { @@ -442,10 +448,6 @@ static int __init rd_init(void) for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) { struct gendisk *disk = rd_disks[i]; - rd_queue[i] = blk_alloc_queue(GFP_KERNEL); - if (!rd_queue[i]) - goto out_queue; - blk_queue_make_request(rd_queue[i], &rd_make_request); blk_queue_hardsect_size(rd_queue[i], rd_blocksize); @@ -466,8 +468,6 @@ static int __init rd_init(void) CONFIG_BLK_DEV_RAM_COUNT, rd_size, rd_blocksize); return 0; -out_queue: - unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); out: while (i--) { put_disk(rd_disks[i]); -- cgit v1.2.3 From dabad0568a5935e9f4903f5fd1d8f22b1c7c88c7 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Tue, 17 Oct 2006 00:10:28 -0700 Subject: [PATCH] epca: prevent panic on tty_register_driver() failure Make epca fail on initialization failure instead of panic. Cc: "Digi International, Inc" Signed-off-by: Akinobu Mita Acked-by: Alan Cox Acked-by: Scott Kilau Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/epca.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/char/epca.c b/drivers/char/epca.c index c3f95583a120..706733c0b36a 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -1157,6 +1157,7 @@ static int __init pc_init(void) int crd; struct board_info *bd; unsigned char board_id = 0; + int err = -ENOMEM; int pci_boards_found, pci_count; @@ -1164,13 +1165,11 @@ static int __init pc_init(void) pc_driver = alloc_tty_driver(MAX_ALLOC); if (!pc_driver) - return -ENOMEM; + goto out1; pc_info = alloc_tty_driver(MAX_ALLOC); - if (!pc_info) { - put_tty_driver(pc_driver); - return -ENOMEM; - } + if (!pc_info) + goto out2; /* ----------------------------------------------------------------------- If epca_setup has not been ran by LILO set num_cards to defaults; copy @@ -1370,11 +1369,17 @@ static int __init pc_init(void) } /* End for each card */ - if (tty_register_driver(pc_driver)) - panic("Couldn't register Digi PC/ driver"); + err = tty_register_driver(pc_driver); + if (err) { + printk(KERN_ERR "Couldn't register Digi PC/ driver"); + goto out3; + } - if (tty_register_driver(pc_info)) - panic("Couldn't register Digi PC/ info "); + err = tty_register_driver(pc_info); + if (err) { + printk(KERN_ERR "Couldn't register Digi PC/ info "); + goto out4; + } /* ------------------------------------------------------------------- Start up the poller to check for events on all enabled boards @@ -1385,6 +1390,15 @@ static int __init pc_init(void) mod_timer(&epca_timer, jiffies + HZ/25); return 0; +out4: + tty_unregister_driver(pc_driver); +out3: + put_tty_driver(pc_info); +out2: + put_tty_driver(pc_driver); +out1: + return err; + } /* End pc_init */ /* ------------------ Begin post_fep_init ---------------------- */ -- cgit v1.2.3 From 0d9ba869e103d91d471146378ad85bf1fb8e74b4 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Tue, 17 Oct 2006 00:10:36 -0700 Subject: [PATCH] drivers/isdn/hysdn: save_flags()/cli(), restore_flags() replaced appropriately With Karsten Keil save_flags()/cli() pair is replaced with spin_lock_irqsave() and restore_flags() replaced with spin_unlock_irqrestore() Tested compile only using allmodconfig Signed-off-by: Amol Lad Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hysdn/boardergo.c | 32 ++++++++++++++------------------ drivers/isdn/hysdn/hysdn_defs.h | 2 ++ drivers/isdn/hysdn/hysdn_proclog.c | 17 +++++++---------- drivers/isdn/hysdn/hysdn_sched.c | 9 ++++----- 4 files changed, 27 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index 160f22fa5941..8bbe33ae06db 100644 --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -45,11 +45,10 @@ ergo_interrupt(int intno, void *dev_id) if (!card->irq_enabled) return IRQ_NONE; /* other device interrupting or irq switched off */ - save_flags(flags); - cli(); /* no further irqs allowed */ + spin_lock_irqsave(&card->hysdn_lock, flags); /* no further irqs allowed */ if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) { - restore_flags(flags); /* restore old state */ + spin_unlock_irqrestore(&card->hysdn_lock, flags); /* restore old state */ return IRQ_NONE; /* no interrupt requested by E1 */ } /* clear any pending ints on the board */ @@ -61,7 +60,7 @@ ergo_interrupt(int intno, void *dev_id) /* start kernel task immediately after leaving all interrupts */ if (!card->hw_lock) schedule_work(&card->irq_queue); - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); return IRQ_HANDLED; } /* ergo_interrupt */ @@ -83,10 +82,9 @@ ergo_irq_bh(hysdn_card * card) dpr = card->dpram; /* point to DPRAM */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); if (card->hw_lock) { - restore_flags(flags); /* hardware currently unavailable */ + spin_unlock_irqrestore(&card->hysdn_lock, flags); /* hardware currently unavailable */ return; } card->hw_lock = 1; /* we now lock the hardware */ @@ -120,7 +118,7 @@ ergo_irq_bh(hysdn_card * card) card->hw_lock = 0; /* free hardware again */ } while (again); /* until nothing more to do */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); } /* ergo_irq_bh */ @@ -137,8 +135,7 @@ ergo_stopcard(hysdn_card * card) #ifdef CONFIG_HYSDN_CAPI hycapi_capi_stop(card); #endif /* CONFIG_HYSDN_CAPI */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); val = bytein(card->iobase + PCI9050_INTR_REG); /* get actual value */ val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1); /* mask irq */ byteout(card->iobase + PCI9050_INTR_REG, val); @@ -147,7 +144,7 @@ ergo_stopcard(hysdn_card * card) card->state = CARD_STATE_UNUSED; card->err_log_state = ERRLOG_STATE_OFF; /* currently no log active */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); } /* ergo_stopcard */ /**************************************************************************/ @@ -162,12 +159,11 @@ ergo_set_errlog_state(hysdn_card * card, int on) card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ return; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) || ((card->err_log_state == ERRLOG_STATE_ON) && on)) { - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); return; /* nothing to do */ } if (on) @@ -175,7 +171,7 @@ ergo_set_errlog_state(hysdn_card * card, int on) else card->err_log_state = ERRLOG_STATE_STOP; /* request stop */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); schedule_work(&card->irq_queue); } /* ergo_set_errlog_state */ @@ -356,8 +352,7 @@ ergo_waitpofready(struct HYSDN_CARD *card) if (card->debug_flags & LOG_POF_RECORD) hysdn_addlog(card, "ERGO: pof boot success"); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); card->state = CARD_STATE_RUN; /* now card is running */ /* enable the cards interrupt */ @@ -370,7 +365,7 @@ ergo_waitpofready(struct HYSDN_CARD *card) dpr->ToHyInt = 1; dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); if ((hynet_enable & (1 << card->myid)) && (i = hysdn_net_create(card))) { @@ -448,6 +443,7 @@ ergo_inithardware(hysdn_card * card) card->waitpofready = ergo_waitpofready; card->set_errlog_state = ergo_set_errlog_state; INIT_WORK(&card->irq_queue, (void *) (void *) ergo_irq_bh, card); + card->hysdn_lock = SPIN_LOCK_UNLOCKED; return (0); } /* ergo_inithardware */ diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h index 461e831592dd..729df4089385 100644 --- a/drivers/isdn/hysdn/hysdn_defs.h +++ b/drivers/isdn/hysdn/hysdn_defs.h @@ -188,6 +188,8 @@ typedef struct HYSDN_CARD { /* init and deinit stopcard for booting, too */ void (*stopcard) (struct HYSDN_CARD *); void (*releasehardware) (struct HYSDN_CARD *); + + spinlock_t hysdn_lock; #ifdef CONFIG_HYSDN_CAPI struct hycapictrl_info { char cardname[32]; diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index c4301e8338ef..fcd49920b220 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -116,8 +116,7 @@ put_log_buffer(hysdn_card * card, char *cp) strcpy(ib->log_start, cp); /* set output string */ ib->next = NULL; ib->proc_ctrl = pd; /* point to own control structure */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); ib->usage_cnt = pd->if_used; if (!pd->log_head) pd->log_head = ib; /* new head */ @@ -125,7 +124,7 @@ put_log_buffer(hysdn_card * card, char *cp) pd->log_tail->next = ib; /* follows existing messages */ pd->log_tail = ib; /* new tail */ i = pd->del_lock++; /* get lock state */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); /* delete old entrys */ if (!i) @@ -270,14 +269,13 @@ hysdn_log_open(struct inode *ino, struct file *filep) } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { /* read access -> log/debug read */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); pd->if_used++; if (pd->log_head) filep->private_data = &pd->log_tail->next; else filep->private_data = &pd->log_head; - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); } else { /* simultaneous read/write access forbidden ! */ unlock_kernel(); return (-EPERM); /* no permission this time */ @@ -301,7 +299,7 @@ hysdn_log_close(struct inode *ino, struct file *filep) hysdn_card *card; int retval = 0; unsigned long flags; - + spinlock_t hysdn_lock = SPIN_LOCK_UNLOCKED; lock_kernel(); if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { @@ -311,8 +309,7 @@ hysdn_log_close(struct inode *ino, struct file *filep) /* read access -> log/debug read, mark one further file as closed */ pd = NULL; - save_flags(flags); - cli(); + spin_lock_irqsave(&hysdn_lock, flags); inf = *((struct log_data **) filep->private_data); /* get first log entry */ if (inf) pd = (struct procdata *) inf->proc_ctrl; /* still entries there */ @@ -335,7 +332,7 @@ hysdn_log_close(struct inode *ino, struct file *filep) inf->usage_cnt--; /* decrement usage count for buffers */ inf = inf->next; } - restore_flags(flags); + spin_unlock_irqrestore(&hysdn_lock, flags); if (pd) if (pd->if_used <= 0) /* delete buffers if last file closed */ diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 1c0d54ac12ab..1fadf0133e9b 100644 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -155,8 +155,7 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->hysdn_lock, flags); while (card->async_busy) { sti(); @@ -165,7 +164,7 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) msleep_interruptible(20); /* Timeout 20ms */ if (!--cnt) { - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); return (-ERR_ASYNC_TIME); /* timed out */ } cli(); @@ -194,13 +193,13 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) msleep_interruptible(20); /* Timeout 20ms */ if (!--cnt) { - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); return (-ERR_ASYNC_TIME); /* timed out */ } cli(); } /* wait for buffer to become free again */ - restore_flags(flags); + spin_unlock_irqrestore(&card->hysdn_lock, flags); if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg data send"); -- cgit v1.2.3 From 078d396598401dbaa88d5f95ec45579f9d3dce0e Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Tue, 17 Oct 2006 00:10:37 -0700 Subject: [PATCH] drivers/isdn/isdnloop: save_flags()/cli(), restore_flags() replaced appropriately Signed-off-by: Amol Lad Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/isdnloop/isdnloop.c | 70 +++++++++++++++++----------------------- drivers/isdn/isdnloop/isdnloop.h | 1 + 2 files changed, 31 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index fabbd461603e..23afba46433e 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -100,12 +100,11 @@ isdnloop_pollbchan(unsigned long data) isdnloop_bchan_send(card, 1); if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) { /* schedule b-channel polling again */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; add_timer(&card->rb_timer); card->flags |= ISDNLOOP_FLAGS_RBTIMER; - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } else card->flags &= ~ISDNLOOP_FLAGS_RBTIMER; } @@ -281,8 +280,7 @@ isdnloop_putmsg(isdnloop_card * card, unsigned char c) { ulong flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; if (card->msg_buf_write == card->msg_buf_read) { if (++card->msg_buf_read > card->msg_buf_end) @@ -290,7 +288,7 @@ isdnloop_putmsg(isdnloop_card * card, unsigned char c) } if (card->msg_buf_write > card->msg_buf_end) card->msg_buf_write = card->msg_buf; - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* @@ -372,21 +370,19 @@ isdnloop_polldchan(unsigned long data) if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { /* schedule b-channel polling */ card->flags |= ISDNLOOP_FLAGS_RBTIMER; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); del_timer(&card->rb_timer); card->rb_timer.function = isdnloop_pollbchan; card->rb_timer.data = (unsigned long) card; card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; add_timer(&card->rb_timer); - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* schedule again */ - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; add_timer(&card->st_timer); - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* @@ -416,8 +412,7 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card) return 0; if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE) return 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); nskb = dev_alloc_skb(skb->len); if (nskb) { memcpy(skb_put(nskb, len), skb->data, len); @@ -426,7 +421,7 @@ isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card) } else len = 0; card->sndcount[channel] += len; - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } return len; } @@ -576,8 +571,7 @@ isdnloop_atimeout(isdnloop_card * card, int ch) unsigned long flags; char buf[60]; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); if (card->rcard) { isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1); card->rcard[ch]->rcard[card->rch[ch]] = NULL; @@ -587,7 +581,7 @@ isdnloop_atimeout(isdnloop_card * card, int ch) /* No user responding */ sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3)); isdnloop_fake(card, buf, ch + 1); - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* @@ -622,8 +616,7 @@ isdnloop_start_ctimer(isdnloop_card * card, int ch) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); init_timer(&card->c_timer[ch]); card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; if (ch) @@ -632,7 +625,7 @@ isdnloop_start_ctimer(isdnloop_card * card, int ch) card->c_timer[ch].function = isdnloop_atimeout0; card->c_timer[ch].data = (unsigned long) card; add_timer(&card->c_timer[ch]); - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* @@ -647,10 +640,9 @@ isdnloop_kill_ctimer(isdnloop_card * card, int ch) { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); del_timer(&card->c_timer[ch]); - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } static u_char si2bit[] = @@ -706,13 +698,12 @@ isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) } } if (num_match) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); /* channel idle? */ if (!(cc->rcard[ch])) { /* Check SI */ if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return 3; } /* ch is idle, si and number matches */ @@ -720,10 +711,10 @@ isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) cc->rch[ch] = lch; card->rcard[lch] = cc; card->rch[lch] = ch; - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return 0; } else { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); /* num matches, but busy */ if (ch == 1) return 1; @@ -1027,8 +1018,7 @@ isdnloop_stopcard(isdnloop_card * card) unsigned long flags; isdn_ctrl cmd; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); if (card->flags & ISDNLOOP_FLAGS_RUNNING) { card->flags &= ~ISDNLOOP_FLAGS_RUNNING; del_timer(&card->st_timer); @@ -1039,7 +1029,7 @@ isdnloop_stopcard(isdnloop_card * card) cmd.driver = card->myid; card->interface.statcallb(&cmd); } - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); } /* @@ -1078,18 +1068,17 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) return -EBUSY; if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef))) return -EFAULT; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->isdnloop_lock, flags); switch (sdef.ptype) { case ISDN_PTYPE_EURO: if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96", -1)) { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } card->sil[0] = card->sil[1] = 4; if (isdnloop_fake(card, "TEI OK", 0)) { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } for (i = 0; i < 3; i++) @@ -1098,12 +1087,12 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) case ISDN_PTYPE_1TR6: if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", -1)) { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } card->sil[0] = card->sil[1] = 4; if (isdnloop_fake(card, "TEI OK", 0)) { - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } strcpy(card->s0num[0], sdef.num[0]); @@ -1111,7 +1100,7 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) card->s0num[2][0] = '\0'; break; default: - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n", sdef.ptype); return -EINVAL; @@ -1122,7 +1111,7 @@ isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) card->st_timer.data = (unsigned long) card; add_timer(&card->st_timer); card->flags |= ISDNLOOP_FLAGS_RUNNING; - restore_flags(flags); + spin_unlock_irqrestore(&card->isdnloop_lock, flags); return 0; } @@ -1472,6 +1461,7 @@ isdnloop_initcard(char *id) skb_queue_head_init(&card->bqueue[i]); } skb_queue_head_init(&card->dqueue); + card->isdnloop_lock = SPIN_LOCK_UNLOCKED; card->next = cards; cards = card; if (!register_isdn(&card->interface)) { diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index d699fe53e1c3..0d458a86f529 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -94,6 +94,7 @@ typedef struct isdnloop_card { struct sk_buff_head bqueue[ISDNLOOP_BCH]; /* B-Channel queues */ struct sk_buff_head dqueue; /* D-Channel queue */ + spinlock_t isdnloop_lock; } isdnloop_card; /* -- cgit v1.2.3 From 04518bfe8eac2e82b476fb2b0093527adc2bc791 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:39 -0700 Subject: [PATCH] ISDN: fix drivers, by handling errors thrown by ->readstat() This is a particularly ugly on-failure bug, possibly security, since the lack of error handling here is covering up another class of bug: failure to handle copy_to_user() return values. The I4L API function ->readstat() returns an integer, and by looking at several existing driver implementations, it is clear that a negative return value was meant to indicate an error. Given that several drivers already return a negative value indicating an errno-style error, the current code would blindly accept that [negative] value as a valid amount of bytes read. Obvious damage ensues. Correcting ->readstat() handling to properly notice errors fixes the existing code to work correctly on error, and enables future patches to more easily indicate errors during operation. Signed-off-by: Jeff Garzik Cc: Karsten Keil Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_common.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index c3d79eef9e32..69aee2602aa6 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1134,9 +1134,12 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off) if (dev->drv[drvidx]->interface->readstat) { if (count > dev->drv[drvidx]->stavail) count = dev->drv[drvidx]->stavail; - len = dev->drv[drvidx]->interface-> - readstat(buf, count, drvidx, - isdn_minor2chan(minor)); + len = dev->drv[drvidx]->interface->readstat(buf, count, + drvidx, isdn_minor2chan(minor)); + if (len < 0) { + retval = len; + goto out; + } } else { len = 0; } -- cgit v1.2.3 From 7786ce192fc4917fb9b789dd823476ff8fd6cf66 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 17 Oct 2006 00:10:40 -0700 Subject: [PATCH] ISDN: check for userspace copy faults Most of the ISDN ->readstat() implementations needed to check copy_to_user() and put_user() return values. Signed-off-by: Jeff Garzik Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/capi/capidrv.c | 3 ++- drivers/isdn/hisax/config.c | 6 ++++-- drivers/isdn/icn/icn.c | 3 ++- drivers/isdn/isdnloop/isdnloop.c | 3 ++- drivers/isdn/pcbit/drv.c | 16 ++++++++++------ 5 files changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c index d10c8b82e6aa..b6f9476c0501 100644 --- a/drivers/isdn/capi/capidrv.c +++ b/drivers/isdn/capi/capidrv.c @@ -1907,7 +1907,8 @@ static int if_readstat(u8 __user *buf, int len, int id, int channel) } for (p=buf, count=0; count < len; p++, count++) { - put_user(*card->q931_read++, p); + if (put_user(*card->q931_read++, p)) + return -EFAULT; if (card->q931_read > card->q931_end) card->q931_read = card->q931_buf; } diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c index e4823ab2b127..785b08554fca 100644 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -631,7 +631,8 @@ static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel) count = cs->status_end - cs->status_read + 1; if (count >= len) count = len; - copy_to_user(p, cs->status_read, count); + if (copy_to_user(p, cs->status_read, count)) + return -EFAULT; cs->status_read += count; if (cs->status_read > cs->status_end) cs->status_read = cs->status_buf; @@ -642,7 +643,8 @@ static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel) cnt = HISAX_STATUS_BUFSIZE; else cnt = count; - copy_to_user(p, cs->status_read, cnt); + if (copy_to_user(p, cs->status_read, cnt)) + return -EFAULT; p += cnt; cs->status_read += cnt % HISAX_STATUS_BUFSIZE; count -= cnt; diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 6649f8bc9951..730bbd07ebc7 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1010,7 +1010,8 @@ icn_readstatus(u_char __user *buf, int len, icn_card * card) for (p = buf, count = 0; count < len; p++, count++) { if (card->msg_buf_read == card->msg_buf_write) return count; - put_user(*card->msg_buf_read++, p); + if (put_user(*card->msg_buf_read++, p)) + return -EFAULT; if (card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 23afba46433e..c3ae2edaf6fa 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -446,7 +446,8 @@ isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card * card) for (p = buf, count = 0; count < len; p++, count++) { if (card->msg_buf_read == card->msg_buf_write) return count; - put_user(*card->msg_buf_read++, p); + if (put_user(*card->msg_buf_read++, p)) + return -EFAULT; if (card->msg_buf_read > card->msg_buf_end) card->msg_buf_read = card->msg_buf; } diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c index 94f21486bb24..6ead5e1508b7 100644 --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -725,23 +725,27 @@ static int pcbit_stat(u_char __user *buf, int len, int driver, int channel) if (stat_st < stat_end) { - copy_to_user(buf, statbuf + stat_st, len); + if (copy_to_user(buf, statbuf + stat_st, len)) + return -EFAULT; stat_st += len; } else { if (len > STATBUF_LEN - stat_st) { - copy_to_user(buf, statbuf + stat_st, - STATBUF_LEN - stat_st); - copy_to_user(buf, statbuf, - len - (STATBUF_LEN - stat_st)); + if (copy_to_user(buf, statbuf + stat_st, + STATBUF_LEN - stat_st)) + return -EFAULT; + if (copy_to_user(buf, statbuf, + len - (STATBUF_LEN - stat_st))) + return -EFAULT; stat_st = len - (STATBUF_LEN - stat_st); } else { - copy_to_user(buf, statbuf + stat_st, len); + if (copy_to_user(buf, statbuf + stat_st, len)) + return -EFAULT; stat_st += len; -- cgit v1.2.3 From 2bffc23a01a489ad46ba7d61a1a657cecec87cc8 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:17:18 -0700 Subject: sky2: MSI test is only a warning Some motherboards don't implement MSI correctly. The driver handles this but the warning is too verbose and overly cautious. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c10e7f5faa5f..9e31efeea7c8 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3326,9 +3326,8 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) if (!hw->msi_detected) { /* MSI test failed, go back to INTx mode */ - printk(KERN_WARNING PFX "%s: No interrupt was generated using MSI, " - "switching to INTx mode. Please report this failure to " - "the PCI maintainer and include system chipset information.\n", + printk(KERN_INFO PFX "%s: No interrupt generated using MSI, " + "switching to INTx mode.\n", pci_name(pdev)); err = -EOPNOTSUPP; @@ -3336,6 +3335,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) } sky2_write32(hw, B0_IMSK, 0); + sky2_read32(hw, B0_IMSK); free_irq(pdev->irq, hw); -- cgit v1.2.3 From e561a83be5c9cada5fa3733efdff67a2098a0c8e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:20:51 -0700 Subject: sky2: turn of workaround timer The workaround timer is not needed in most systems with proper IRQ routing and by perodically waking up it adds to laptop power consumption. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 9e31efeea7c8..bd5ccae53879 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -96,9 +96,9 @@ static int disable_msi = 0; module_param(disable_msi, int, 0); MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); -static int idle_timeout = 100; +static int idle_timeout = 0; module_param(idle_timeout, int, 0); -MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms)"); +MODULE_PARM_DESC(idle_timeout, "Watchdog timer for lost interrupts (ms)"); static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, -- cgit v1.2.3 From ebc646f681a6ad5a81989a6906832e82155df283 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:23:56 -0700 Subject: sky2: phy irq on shutdown When PHY is turned off on shutdown, it causes the IRQ to get stuck on. Make sure and disable the IRQ first, and if IRQ occurs when device is not running, don't access PHY because that will hang. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bd5ccae53879..2747e2f74dcb 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1499,6 +1499,11 @@ static int sky2_down(struct net_device *dev) /* Stop more packets from being queued */ netif_stop_queue(dev); + /* Disable port IRQ */ + imask = sky2_read32(hw, B0_IMSK); + imask &= ~portirq_msk[port]; + sky2_write32(hw, B0_IMSK, imask); + sky2_gmac_reset(hw, port); /* Stop transmitter */ @@ -1549,11 +1554,6 @@ static int sky2_down(struct net_device *dev) sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); - /* Disable port IRQ */ - imask = sky2_read32(hw, B0_IMSK); - imask &= ~portirq_msk[port]; - sky2_write32(hw, B0_IMSK, imask); - sky2_phy_power(hw, port, 0); /* turn off LED's */ @@ -1750,13 +1750,13 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) struct sky2_port *sky2 = netdev_priv(dev); u16 istatus, phystat; + if (!netif_running(dev)) + return; + spin_lock(&sky2->phy_lock); istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - if (!netif_running(dev)) - goto out; - if (netif_msg_intr(sky2)) printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", sky2->netdev->name, istatus, phystat); -- cgit v1.2.3 From 709c6e7bb07411176ef9ef660242b1e59fc87a6f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:04 -0700 Subject: sky2: fiber pause bits The advertisement bits for flow control are located in different location on fiber (1000baseX) Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 2747e2f74dcb..88b12e856649 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -384,20 +384,31 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) adv |= PHY_M_AN_10_FD; if (sky2->advertising & ADVERTISED_10baseT_Half) adv |= PHY_M_AN_10_HD; + + /* desired flow control */ + if (sky2->tx_pause && sky2->rx_pause) /* both */ + adv |= PHY_M_AN_PC | PHY_M_AN_ASP; + else if (sky2->tx_pause) + adv |= PHY_M_AN_ASP; + else if (sky2->rx_pause) + adv |= PHY_M_AN_PC; + + } else { /* special defines for FIBER (88E1040S only) */ if (sky2->advertising & ADVERTISED_1000baseT_Full) adv |= PHY_M_AN_1000X_AFD; if (sky2->advertising & ADVERTISED_1000baseT_Half) adv |= PHY_M_AN_1000X_AHD; - } - /* Set Flow-control capabilities */ - if (sky2->tx_pause && sky2->rx_pause) - adv |= PHY_AN_PAUSE_CAP; /* symmetric */ - else if (sky2->rx_pause && !sky2->tx_pause) - adv |= PHY_AN_PAUSE_ASYM | PHY_AN_PAUSE_CAP; - else if (!sky2->rx_pause && sky2->tx_pause) - adv |= PHY_AN_PAUSE_ASYM; /* local */ + if (sky2->tx_pause && sky2->rx_pause) /* both */ + adv |= PHY_M_P_BOTH_MD_X; + else if (sky2->tx_pause) + adv |= PHY_M_P_ASYM_MD_X; + else if (sky2->rx_pause) + adv |= PHY_M_P_SYM_MD_X; + else + adv |= PHY_M_P_NO_PAUSE_X; + } /* Restart Auto-negotiation */ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; -- cgit v1.2.3 From 0edea0f54e1e28bdc1ce6b02d5ca3c4c878cf959 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:07 -0700 Subject: sky2: advertising register 16 bits The advertising bits (from ethtool.h) fit in 16 bits. --- drivers/net/sky2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 43d2accf60e1..0a8d8210679a 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1860,7 +1860,7 @@ struct sky2_port { dma_addr_t rx_le_map; dma_addr_t tx_le_map; - u32 advertising; /* ADVERTISED_ bits */ + u16 advertising; /* ADVERTISED_ bits */ u16 speed; /* SPEED_1000, SPEED_100, ... */ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ -- cgit v1.2.3 From 7c74ac1c236457e454804774e832046c1a7cc0bf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:08 -0700 Subject: sky2: use duplex result bits The result of duplex negotiation is avaliable in the phy status register, so use that to simplify code and avoid rereading the PHY. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 88b12e856649..6a594b001f58 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1714,26 +1714,7 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) } sky2->speed = sky2_phy_speed(hw, aux); - if (sky2->speed == SPEED_1000) { - u16 ctl2 = gm_phy_read(hw, port, PHY_MARV_1000T_CTRL); - u16 lpa2 = gm_phy_read(hw, port, PHY_MARV_1000T_STAT); - if (lpa2 & PHY_B_1000S_MSF) { - printk(KERN_ERR PFX "%s: master/slave fault", - sky2->netdev->name); - return -1; - } - - if ((ctl2 & PHY_M_1000C_AFD) && (lpa2 & PHY_B_1000S_LP_FD)) - sky2->duplex = DUPLEX_FULL; - else - sky2->duplex = DUPLEX_HALF; - } else { - u16 adv = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); - if ((aux & adv) & PHY_AN_FULL) - sky2->duplex = DUPLEX_FULL; - else - sky2->duplex = DUPLEX_HALF; - } + sky2->duplex = (aux & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; /* Pause bits are offset (9..8) */ if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) -- cgit v1.2.3 From 7800fddcd05a7dc89276389b96664af4f7890ea7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:10 -0700 Subject: sky2: don't reset PHY twice Don't need to reset PHY twice on startup. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6a594b001f58..20a8c34e6d53 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -356,16 +356,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); } - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - if (sky2->autoneg == AUTONEG_DISABLE) - ctrl &= ~PHY_CT_ANE; - else - ctrl |= PHY_CT_ANE; - - ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - ctrl = 0; + ctrl = PHY_CT_RESET; ct1000 = 0; adv = PHY_AN_CSMA; reg = 0; @@ -450,8 +441,6 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); else sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); - - ctrl |= PHY_CT_RESET; } gma_write16(hw, port, GM_GP_CTRL, reg); -- cgit v1.2.3 From 16ad91e1c686734aaa5664cd08af0b5e9bf3af61 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:13 -0700 Subject: sky2: flow control setting fixes The result of flow control negotiation should not limit the next negotiatition. If board is plugged into an old half duplex 10Mbit port, without pause, then replugged into a gigabit port, it should negotiate what is desired, not inherit that last negotiation. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 115 +++++++++++++++++++++++++++++++++-------------------- drivers/net/sky2.h | 11 ++++- 2 files changed, 81 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 20a8c34e6d53..b8f202169a75 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -284,6 +284,31 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) gma_write16(hw, port, GM_RX_CTRL, reg); } +/* flow control to advertise bits */ +static const u16 copper_fc_adv[] = { + [FC_NONE] = 0, + [FC_TX] = PHY_M_AN_ASP, + [FC_RX] = PHY_M_AN_PC, + [FC_BOTH] = PHY_M_AN_PC | PHY_M_AN_ASP, +}; + +/* flow control to advertise bits when using 1000BaseX */ +static const u16 fiber_fc_adv[] = { + [FC_BOTH] = PHY_M_P_BOTH_MD_X, + [FC_TX] = PHY_M_P_ASYM_MD_X, + [FC_RX] = PHY_M_P_SYM_MD_X, + [FC_NONE] = PHY_M_P_NO_PAUSE_X, +}; + +/* flow control to GMA disable bits */ +static const u16 gm_fc_disable[] = { + [FC_NONE] = GM_GPCR_FC_RX_DIS | GM_GPCR_FC_TX_DIS, + [FC_TX] = GM_GPCR_FC_RX_DIS, + [FC_RX] = GM_GPCR_FC_TX_DIS, + [FC_BOTH] = 0, +}; + + static void sky2_phy_init(struct sky2_hw *hw, unsigned port) { struct sky2_port *sky2 = netdev_priv(hw->dev[port]); @@ -376,29 +401,14 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) if (sky2->advertising & ADVERTISED_10baseT_Half) adv |= PHY_M_AN_10_HD; - /* desired flow control */ - if (sky2->tx_pause && sky2->rx_pause) /* both */ - adv |= PHY_M_AN_PC | PHY_M_AN_ASP; - else if (sky2->tx_pause) - adv |= PHY_M_AN_ASP; - else if (sky2->rx_pause) - adv |= PHY_M_AN_PC; - - + adv |= copper_fc_adv[sky2->flow_mode]; } else { /* special defines for FIBER (88E1040S only) */ if (sky2->advertising & ADVERTISED_1000baseT_Full) adv |= PHY_M_AN_1000X_AFD; if (sky2->advertising & ADVERTISED_1000baseT_Half) adv |= PHY_M_AN_1000X_AHD; - if (sky2->tx_pause && sky2->rx_pause) /* both */ - adv |= PHY_M_P_BOTH_MD_X; - else if (sky2->tx_pause) - adv |= PHY_M_P_ASYM_MD_X; - else if (sky2->rx_pause) - adv |= PHY_M_P_SYM_MD_X; - else - adv |= PHY_M_P_NO_PAUSE_X; + adv |= fiber_fc_adv[sky2->flow_mode]; } /* Restart Auto-negotiation */ @@ -424,20 +434,14 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) if (sky2->duplex == DUPLEX_FULL) { reg |= GM_GPCR_DUP_FULL; ctrl |= PHY_CT_DUP_MD; - } else if (sky2->speed != SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) { - /* Turn off flow control for 10/100mbps */ - sky2->rx_pause = 0; - sky2->tx_pause = 0; - } + } else if (sky2->speed < SPEED_1000) + sky2->flow_mode = FC_NONE; - if (!sky2->rx_pause) - reg |= GM_GPCR_FC_RX_DIS; - if (!sky2->tx_pause) - reg |= GM_GPCR_FC_TX_DIS; + reg |= gm_fc_disable[sky2->flow_mode]; /* Forward pause packets to GMAC? */ - if (sky2->tx_pause || sky2->rx_pause) + if (sky2->flow_mode & FC_RX) sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); else sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); @@ -1605,6 +1609,12 @@ static void sky2_link_up(struct sky2_port *sky2) struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; u16 reg; + static const char *fc_name[] = { + [FC_NONE] = "none", + [FC_TX] = "tx", + [FC_RX] = "rx", + [FC_BOTH] = "both", + }; /* enable Rx/Tx */ reg = gma_read16(hw, port, GM_GP_CTRL); @@ -1648,8 +1658,7 @@ static void sky2_link_up(struct sky2_port *sky2) "%s: Link is up at %d Mbps, %s duplex, flow control %s\n", sky2->netdev->name, sky2->speed, sky2->duplex == DUPLEX_FULL ? "full" : "half", - (sky2->tx_pause && sky2->rx_pause) ? "both" : - sky2->tx_pause ? "tx" : sky2->rx_pause ? "rx" : "none"); + fc_name[sky2->flow_status]); } static void sky2_link_down(struct sky2_port *sky2) @@ -1664,7 +1673,7 @@ static void sky2_link_down(struct sky2_port *sky2) reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); gma_write16(hw, port, GM_GP_CTRL, reg); - if (sky2->rx_pause && !sky2->tx_pause) { + if (sky2->flow_status == FC_RX) { /* restore Asymmetric Pause bit */ gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, gm_phy_read(hw, port, PHY_MARV_AUNE_ADV) @@ -1683,6 +1692,14 @@ static void sky2_link_down(struct sky2_port *sky2) sky2_phy_init(hw, port); } +static enum flow_control sky2_flow(int rx, int tx) +{ + if (rx) + return tx ? FC_BOTH : FC_RX; + else + return tx ? FC_TX : FC_NONE; +} + static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) { struct sky2_hw *hw = sky2->hw; @@ -1709,14 +1726,14 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) if (hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U) aux >>= 6; - sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; - sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0; + sky2->flow_status = sky2_flow(aux & PHY_M_PS_RX_P_EN, + aux & PHY_M_PS_TX_P_EN); - if (sky2->duplex == DUPLEX_HALF && sky2->speed != SPEED_1000 + if (sky2->duplex == DUPLEX_HALF && sky2->speed < SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) - sky2->rx_pause = sky2->tx_pause = 0; + sky2->flow_status = FC_NONE; - if (sky2->rx_pause || sky2->tx_pause) + if (aux & PHY_M_PS_RX_P_EN) sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); else sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); @@ -2729,7 +2746,7 @@ static int sky2_nway_reset(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); - if (sky2->autoneg != AUTONEG_ENABLE) + if (!netif_running(dev) || sky2->autoneg != AUTONEG_ENABLE) return -EINVAL; sky2_phy_reinit(sky2); @@ -2971,8 +2988,20 @@ static void sky2_get_pauseparam(struct net_device *dev, { struct sky2_port *sky2 = netdev_priv(dev); - ecmd->tx_pause = sky2->tx_pause; - ecmd->rx_pause = sky2->rx_pause; + switch (sky2->flow_mode) { + case FC_NONE: + ecmd->tx_pause = ecmd->rx_pause = 0; + break; + case FC_TX: + ecmd->tx_pause = 1, ecmd->rx_pause = 0; + break; + case FC_RX: + ecmd->tx_pause = 0, ecmd->rx_pause = 1; + break; + case FC_BOTH: + ecmd->tx_pause = ecmd->rx_pause = 1; + } + ecmd->autoneg = sky2->autoneg; } @@ -2982,10 +3011,10 @@ static int sky2_set_pauseparam(struct net_device *dev, struct sky2_port *sky2 = netdev_priv(dev); sky2->autoneg = ecmd->autoneg; - sky2->tx_pause = ecmd->tx_pause != 0; - sky2->rx_pause = ecmd->rx_pause != 0; + sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause); - sky2_phy_reinit(sky2); + if (netif_running(dev)) + sky2_phy_reinit(sky2); return 0; } @@ -3215,8 +3244,8 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, /* Auto speed and flow control */ sky2->autoneg = AUTONEG_ENABLE; - sky2->tx_pause = 1; - sky2->rx_pause = 1; + sky2->flow_mode = FC_BOTH; + sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 0a8d8210679a..3f05492da703 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1828,6 +1828,13 @@ struct rx_ring_info { dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; }; +enum flow_control { + FC_NONE = 0, + FC_TX = 1, + FC_RX = 2, + FC_BOTH = 3, +}; + struct sky2_port { struct sky2_hw *hw; struct net_device *netdev; @@ -1864,9 +1871,9 @@ struct sky2_port { u16 speed; /* SPEED_1000, SPEED_100, ... */ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ - u8 rx_pause; - u8 tx_pause; u8 rx_csum; + enum flow_control flow_mode; + enum flow_control flow_status; struct net_device_stats net_stats; -- cgit v1.2.3 From b6d7773462df13c105c19ab89706687ded839844 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:16 -0700 Subject: sky2: no message on rx fifo overflow Under high load it is possible to make the receiver FIFO get overloaded. The driver/hardware recover properly, so there is no reason to fill the log with lots of extra messages, just update counter. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b8f202169a75..6eddd0f36bc0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2014,6 +2014,10 @@ oversize: error: ++sky2->net_stats.rx_errors; + if (status & GMR_FS_RX_FF_OV) { + sky2->net_stats.rx_fifo_errors++; + goto resubmit; + } if (netif_msg_rx_err(sky2) && net_ratelimit()) printk(KERN_INFO PFX "%s: rx error, status 0x%x length %d\n", @@ -2025,8 +2029,6 @@ error: sky2->net_stats.rx_frame_errors++; if (status & GMR_FS_CRC_ERR) sky2->net_stats.rx_crc_errors++; - if (status & GMR_FS_RX_FF_OV) - sky2->net_stats.rx_fifo_errors++; goto resubmit; } -- cgit v1.2.3 From 52c89cac6781dea0ee2426821cd3effae1a925d3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:18 -0700 Subject: sky2: version 1.9 Mark version, this has been a lot of patches. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 6eddd0f36bc0..c19338351780 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -50,7 +50,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.9" +#define DRV_VERSION "1.10" #define PFX DRV_NAME " " /* -- cgit v1.2.3 From a052b52f4b6b77503af2647dc0c7415939d8232a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:23 -0700 Subject: sky2: accept multicast pause frames When using flow control, the PHY needs to accept multicast pause frames. Without this fix, these frames were getting discarded by the PHY before doing any flow control. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index c19338351780..67ecd66f26d6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2850,6 +2850,14 @@ static int sky2_set_mac_address(struct net_device *dev, void *p) return 0; } +static void inline sky2_add_filter(u8 filter[8], const u8 *addr) +{ + u32 bit; + + bit = ether_crc(ETH_ALEN, addr) & 63; + filter[bit >> 3] |= 1 << (bit & 7); +} + static void sky2_set_multicast(struct net_device *dev) { struct sky2_port *sky2 = netdev_priv(dev); @@ -2858,7 +2866,10 @@ static void sky2_set_multicast(struct net_device *dev) struct dev_mc_list *list = dev->mc_list; u16 reg; u8 filter[8]; + int rx_pause; + static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; + rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH); memset(filter, 0, sizeof(filter)); reg = gma_read16(hw, port, GM_RX_CTRL); @@ -2866,18 +2877,19 @@ static void sky2_set_multicast(struct net_device *dev) if (dev->flags & IFF_PROMISC) /* promiscuous */ reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */ + else if (dev->flags & IFF_ALLMULTI) memset(filter, 0xff, sizeof(filter)); - else if (dev->mc_count == 0) /* no multicast */ + else if (dev->mc_count == 0 && !rx_pause) reg &= ~GM_RXCR_MCF_ENA; else { int i; reg |= GM_RXCR_MCF_ENA; - for (i = 0; list && i < dev->mc_count; i++, list = list->next) { - u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; - filter[bit / 8] |= 1 << (bit % 8); - } + if (rx_pause) + sky2_add_filter(filter, pause_mc_addr); + + for (i = 0; list && i < dev->mc_count; i++, list = list->next) + sky2_add_filter(filter, list->dmi_addr); } gma_write16(hw, port, GM_MC_ADDR_H1, -- cgit v1.2.3 From 4e4bc305e16440ab38060d61fbcb7d774881d2f1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 17 Oct 2006 10:24:25 -0700 Subject: sky2: GMAC pause frame This reverts earlier change that attempted to fix flow control. Device needs to discard pause frames, otherwise it hangs after a while. Signed-off-by: Stephen Hemminger --- drivers/net/sky2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 3f05492da703..6d2a23f66c9a 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1576,7 +1576,7 @@ enum { GMR_FS_ANY_ERR = GMR_FS_RX_FF_OV | GMR_FS_CRC_ERR | GMR_FS_FRAGMENT | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | + GMR_FS_MII_ERR | GMR_FS_GOOD_FC | GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, }; -- cgit v1.2.3 From 41072a1be57f63bf83afc31c44d72de018d800fa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 17 Oct 2006 13:47:40 -0400 Subject: [PATCH] zd1211rw: fix build-break caused by association race fix The break was caused by 7c28ad2d83ecc637237fe684659a6afbce0bb2a8. Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 2d12837052b0..a7d29bddb298 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -1099,7 +1099,7 @@ static void link_led_handler(void *p) int r; spin_lock_irq(&mac->lock); - is_associated = sm->associated != 0; + is_associated = sm->associnfo.associated != 0; spin_unlock_irq(&mac->lock); r = zd_chip_control_leds(chip, -- cgit v1.2.3 From 64f89798da35f43c6ef6afda0541e25034513458 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Oct 2006 13:57:18 -0700 Subject: USB: revert EHCI VIA workaround patch This reverts 26f953fd884ea4879585287917f855c63c6b2666 which caused resume problems on the mac mini. Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-dbg.c | 4 ++- drivers/usb/host/ehci-hcd.c | 70 ++++++++++++++------------------------------- drivers/usb/host/ehci-hub.c | 2 +- drivers/usb/host/ehci-pci.c | 2 +- drivers/usb/host/ehci-q.c | 6 ++-- drivers/usb/host/ehci.h | 22 +++++--------- 6 files changed, 37 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 23b95b2bfe15..34b7a31cd85b 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -754,7 +754,9 @@ show_registers (struct class_device *class_dev, char *buf) } if (ehci->reclaim) { - temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim); + temp = scnprintf (next, size, "reclaim qh %p%s\n", + ehci->reclaim, + ehci->reclaim_ready ? " ready" : ""); size -= temp; next += temp; } diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index aac6ec5dd7cf..9030994aba98 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -111,7 +111,7 @@ static const char hcd_name [] = "ehci_hcd"; #define EHCI_TUNE_MULT_TT 1 #define EHCI_TUNE_FLS 2 /* (small) 256 frame schedule */ -#define EHCI_IAA_MSECS 10 /* arbitrary */ +#define EHCI_IAA_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ @@ -254,7 +254,6 @@ static void ehci_quiesce (struct ehci_hcd *ehci) /*-------------------------------------------------------------------------*/ -static void end_unlink_async (struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); #include "ehci-hub.c" @@ -264,37 +263,25 @@ static void ehci_work(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -static void ehci_iaa_watchdog (unsigned long param) +static void ehci_watchdog (unsigned long param) { struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; - u32 status; spin_lock_irqsave (&ehci->lock, flags); - WARN_ON(!ehci->reclaim); - /* lost IAA irqs wedge things badly; seen first with a vt8235 */ + /* lost IAA irqs wedge things badly; seen with a vt8235 */ if (ehci->reclaim) { - status = readl (&ehci->regs->status); + u32 status = readl (&ehci->regs->status); if (status & STS_IAA) { ehci_vdbg (ehci, "lost IAA\n"); COUNT (ehci->stats.lost_iaa); writel (STS_IAA, &ehci->regs->status); - end_unlink_async (ehci); + ehci->reclaim_ready = 1; } } - spin_unlock_irqrestore (&ehci->lock, flags); -} - -static void ehci_watchdog (unsigned long param) -{ - struct ehci_hcd *ehci = (struct ehci_hcd *) param; - unsigned long flags; - - spin_lock_irqsave (&ehci->lock, flags); - - /* stop async processing after it's idled a bit */ + /* stop async processing after it's idled a bit */ if (test_bit (TIMER_ASYNC_OFF, &ehci->actions)) start_unlink_async (ehci, ehci->async); @@ -345,6 +332,8 @@ static void ehci_port_power (struct ehci_hcd *ehci, int is_on) static void ehci_work (struct ehci_hcd *ehci) { timer_action_done (ehci, TIMER_IO_WATCHDOG); + if (ehci->reclaim_ready) + end_unlink_async (ehci); /* another CPU may drop ehci->lock during a schedule scan while * it reports urb completions. this flag guards against bogus @@ -379,7 +368,6 @@ static void ehci_stop (struct usb_hcd *hcd) /* no more interrupts ... */ del_timer_sync (&ehci->watchdog); - del_timer_sync (&ehci->iaa_watchdog); spin_lock_irq(&ehci->lock); if (HC_IS_RUNNING (hcd->state)) @@ -426,10 +414,6 @@ static int ehci_init(struct usb_hcd *hcd) ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci; - init_timer(&ehci->iaa_watchdog); - ehci->iaa_watchdog.function = ehci_iaa_watchdog; - ehci->iaa_watchdog.data = (unsigned long) ehci; - /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows. @@ -446,6 +430,7 @@ static int ehci_init(struct usb_hcd *hcd) ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); ehci->reclaim = NULL; + ehci->reclaim_ready = 0; ehci->next_uframe = -1; /* @@ -619,7 +604,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* complete the unlinking of some qh [4.15.2.3] */ if (status & STS_IAA) { COUNT (ehci->stats.reclaim); - end_unlink_async (ehci); + ehci->reclaim_ready = 1; bh = 1; } @@ -723,14 +708,10 @@ static int ehci_urb_enqueue ( static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) { - // BUG_ON(qh->qh_state != QH_STATE_LINKED); - - /* failfast */ - if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) - end_unlink_async (ehci); - - /* defer till later if busy */ - else if (ehci->reclaim) { + /* if we need to use IAA and it's busy, defer */ + if (qh->qh_state == QH_STATE_LINKED + && ehci->reclaim + && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) { struct ehci_qh *last; for (last = ehci->reclaim; @@ -740,8 +721,12 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) qh->qh_state = QH_STATE_UNLINK_WAIT; last->reclaim = qh; - /* start IAA cycle */ - } else + /* bypass IAA if the hc can't care */ + } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim) + end_unlink_async (ehci); + + /* something else might have unlinked the qh by now */ + if (qh->qh_state == QH_STATE_LINKED) start_unlink_async (ehci, qh); } @@ -763,19 +748,7 @@ static int ehci_urb_dequeue (struct usb_hcd *hcd, struct urb *urb) qh = (struct ehci_qh *) urb->hcpriv; if (!qh) break; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - unlink_async (ehci, qh); - break; - case QH_STATE_UNLINK: - case QH_STATE_UNLINK_WAIT: - /* already started */ - break; - case QH_STATE_IDLE: - WARN_ON(1); - break; - } + unlink_async (ehci, qh); break; case PIPE_INTERRUPT: @@ -867,7 +840,6 @@ rescan: unlink_async (ehci, qh); /* FALL THROUGH */ case QH_STATE_UNLINK: /* wait for hw to finish? */ - case QH_STATE_UNLINK_WAIT: idle_timeout: spin_unlock_irqrestore (&ehci->lock, flags); schedule_timeout_uninterruptible(1); diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 2012213c0a25..1b20722c102b 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } ehci->command = readl (&ehci->regs->command); if (ehci->reclaim) - end_unlink_async (ehci); + ehci->reclaim_ready = 1; ehci_work(ehci); /* suspend any active/unsuspended ports, maybe allow wakeup */ diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 35e3fab6fc4e..e51c1ed81ac4 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -303,7 +303,7 @@ restart: /* emptying the schedule aborts any urbs */ spin_lock_irq(&ehci->lock); if (ehci->reclaim) - end_unlink_async (ehci); + ehci->reclaim_ready = 1; ehci_work(ehci); spin_unlock_irq(&ehci->lock); diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 46327272f614..62e46dc60e86 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -967,7 +967,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) struct ehci_qh *qh = ehci->reclaim; struct ehci_qh *next; - iaa_watchdog_done (ehci); + timer_action_done (ehci, TIMER_IAA_WATCHDOG); // qh->hw_next = cpu_to_le32 (qh->qh_dma); qh->qh_state = QH_STATE_IDLE; @@ -977,6 +977,7 @@ static void end_unlink_async (struct ehci_hcd *ehci) /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */ next = qh->reclaim; ehci->reclaim = next; + ehci->reclaim_ready = 0; qh->reclaim = NULL; qh_completions (ehci, qh); @@ -1051,10 +1052,11 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) return; } + ehci->reclaim_ready = 0; cmd |= CMD_IAAD; writel (cmd, &ehci->regs->command); (void) readl (&ehci->regs->command); - iaa_watchdog_start (ehci); + timer_action (ehci, TIMER_IAA_WATCHDOG); } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 6aac39f50e07..bbc3082a73d7 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -58,6 +58,7 @@ struct ehci_hcd { /* one per controller */ /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; + unsigned reclaim_ready : 1; unsigned scanning : 1; /* periodic schedule support */ @@ -80,7 +81,6 @@ struct ehci_hcd { /* one per controller */ struct dma_pool *itd_pool; /* itd per iso urb */ struct dma_pool *sitd_pool; /* sitd per split iso urb */ - struct timer_list iaa_watchdog; struct timer_list watchdog; unsigned long actions; unsigned stamp; @@ -114,21 +114,9 @@ static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) } -static inline void -iaa_watchdog_start (struct ehci_hcd *ehci) -{ - WARN_ON(timer_pending(&ehci->iaa_watchdog)); - mod_timer (&ehci->iaa_watchdog, - jiffies + msecs_to_jiffies(EHCI_IAA_MSECS)); -} - -static inline void iaa_watchdog_done (struct ehci_hcd *ehci) -{ - del_timer (&ehci->iaa_watchdog); -} - enum ehci_timer_action { TIMER_IO_WATCHDOG, + TIMER_IAA_WATCHDOG, TIMER_ASYNC_SHRINK, TIMER_ASYNC_OFF, }; @@ -146,6 +134,9 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) unsigned long t; switch (action) { + case TIMER_IAA_WATCHDOG: + t = EHCI_IAA_JIFFIES; + break; case TIMER_IO_WATCHDOG: t = EHCI_IO_JIFFIES; break; @@ -162,7 +153,8 @@ timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) // async queue SHRINK often precedes IAA. while it's ready // to go OFF neither can matter, and afterwards the IO // watchdog stops unless there's still periodic traffic. - if (time_before_eq(t, ehci->watchdog.expires) + if (action != TIMER_IAA_WATCHDOG + && t > ehci->watchdog.expires && timer_pending (&ehci->watchdog)) return; mod_timer (&ehci->watchdog, t); -- cgit v1.2.3 From 8d32e3ae5972641ee9eb813e7a5c44a2b85d3694 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Tue, 26 Sep 2006 13:34:47 -0700 Subject: USB: Wacom driver updates This fixes some issues with the current wacom driver due to the split of the driver into different pieces and adds support for the Intuos3 4x6 Signed-off-by: Ping Cheng Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/Makefile | 2 +- drivers/usb/input/wacom.h | 2 + drivers/usb/input/wacom_sys.c | 15 ++++-- drivers/usb/input/wacom_wac.c | 121 +++++++++++++++++++++++------------------- drivers/usb/input/wacom_wac.h | 2 +- 5 files changed, 80 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 295f459d1079..71437db7e9b1 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -3,7 +3,7 @@ # # Multipart objects. -wacom-objs := wacom_sys.o wacom_wac.o +wacom-objs := wacom_wac.o wacom_sys.o usbhid-objs := hid-core.o # Optional parts of multipart objects. diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h index 7b3840e378a8..1cf08f02c50e 100644 --- a/drivers/usb/input/wacom.h +++ b/drivers/usb/input/wacom.h @@ -63,6 +63,7 @@ * v1.46 (pc) - Split wacom.c into wacom_sys.c and wacom_wac.c, * - where wacom_sys.c deals with system specific code, * - and wacom_wac.c deals with Wacom specific code + * - Support Intuos3 4x6 */ /* @@ -118,6 +119,7 @@ extern void wacom_input_sync(void *wcombo); extern void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac); +extern void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac); extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index d233c37bd533..3c27f9b0aaa0 100644 --- a/drivers/usb/input/wacom_sys.c +++ b/drivers/usb/input/wacom_sys.c @@ -110,7 +110,7 @@ __u16 wacom_be16_to_cpu(unsigned char *data) __u16 wacom_le16_to_cpu(unsigned char *data) { __u16 value; - value = be16_to_cpu(*(__be16 *) data); + value = le16_to_cpu(*(__le16 *) data); return value; } @@ -143,7 +143,7 @@ void input_dev_g4(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->evbit[0] |= BIT(EV_MSC); input_dev->mscbit[0] |= BIT(MSC_SERIAL); input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); - input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_4); } void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -155,11 +155,16 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); } -void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) +void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); - input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3); input_set_abs_params(input_dev, ABS_RX, 0, 4097, 0, 0); +} + +void input_dev_i3(struct input_dev *input_dev, struct wacom_wac *wacom_wac) +{ + input_dev->keybit[LONG(BTN_LEFT)] |= BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7); input_set_abs_params(input_dev, ABS_RY, 0, 4097, 0, 0); } @@ -244,7 +249,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_fill_int_urb(wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wacom_wac->data, wacom_wac->features->pktlen, - wacom_wac->features->irq, wacom, endpoint->bInterval); + wacom_sys_irq, wacom, endpoint->bInterval); wacom->irq->transfer_dma = wacom->data_dma; wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; diff --git a/drivers/usb/input/wacom_wac.c b/drivers/usb/input/wacom_wac.c index aa31d22d4f05..92726fe89379 100644 --- a/drivers/usb/input/wacom_wac.c +++ b/drivers/usb/input/wacom_wac.c @@ -191,9 +191,9 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); if (wacom->features->type == WACOM_G4) - wacom_report_abs(wcombo, ABS_DISTANCE, data[6]); + wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); else - wacom_report_abs(wcombo, ABS_DISTANCE, data[7]); + wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); break; } } @@ -303,8 +303,9 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) wacom->tool[idx] = BTN_TOOL_PEN; } /* only large I3 support Lens Cursor */ - if(!((wacom->tool[idx] == BTN_TOOL_LENS) && - (wacom->features->type == INTUOS3))) { + if(!((wacom->tool[idx] == BTN_TOOL_LENS) + && ((wacom->features->type == INTUOS3) + || (wacom->features->type == INTUOS3S)))) { wacom_report_abs(wcombo, ABS_MISC, wacom->id[idx]); /* report tool id */ wacom_report_key(wcombo, wacom->tool[idx], 1); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); @@ -315,10 +316,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) /* Exit report */ if ((data[1] & 0xfe) == 0x80) { - wacom_report_key(wcombo, wacom->tool[idx], 0); - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); - return 2; + if(!((wacom->tool[idx] == BTN_TOOL_LENS) + && ((wacom->features->type == INTUOS3) + || (wacom->features->type == INTUOS3S)))) { + wacom_report_key(wcombo, wacom->tool[idx], 0); + wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ + wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, wacom->serial[idx]); + return 2; + } } return 0; } @@ -382,7 +387,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]); wacom_report_abs(wcombo, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]); - if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | data[2]) + if((data[5] & 0x0f) | (data[6] & 0x0f) | (data[1] & 0x1f) | + data[2] | (data[3] & 0x1f) | data[4]) wacom_report_key(wcombo, wacom->tool[1], 1); else wacom_report_key(wcombo, wacom->tool[1], 0); @@ -432,7 +438,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) ((t - 1) / 2) : -t / 2); } - } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3) { + } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { /* 4D mouse packet */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); @@ -452,12 +458,12 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) - ((data[8] & 0x02) >> 1)); /* I3 2D mouse side buttons */ - if (wacom->features->type == INTUOS3) { + if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); } - } else if (wacom->features->type < INTUOS3) { + } else if (wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L) { /* Lens cursor packets */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); @@ -490,6 +496,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) return (wacom_ptu_irq(wacom_wac, wcombo)); break; case INTUOS: + case INTUOS3S: case INTUOS3: case INTUOS3L: case CINTIQ: @@ -515,6 +522,8 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w case CINTIQ: input_dev_i3(input_dev, wacom_wac); /* fall through */ + case INTUOS3S: + input_dev_i3s(input_dev, wacom_wac); case INTUOS: input_dev_i(input_dev, wacom_wac); break; @@ -530,49 +539,50 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w } static struct wacom_features wacom_features[] = { - { "Wacom Penpartner", 7, 5040, 3780, 255, 32, PENPARTNER, wacom_sys_irq }, - { "Wacom Graphire", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_sys_irq }, - { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_sys_irq }, - { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom PenPartner2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_sys_irq }, - { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_sys_irq}, - { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_sys_irq}, - { "Wacom PL400", 8, 5408, 4056, 255, 32, PL, wacom_sys_irq }, - { "Wacom PL500", 8, 6144, 4608, 255, 32, PL, wacom_sys_irq }, - { "Wacom PL600", 8, 6126, 4604, 255, 32, PL, wacom_sys_irq }, - { "Wacom PL600SX", 8, 6260, 5016, 255, 32, PL, wacom_sys_irq }, - { "Wacom PL550", 8, 6144, 4608, 511, 32, PL, wacom_sys_irq }, - { "Wacom PL800", 8, 7220, 5780, 511, 32, PL, wacom_sys_irq }, - { "Wacom PL700", 8, 6758, 5406, 511, 32, PL, wacom_sys_irq }, - { "Wacom PL510", 8, 6282, 4762, 511, 32, PL, wacom_sys_irq }, - { "Wacom DTU710", 8, 34080, 27660, 511, 32, PL, wacom_sys_irq }, - { "Wacom DTF521", 8, 6282, 4762, 511, 32, PL, wacom_sys_irq }, - { "Wacom DTF720", 8, 6858, 5506, 511, 32, PL, wacom_sys_irq }, - { "Wacom Cintiq Partner",8, 20480, 15360, 511, 32, PTU, wacom_sys_irq }, - { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, INTUOS, wacom_sys_irq }, - { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 15, INTUOS3, wacom_sys_irq }, - { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, INTUOS3, wacom_sys_irq }, - { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, INTUOS3, wacom_sys_irq }, - { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 15, INTUOS3L, wacom_sys_irq }, - { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 15, INTUOS3L, wacom_sys_irq }, - { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 15, INTUOS3, wacom_sys_irq }, - { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 15, CINTIQ, wacom_sys_irq }, - { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, INTUOS, wacom_sys_irq }, + { "Wacom Penpartner", 7, 5040, 3780, 255, 0, PENPARTNER }, + { "Wacom Graphire", 8, 10206, 7422, 511, 63, GRAPHIRE }, + { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 63, GRAPHIRE }, + { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 63, GRAPHIRE }, + { "Wacom Graphire3", 8, 10208, 7424, 511, 63, GRAPHIRE }, + { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, + { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, + { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, + { "Wacom Volito", 8, 5104, 3712, 511, 0, GRAPHIRE }, + { "Wacom PenStation2", 8, 3250, 2320, 255, 0, GRAPHIRE }, + { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 0, GRAPHIRE }, + { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 0, GRAPHIRE }, + { "Wacom PenPartner2", 8, 3250, 2320, 255, 0, GRAPHIRE }, + { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, + { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, + { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, + { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, + { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, + { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, + { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, + { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, + { "Wacom PL600SX", 8, 6260, 5016, 255, 0, PL }, + { "Wacom PL550", 8, 6144, 4608, 511, 0, PL }, + { "Wacom PL800", 8, 7220, 5780, 511, 0, PL }, + { "Wacom PL700", 8, 6758, 5406, 511, 0, PL }, + { "Wacom PL510", 8, 6282, 4762, 511, 0, PL }, + { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, + { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, + { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, + { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, + { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 63, INTUOS }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, + { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 63, INTUOS }, + { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 63, INTUOS }, + { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 63, INTUOS }, + { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, + { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, + { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, + { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, + { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, + { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, + { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 15, INTUOS3S }, + { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, + { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 63, INTUOS }, { } }; @@ -618,6 +628,7 @@ static struct usb_device_id wacom_ids[] = { { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, + { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, { } diff --git a/drivers/usb/input/wacom_wac.h b/drivers/usb/input/wacom_wac.h index ceae7bf59d9f..a1d9ce007970 100644 --- a/drivers/usb/input/wacom_wac.h +++ b/drivers/usb/input/wacom_wac.h @@ -20,6 +20,7 @@ enum { PTU, PL, INTUOS, + INTUOS3S, INTUOS3, INTUOS3L, CINTIQ, @@ -34,7 +35,6 @@ struct wacom_features { int pressure_max; int distance_max; int type; - usb_complete_t irq; }; struct wacom_wac { -- cgit v1.2.3 From 2920349d438ec08d2b1f6761c8b78b8d13fd1dee Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn <[mailto:snakebyte@gmx.de]> Date: Tue, 17 Oct 2006 14:46:30 -0700 Subject: USB: BUG_ON conversion for wacom.c this patch converts two if () BUG(); construct to BUG_ON(); which occupies less space, uses unlikely and is safer when BUG() is disabled. Signed-off-by: Eric Sesterhenn Acked-by: "Ping Cheng" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/wacom_sys.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 3c27f9b0aaa0..31379b89c339 100644 --- a/drivers/usb/input/wacom_sys.c +++ b/drivers/usb/input/wacom_sys.c @@ -223,8 +223,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); wacom_wac->features = get_wacom_feature(id); - if (wacom_wac->features->pktlen > 10) - BUG(); + BUG_ON(wacom_wac->features->pktlen > 10); input_dev->name = wacom_wac->features->name; wacom->wacom_wac = wacom_wac; -- cgit v1.2.3 From 2daa48729dfafd349c2a52520734de2edb9dc805 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Wed, 4 Oct 2006 09:56:44 -0700 Subject: USB: fix use after free in wacom_sys.c the following commit added a use after free http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=3D3bea733ab21247290bd552dd6a2cd3049af9adef Found by coverity (cid #1441) Signed-off-by: Eric Sesterhenn Signed-off-by: "Ping Cheng" Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/wacom_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 31379b89c339..3498b893b53b 100644 --- a/drivers/usb/input/wacom_sys.c +++ b/drivers/usb/input/wacom_sys.c @@ -282,8 +282,8 @@ static void wacom_disconnect(struct usb_interface *intf) input_unregister_device(wacom->dev); usb_free_urb(wacom->irq); usb_buffer_free(interface_to_usbdev(intf), 10, wacom->wacom_wac->data, wacom->data_dma); - kfree(wacom); kfree(wacom->wacom_wac); + kfree(wacom); } } -- cgit v1.2.3 From 931b0411ac296591643662b7a790d15d6e23d57e Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Tue, 3 Oct 2006 10:31:36 -0300 Subject: airprime: New device ID. Adds support for the verizon wireless Broadband Access, National Access V640 ExpressCard34 Qualcomm 3G CDMA. Reported by Maciej A. __enczykowski Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 2c19f19b255c..392a5129af64 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -24,6 +24,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ + { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From 91a9c9214e34c364bf15406aadb922787ae7129b Mon Sep 17 00:00:00 2001 From: Chris Malley Date: Tue, 3 Oct 2006 10:08:28 +0100 Subject: USB: Support for BT On-Air USB modem in cdc-acm.c The patch below is a necessary workaround to support the BT On-Air USB modem, which fails to initialise properly during normal probing thus: Sep 30 17:34:57 sled kernel: drivers/usb/class/cdc-acm.c: Zero length descriptor references Sep 30 17:34:57 sled kernel: cdc_acm: probe of 1-1.2:1.0 failed with error -22 Adding the patch below causes the probing section to be skipped, and the modem then initialises correctly. Signed-off-by: Chris Malley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index ec4d1d756725..daecdf0bff04 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1083,6 +1083,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0482, 0x0203), /* KYOCERA AH-K3001V */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x079b, 0x000f), /* BT On-Air USB MODEM */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, { USB_DEVICE(0x0ace, 0x1608), /* ZyDAS 56K USB MODEM */ .driver_info = SINGLE_RX_URB, /* firmware bug */ }, -- cgit v1.2.3 From fbe2bafcb00b25265c2c869ba4615d6a5324b7f1 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 28 Sep 2006 23:36:04 +0200 Subject: USB: remove private debug macros from kaweth this kills the private debug macros from the kaweth driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/kaweth.c | 122 ++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 66 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 957d4ad316f9..9ef9075a1680 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -65,16 +65,6 @@ #undef DEBUG -#ifdef DEBUG -#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg) -#else -#define kaweth_dbg(format, arg...) do {} while (0) -#endif -#define kaweth_err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" ,##arg) -#define kaweth_info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ##arg) -#define kaweth_warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ##arg) - - #include "kawethfw.h" #define KAWETH_MTU 1514 @@ -265,17 +255,17 @@ static int kaweth_control(struct kaweth_device *kaweth, { struct usb_ctrlrequest *dr; - kaweth_dbg("kaweth_control()"); + dbg("kaweth_control()"); if(in_interrupt()) { - kaweth_dbg("in_interrupt()"); + dbg("in_interrupt()"); return -EBUSY; } dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC); if (!dr) { - kaweth_dbg("kmalloc() failed"); + dbg("kmalloc() failed"); return -ENOMEM; } @@ -300,7 +290,7 @@ static int kaweth_read_configuration(struct kaweth_device *kaweth) { int retval; - kaweth_dbg("Reading kaweth configuration"); + dbg("Reading kaweth configuration"); retval = kaweth_control(kaweth, usb_rcvctrlpipe(kaweth->dev, 0), @@ -322,7 +312,7 @@ static int kaweth_set_urb_size(struct kaweth_device *kaweth, __u16 urb_size) { int retval; - kaweth_dbg("Setting URB size to %d", (unsigned)urb_size); + dbg("Setting URB size to %d", (unsigned)urb_size); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -344,7 +334,7 @@ static int kaweth_set_sofs_wait(struct kaweth_device *kaweth, __u16 sofs_wait) { int retval; - kaweth_dbg("Set SOFS wait to %d", (unsigned)sofs_wait); + dbg("Set SOFS wait to %d", (unsigned)sofs_wait); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -367,7 +357,7 @@ static int kaweth_set_receive_filter(struct kaweth_device *kaweth, { int retval; - kaweth_dbg("Set receive filter to %d", (unsigned)receive_filter); + dbg("Set receive filter to %d", (unsigned)receive_filter); retval = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -392,7 +382,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, __u8 type) { if(data_len > KAWETH_FIRMWARE_BUF_SIZE) { - kaweth_err("Firmware too big: %d", data_len); + err("Firmware too big: %d", data_len); return -ENOSPC; } @@ -403,13 +393,13 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth, kaweth->firmware_buf[4] = type; kaweth->firmware_buf[5] = interrupt; - kaweth_dbg("High: %i, Low:%i", kaweth->firmware_buf[3], + dbg("High: %i, Low:%i", kaweth->firmware_buf[3], kaweth->firmware_buf[2]); - kaweth_dbg("Downloading firmware at %p to kaweth device at %p", + dbg("Downloading firmware at %p to kaweth device at %p", data, kaweth); - kaweth_dbg("Firmware length: %d", data_len); + dbg("Firmware length: %d", data_len); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -437,7 +427,7 @@ static int kaweth_trigger_firmware(struct kaweth_device *kaweth, kaweth->firmware_buf[6] = 0x00; kaweth->firmware_buf[7] = 0x00; - kaweth_dbg("Triggering firmware"); + dbg("Triggering firmware"); return kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), @@ -457,7 +447,7 @@ static int kaweth_reset(struct kaweth_device *kaweth) { int result; - kaweth_dbg("kaweth_reset(%p)", kaweth); + dbg("kaweth_reset(%p)", kaweth); result = kaweth_control(kaweth, usb_sndctrlpipe(kaweth->dev, 0), USB_REQ_SET_CONFIGURATION, @@ -470,7 +460,7 @@ static int kaweth_reset(struct kaweth_device *kaweth) mdelay(10); - kaweth_dbg("kaweth_reset() returns %d.",result); + dbg("kaweth_reset() returns %d.",result); return result; } @@ -568,7 +558,7 @@ static int kaweth_resubmit_rx_urb(struct kaweth_device *kaweth, kaweth->suspend_lowmem_rx = 1; schedule_delayed_work(&kaweth->lowmem_work, HZ/4); } - kaweth_err("resubmitting rx_urb %d failed", result); + err("resubmitting rx_urb %d failed", result); } else { kaweth->suspend_lowmem_rx = 0; } @@ -605,7 +595,7 @@ static void kaweth_usb_receive(struct urb *urb) return; if(urb->status && urb->status != -EREMOTEIO && count != 1) { - kaweth_err("%s RX status: %d count: %d packet_len: %d", + err("%s RX status: %d count: %d packet_len: %d", net->name, urb->status, count, @@ -616,9 +606,9 @@ static void kaweth_usb_receive(struct urb *urb) if(kaweth->net && (count > 2)) { if(pkt_len > (count - 2)) { - kaweth_err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count); - kaweth_err("Packet len & 2047: %x", pkt_len & 2047); - kaweth_err("Count 2: %x", count2); + err("Packet length too long for USB frame (pkt_len: %x, count: %x)",pkt_len, count); + err("Packet len & 2047: %x", pkt_len & 2047); + err("Count 2: %x", count2); kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC); return; } @@ -655,7 +645,7 @@ static int kaweth_open(struct net_device *net) struct kaweth_device *kaweth = netdev_priv(net); int res; - kaweth_dbg("Opening network device."); + dbg("Opening network device."); res = kaweth_resubmit_rx_urb(kaweth, GFP_KERNEL); if (res) @@ -732,7 +722,7 @@ static void kaweth_usb_transmit_complete(struct urb *urb) if (unlikely(urb->status != 0)) if (urb->status != -ENOENT) - kaweth_dbg("%s: TX status %d.", kaweth->net->name, urb->status); + dbg("%s: TX status %d.", kaweth->net->name, urb->status); netif_wake_queue(kaweth->net); dev_kfree_skb_irq(skb); @@ -783,7 +773,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC))) { - kaweth_warn("kaweth failed tx_urb %d", res); + warn("kaweth failed tx_urb %d", res); kaweth->stats.tx_errors++; netif_start_queue(net); @@ -812,7 +802,7 @@ static void kaweth_set_rx_mode(struct net_device *net) KAWETH_PACKET_FILTER_BROADCAST | KAWETH_PACKET_FILTER_MULTICAST; - kaweth_dbg("Setting Rx mode to %d", packet_filter_bitmap); + dbg("Setting Rx mode to %d", packet_filter_bitmap); netif_stop_queue(net); @@ -850,10 +840,10 @@ static void kaweth_async_set_rx_mode(struct kaweth_device *kaweth) KAWETH_CONTROL_TIMEOUT); if(result < 0) { - kaweth_err("Failed to set Rx mode: %d", result); + err("Failed to set Rx mode: %d", result); } else { - kaweth_dbg("Set Rx mode to %d", packet_filter_bitmap); + dbg("Set Rx mode to %d", packet_filter_bitmap); } } } @@ -874,7 +864,7 @@ static void kaweth_tx_timeout(struct net_device *net) { struct kaweth_device *kaweth = netdev_priv(net); - kaweth_warn("%s: Tx timed out. Resetting.", net->name); + warn("%s: Tx timed out. Resetting.", net->name); kaweth->stats.tx_errors++; net->trans_start = jiffies; @@ -895,15 +885,15 @@ static int kaweth_probe( const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; int result = 0; - kaweth_dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", + dbg("Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x", dev->devnum, le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct), le16_to_cpu(dev->descriptor.bcdDevice)); - kaweth_dbg("Device at %p", dev); + dbg("Device at %p", dev); - kaweth_dbg("Descriptor length: %x type: %x", + dbg("Descriptor length: %x type: %x", (int)dev->descriptor.bLength, (int)dev->descriptor.bDescriptorType); @@ -918,7 +908,7 @@ static int kaweth_probe( spin_lock_init(&kaweth->device_lock); init_waitqueue_head(&kaweth->term_wait); - kaweth_dbg("Resetting."); + dbg("Resetting."); kaweth_reset(kaweth); @@ -928,17 +918,17 @@ static int kaweth_probe( */ if (le16_to_cpu(dev->descriptor.bcdDevice) >> 8) { - kaweth_info("Firmware present in device."); + info("Firmware present in device."); } else { /* Download the firmware */ - kaweth_info("Downloading firmware..."); + info("Downloading firmware..."); kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL); if ((result = kaweth_download_firmware(kaweth, kaweth_new_code, len_kaweth_new_code, 100, 2)) < 0) { - kaweth_err("Error downloading firmware (%d)", result); + err("Error downloading firmware (%d)", result); goto err_fw; } @@ -947,7 +937,7 @@ static int kaweth_probe( len_kaweth_new_code_fix, 100, 3)) < 0) { - kaweth_err("Error downloading firmware fix (%d)", result); + err("Error downloading firmware fix (%d)", result); goto err_fw; } @@ -956,7 +946,7 @@ static int kaweth_probe( len_kaweth_trigger_code, 126, 2)) < 0) { - kaweth_err("Error downloading trigger code (%d)", result); + err("Error downloading trigger code (%d)", result); goto err_fw; } @@ -966,18 +956,18 @@ static int kaweth_probe( len_kaweth_trigger_code_fix, 126, 3)) < 0) { - kaweth_err("Error downloading trigger code fix (%d)", result); + err("Error downloading trigger code fix (%d)", result); goto err_fw; } if ((result = kaweth_trigger_firmware(kaweth, 126)) < 0) { - kaweth_err("Error triggering firmware (%d)", result); + err("Error triggering firmware (%d)", result); goto err_fw; } /* Device will now disappear for a moment... */ - kaweth_info("Firmware loaded. I'll be back..."); + info("Firmware loaded. I'll be back..."); err_fw: free_page((unsigned long)kaweth->firmware_buf); free_netdev(netdev); @@ -987,14 +977,14 @@ err_fw: result = kaweth_read_configuration(kaweth); if(result < 0) { - kaweth_err("Error reading configuration (%d), no net device created", result); + err("Error reading configuration (%d), no net device created", result); goto err_free_netdev; } - kaweth_info("Statistics collection: %x", kaweth->configuration.statistics_mask); - kaweth_info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); - kaweth_info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); - kaweth_info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", + info("Statistics collection: %x", kaweth->configuration.statistics_mask); + info("Multicast filter limit: %x", kaweth->configuration.max_multicast_filters & ((1 << 15) - 1)); + info("MTU: %d", le16_to_cpu(kaweth->configuration.segment_size)); + info("Read MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", (int)kaweth->configuration.hw_addr[0], (int)kaweth->configuration.hw_addr[1], (int)kaweth->configuration.hw_addr[2], @@ -1005,17 +995,17 @@ err_fw: if(!memcmp(&kaweth->configuration.hw_addr, &bcast_addr, sizeof(bcast_addr))) { - kaweth_err("Firmware not functioning properly, no net device created"); + err("Firmware not functioning properly, no net device created"); goto err_free_netdev; } if(kaweth_set_urb_size(kaweth, KAWETH_BUF_SIZE) < 0) { - kaweth_dbg("Error setting URB size"); + dbg("Error setting URB size"); goto err_free_netdev; } if(kaweth_set_sofs_wait(kaweth, KAWETH_SOFS_TO_WAIT) < 0) { - kaweth_err("Error setting SOFS wait"); + err("Error setting SOFS wait"); goto err_free_netdev; } @@ -1025,11 +1015,11 @@ err_fw: KAWETH_PACKET_FILTER_MULTICAST); if(result < 0) { - kaweth_err("Error setting receive filter"); + err("Error setting receive filter"); goto err_free_netdev; } - kaweth_dbg("Initializing net device."); + dbg("Initializing net device."); kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!kaweth->tx_urb) @@ -1086,13 +1076,13 @@ err_fw: SET_NETDEV_DEV(netdev, &intf->dev); if (register_netdev(netdev) != 0) { - kaweth_err("Error registering netdev."); + err("Error registering netdev."); goto err_intfdata; } - kaweth_info("kaweth interface created at %s", kaweth->net->name); + info("kaweth interface created at %s", kaweth->net->name); - kaweth_dbg("Kaweth probe returning."); + dbg("Kaweth probe returning."); return 0; @@ -1121,16 +1111,16 @@ static void kaweth_disconnect(struct usb_interface *intf) struct kaweth_device *kaweth = usb_get_intfdata(intf); struct net_device *netdev; - kaweth_info("Unregistering"); + info("Unregistering"); usb_set_intfdata(intf, NULL); if (!kaweth) { - kaweth_warn("unregistering non-existant device"); + warn("unregistering non-existant device"); return; } netdev = kaweth->net; - kaweth_dbg("Unregistering net device"); + dbg("Unregistering net device"); unregister_netdev(netdev); usb_free_urb(kaweth->rx_urb); @@ -1185,7 +1175,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length) if (!wait_event_timeout(awd.wqh, awd.done, timeout)) { // timeout - kaweth_warn("usb_control/bulk_msg: timeout"); + warn("usb_control/bulk_msg: timeout"); usb_kill_urb(urb); // remove urb safely status = -ETIMEDOUT; } @@ -1234,7 +1224,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, ****************************************************************/ static int __init kaweth_init(void) { - kaweth_dbg("Driver loading"); + dbg("Driver loading"); return usb_register(&kaweth_driver); } -- cgit v1.2.3 From 1a2ea1dfc4ee078841cd6406ebf6bf0c5a3d25e9 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 3 Oct 2006 10:30:52 +0200 Subject: USB: suspend/resume support for kaweth this adds support for suspend and resume to the kaweth driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/kaweth.c | 82 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c index 9ef9075a1680..7c906a43e497 100644 --- a/drivers/usb/net/kaweth.c +++ b/drivers/usb/net/kaweth.c @@ -76,6 +76,9 @@ #define KAWETH_STATUS_BROKEN 0x0000001 #define KAWETH_STATUS_CLOSING 0x0000002 +#define KAWETH_STATUS_SUSPENDING 0x0000004 + +#define KAWETH_STATUS_BLOCKED (KAWETH_STATUS_CLOSING | KAWETH_STATUS_SUSPENDING) #define KAWETH_PACKET_FILTER_PROMISCUOUS 0x01 #define KAWETH_PACKET_FILTER_ALL_MULTICAST 0x02 @@ -102,6 +105,8 @@ #define STATE_MASK 0x40 #define STATE_SHIFT 5 +#define IS_BLOCKED(s) (s & KAWETH_STATUS_BLOCKED) + MODULE_AUTHOR("Michael Zappe , Stephane Alnet , Brad Hards and Oliver Neukum "); MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver"); @@ -118,6 +123,8 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, struct usb_ctrlrequest *cmd, void *data, int len, int timeout); +static int kaweth_suspend(struct usb_interface *intf, pm_message_t message); +static int kaweth_resume(struct usb_interface *intf); /**************************************************************** * usb_device_id @@ -169,6 +176,8 @@ static struct usb_driver kaweth_driver = { .name = driver_name, .probe = kaweth_probe, .disconnect = kaweth_disconnect, + .suspend = kaweth_suspend, + .resume = kaweth_resume, .id_table = usb_klsi_table, }; @@ -212,6 +221,7 @@ struct kaweth_device int suspend_lowmem_rx; int suspend_lowmem_ctrl; int linkstate; + int opened; struct work_struct lowmem_work; struct usb_device *dev; @@ -524,7 +534,7 @@ static void kaweth_resubmit_tl(void *d) { struct kaweth_device *kaweth = (struct kaweth_device *)d; - if (kaweth->status | KAWETH_STATUS_CLOSING) + if (IS_BLOCKED(kaweth->status)) return; if (kaweth->suspend_lowmem_rx) @@ -591,8 +601,12 @@ static void kaweth_usb_receive(struct urb *urb) return; } - if (kaweth->status & KAWETH_STATUS_CLOSING) + spin_lock(&kaweth->device_lock); + if (IS_BLOCKED(kaweth->status)) { + spin_unlock(&kaweth->device_lock); return; + } + spin_unlock(&kaweth->device_lock); if(urb->status && urb->status != -EREMOTEIO && count != 1) { err("%s RX status: %d count: %d packet_len: %d", @@ -668,6 +682,7 @@ static int kaweth_open(struct net_device *net) usb_kill_urb(kaweth->rx_urb); return -EIO; } + kaweth->opened = 1; netif_start_queue(net); @@ -678,14 +693,8 @@ static int kaweth_open(struct net_device *net) /**************************************************************** * kaweth_close ****************************************************************/ -static int kaweth_close(struct net_device *net) +static void kaweth_kill_urbs(struct kaweth_device *kaweth) { - struct kaweth_device *kaweth = netdev_priv(net); - - netif_stop_queue(net); - - kaweth->status |= KAWETH_STATUS_CLOSING; - usb_kill_urb(kaweth->irq_urb); usb_kill_urb(kaweth->rx_urb); usb_kill_urb(kaweth->tx_urb); @@ -696,6 +705,21 @@ static int kaweth_close(struct net_device *net) we hit them again */ usb_kill_urb(kaweth->irq_urb); usb_kill_urb(kaweth->rx_urb); +} + +/**************************************************************** + * kaweth_close + ****************************************************************/ +static int kaweth_close(struct net_device *net) +{ + struct kaweth_device *kaweth = netdev_priv(net); + + netif_stop_queue(net); + kaweth->opened = 0; + + kaweth->status |= KAWETH_STATUS_CLOSING; + + kaweth_kill_urbs(kaweth); kaweth->status &= ~KAWETH_STATUS_CLOSING; @@ -742,6 +766,9 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) kaweth_async_set_rx_mode(kaweth); netif_stop_queue(net); + if (IS_BLOCKED(kaweth->status)) { + goto skip; + } /* We now decide whether we can put our special header into the sk_buff */ if (skb_cloned(skb) || skb_headroom(skb) < 2) { @@ -774,6 +801,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net) if((res = usb_submit_urb(kaweth->tx_urb, GFP_ATOMIC))) { warn("kaweth failed tx_urb %d", res); +skip: kaweth->stats.tx_errors++; netif_start_queue(net); @@ -871,6 +899,42 @@ static void kaweth_tx_timeout(struct net_device *net) usb_unlink_urb(kaweth->tx_urb); } +/**************************************************************** + * kaweth_suspend + ****************************************************************/ +static int kaweth_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct kaweth_device *kaweth = usb_get_intfdata(intf); + unsigned long flags; + + spin_lock_irqsave(&kaweth->device_lock, flags); + kaweth->status |= KAWETH_STATUS_SUSPENDING; + spin_unlock_irqrestore(&kaweth->device_lock, flags); + + kaweth_kill_urbs(kaweth); + return 0; +} + +/**************************************************************** + * kaweth_resume + ****************************************************************/ +static int kaweth_resume(struct usb_interface *intf) +{ + struct kaweth_device *kaweth = usb_get_intfdata(intf); + unsigned long flags; + + spin_lock_irqsave(&kaweth->device_lock, flags); + kaweth->status &= ~KAWETH_STATUS_SUSPENDING; + spin_unlock_irqrestore(&kaweth->device_lock, flags); + + if (!kaweth->opened) + return 0; + kaweth_resubmit_rx_urb(kaweth, GFP_NOIO); + kaweth_resubmit_int_urb(kaweth, GFP_NOIO); + + return 0; +} + /**************************************************************** * kaweth_probe ****************************************************************/ -- cgit v1.2.3 From 8442ae00d47dad690ac1105b426274433dc672f8 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 2 Oct 2006 07:20:10 -0700 Subject: USB: ohci-pnx4008 build fixes The OHCI bus glue for the Philips PNX chips is missing a few calls. - Bus suspend/resume were wrongly omitted in the original submission. - Two new calls were added since that glue was submitted: * Root hub irq enable call * Shutdown hook for usbcore Plus usb_bus.hcpriv has now been removed from usbcore. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-pnx4008.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index 82cb22f002e7..2dbb77414905 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -262,6 +262,7 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .start = ohci_pnx4008_start, .stop = ohci_stop, + .shutdown = ohci_shutdown, /* * managing i/o requests and associated device resources @@ -280,7 +281,11 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - + .hub_irq_enable = ohci_rhsc_enable, +#ifdef CONFIG_PM + .bus_suspend = ohci_bus_suspend, + .bus_resume = ohci_bus_resume, +#endif .start_port_reset = ohci_start_port_reset, }; @@ -410,8 +415,6 @@ static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev) goto out4; } - hcd->self.hcpriv = (void *)hcd; - pnx4008_start_hc(); platform_set_drvdata(pdev, hcd); ohci = hcd_to_ohci(hcd); -- cgit v1.2.3 From 9ca5346483ea2c2e8932268246d1d8746fe3bcaa Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Tue, 3 Oct 2006 21:46:33 +0200 Subject: UEAGLE : be suspend friendly this patch avoid that the kernel thread block the suspend process. Some work is still need to recover after a resume. Signed-off-by: Matthieu Castet Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index f5434b1cbb1e..68b5d0dd4f98 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1173,6 +1173,9 @@ static int uea_kthread(void *data) ret = uea_stat(sc); if (ret != -EAGAIN) msleep(1000); + if (try_to_freeze()) + uea_err(INS_TO_USBDEV(sc), "suspend/resume not supported, " + "please unplug/replug your modem\n"); } uea_leaves(INS_TO_USBDEV(sc)); return ret; -- cgit v1.2.3 From 531a39bbab213209a9914e68809bcf8b60a54f47 Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Tue, 3 Oct 2006 21:49:29 +0200 Subject: UEAGLE : use interruptible sleep this patch use wait_event_interruptible_timeout and msleep_interruptible beacause uninterruptible sleep (task state 'D') is counted as 1 towards load average, like running processes. Signed-off-by: Matthieu Castet Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 68b5d0dd4f98..88585da262dd 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -744,7 +744,7 @@ static inline void wake_up_cmv_ack(struct uea_softc *sc) static inline int wait_cmv_ack(struct uea_softc *sc) { - int ret = wait_event_timeout(sc->cmv_ack_wait, + int ret = wait_event_interruptible_timeout(sc->cmv_ack_wait, sc->cmv_ack, ACK_TIMEOUT); sc->cmv_ack = 0; @@ -1172,7 +1172,7 @@ static int uea_kthread(void *data) if (!ret) ret = uea_stat(sc); if (ret != -EAGAIN) - msleep(1000); + msleep_interruptible(1000); if (try_to_freeze()) uea_err(INS_TO_USBDEV(sc), "suspend/resume not supported, " "please unplug/replug your modem\n"); @@ -1600,7 +1600,7 @@ static int uea_heavy(struct usbatm_data *usbatm, struct usb_interface *intf) { struct uea_softc *sc = usbatm->driver_data; - wait_event(sc->sync_q, IS_OPERATIONAL(sc)); + wait_event_interruptible(sc->sync_q, IS_OPERATIONAL(sc)); return 0; -- cgit v1.2.3 From a7a0c9cd1f45c2cae38ebe0951246bf94399818a Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Tue, 3 Oct 2006 21:44:11 +0200 Subject: UEAGLE : comestic changes Hi, this patch does some cosmetic changes : - dump firwmare version as soon as possible and export it on sysfs - hint about wrong cmv/dsp - Display a message to warn user when the modem is ready : it can help people to detect problems on the line without debug trace - Fix wrong indent - display modem type (pots/isdn) - increase version number Signed-off-by: Matthieu Castet Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 88585da262dd..570529842231 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -68,7 +68,7 @@ #include "usbatm.h" -#define EAGLEUSBVERSION "ueagle 1.3" +#define EAGLEUSBVERSION "ueagle 1.4" /* @@ -80,14 +80,14 @@ dev_dbg(&(usb_dev)->dev, \ "[ueagle-atm dbg] %s: " format, \ __FUNCTION__, ##args); \ - } while (0) + } while (0) #define uea_vdbg(usb_dev, format, args...) \ do { \ if (debug >= 2) \ dev_dbg(&(usb_dev)->dev, \ "[ueagle-atm vdbg] " format, ##args); \ - } while (0) + } while (0) #define uea_enters(usb_dev) \ uea_vdbg(usb_dev, "entering %s\n", __FUNCTION__) @@ -218,8 +218,8 @@ enum { #define UEA_CHIP_VERSION(x) \ ((x)->driver_info & 0xf) -#define IS_ISDN(sc) \ - (le16_to_cpu(sc->usb_dev->descriptor.bcdDevice) & 0x80) +#define IS_ISDN(usb_dev) \ + (le16_to_cpu((usb_dev)->descriptor.bcdDevice) & 0x80) #define INS_TO_USBDEV(ins) ins->usb_dev @@ -625,12 +625,12 @@ static int request_dsp(struct uea_softc *sc) char *dsp_name; if (UEA_CHIP_VERSION(sc) == ADI930) { - if (IS_ISDN(sc)) + if (IS_ISDN(sc->usb_dev)) dsp_name = FW_DIR "DSP9i.bin"; else dsp_name = FW_DIR "DSP9p.bin"; } else { - if (IS_ISDN(sc)) + if (IS_ISDN(sc->usb_dev)) dsp_name = FW_DIR "DSPei.bin"; else dsp_name = FW_DIR "DSPep.bin"; @@ -885,7 +885,8 @@ static int uea_stat(struct uea_softc *sc) break; case 3: /* fail ... */ - uea_info(INS_TO_USBDEV(sc), "modem synchronization failed\n"); + uea_info(INS_TO_USBDEV(sc), "modem synchronization failed" + " (may be try other cmv/dsp)\n"); return -EAGAIN; case 4 ... 6: /* test state */ @@ -913,12 +914,6 @@ static int uea_stat(struct uea_softc *sc) release_firmware(sc->dsp_firm); sc->dsp_firm = NULL; } - - ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid); - if (ret < 0) - return ret; - uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", - sc->stats.phy.firmid); } /* always update it as atm layer could not be init when we switch to @@ -1033,9 +1028,9 @@ static int request_cmvs(struct uea_softc *sc, if (cmv_file[sc->modem_index] == NULL) { if (UEA_CHIP_VERSION(sc) == ADI930) - file = (IS_ISDN(sc)) ? "CMV9i.bin" : "CMV9p.bin"; + file = (IS_ISDN(sc->usb_dev)) ? "CMV9i.bin" : "CMV9p.bin"; else - file = (IS_ISDN(sc)) ? "CMVei.bin" : "CMVep.bin"; + file = (IS_ISDN(sc->usb_dev)) ? "CMVei.bin" : "CMVep.bin"; } else file = cmv_file[sc->modem_index]; @@ -1131,6 +1126,13 @@ static int uea_start_reset(struct uea_softc *sc) if (ret < 0) return ret; + /* Dump firmware version */ + ret = uea_read_cmv(sc, SA_INFO, 10, &sc->stats.phy.firmid); + if (ret < 0) + return ret; + uea_info(INS_TO_USBDEV(sc), "ATU-R firmware version : %x\n", + sc->stats.phy.firmid); + /* get options */ ret = len = request_cmvs(sc, &cmvs, &cmvs_fw); if (ret < 0) @@ -1147,6 +1149,8 @@ static int uea_start_reset(struct uea_softc *sc) /* Enter in R-ACT-REQ */ ret = uea_write_cmv(sc, SA_CNTL, 0, 2); uea_vdbg(INS_TO_USBDEV(sc), "Entering in R-ACT-REQ state\n"); + uea_info(INS_TO_USBDEV(sc), "Modem started, " + "waiting synchronization\n"); out: release_firmware(cmvs_fw); sc->reset = 0; @@ -1569,6 +1573,7 @@ UEA_ATTR(uscorr, 0); UEA_ATTR(dscorr, 0); UEA_ATTR(usunc, 0); UEA_ATTR(dsunc, 0); +UEA_ATTR(firmid, 0); /* Retrieve the device End System Identifier (MAC) */ @@ -1642,6 +1647,7 @@ static struct attribute *attrs[] = { &dev_attr_stat_dscorr.attr, &dev_attr_stat_usunc.attr, &dev_attr_stat_dsunc.attr, + &dev_attr_stat_firmid.attr, }; static struct attribute_group attr_grp = { .attrs = attrs, @@ -1756,10 +1762,10 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id) struct usb_device *usb = interface_to_usbdev(intf); uea_enters(usb); - uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s\n", + uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) : %s %s\n", le16_to_cpu(usb->descriptor.idVendor), le16_to_cpu(usb->descriptor.idProduct), - chip_name[UEA_CHIP_VERSION(id)]); + chip_name[UEA_CHIP_VERSION(id)], IS_ISDN(usb)?"isdn":"pots"); usb_reset_device(usb); -- cgit v1.2.3 From 762f007b05446f5c63268fb2c28646f28959ee4b Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Fri, 6 Oct 2006 07:23:11 +0200 Subject: USB: fix cdc-acm problems with hard irq? (inconsistent lock state) Signed-off-by: Jarek Poplawski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index daecdf0bff04..9a9012fd284b 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -325,7 +325,7 @@ static void acm_rx_tasklet(unsigned long _acm) struct acm_rb *buf; struct tty_struct *tty = acm->tty; struct acm_ru *rcv; - //unsigned long flags; + unsigned long flags; int i = 0; dbg("Entering acm_rx_tasklet"); @@ -333,15 +333,15 @@ static void acm_rx_tasklet(unsigned long _acm) return; next_buffer: - spin_lock(&acm->read_lock); + spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->filled_read_bufs)) { - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); goto urbs; } buf = list_entry(acm->filled_read_bufs.next, struct acm_rb, list); list_del(&buf->list); - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); @@ -356,29 +356,29 @@ next_buffer: memmove(buf->base, buf->base + i, buf->size - i); buf->size -= i; spin_unlock(&acm->throttle_lock); - spin_lock(&acm->read_lock); + spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->filled_read_bufs); - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); return; } spin_unlock(&acm->throttle_lock); - spin_lock(&acm->read_lock); + spin_lock_irqsave(&acm->read_lock, flags); list_add(&buf->list, &acm->spare_read_bufs); - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); goto next_buffer; urbs: while (!list_empty(&acm->spare_read_bufs)) { - spin_lock(&acm->read_lock); + spin_lock_irqsave(&acm->read_lock, flags); if (list_empty(&acm->spare_read_urbs)) { - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); return; } rcv = list_entry(acm->spare_read_urbs.next, struct acm_ru, list); list_del(&rcv->list); - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); buf = list_entry(acm->spare_read_bufs.next, struct acm_rb, list); @@ -400,9 +400,9 @@ urbs: free-urbs-pool and resubmited ASAP */ if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { list_add(&buf->list, &acm->spare_read_bufs); - spin_lock(&acm->read_lock); + spin_lock_irqsave(&acm->read_lock, flags); list_add(&rcv->list, &acm->spare_read_urbs); - spin_unlock(&acm->read_lock); + spin_unlock_irqrestore(&acm->read_lock, flags); return; } } -- cgit v1.2.3 From e4a20daa7b44ab9805979eb716f6bb7532bc67b9 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 4 Oct 2006 16:31:15 -0400 Subject: USB: unusual_devs entry for Nokia 6131 This patch (as796) adds an unusual_devs entry for the Nokia 6131, which doesn't like large transfer sizes. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index c9a8d50106d1..0a846e4a101e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -182,6 +182,13 @@ UNUSUAL_DEV( 0x0421, 0x044e, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE | US_FL_FIX_CAPACITY ), +/* Reported by Bardur Arantsson */ +UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0370, + "Nokia", + "6131", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From ccf40d62c70128990cf2e8775853cc3287cd7ce3 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 5 Oct 2006 09:56:44 +0200 Subject: usbatm: fix tiny race If usbatm_do_heavy_init finishes before usbatm_heavy_init writes the pid, the disconnect method could shoot down the wrong process if the pid has been recycled. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 309073f6433a..ab091fa4c86b 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -1001,6 +1001,7 @@ static int usbatm_do_heavy_init(void *arg) daemonize(instance->driver->driver_name); allow_signal(SIGTERM); + instance->thread_pid = get_current()->pid; complete(&instance->thread_started); @@ -1025,10 +1026,6 @@ static int usbatm_heavy_init(struct usbatm_data *instance) return ret; } - mutex_lock(&instance->serialize); - instance->thread_pid = ret; - mutex_unlock(&instance->serialize); - wait_for_completion(&instance->thread_started); return 0; -- cgit v1.2.3 From 6a4f1b41357d2bd65d39f7a5d44e92f69daaf04b Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 5 Oct 2006 10:40:55 +0200 Subject: speedtch: "extended reach" The speedtouch modem setup code was reverse engineered many years ago from a prehistoric windows driver. Less ancient windows drivers, even those from a few years ago, perform extra initialization steps which this patch adds to the linux driver. David Woodhouse observed that this initialization along with the firmware bin/sachu3/zzzlp2.eni from the driver at http://www.speedtouch.co.uk/downloads/330/301/UK3012%20Extended.zip improves line sync speeds by about 20%. He provided the original patch, which I've modified to use symbolic names (BMaxDSL, ModemMode, ModemOption) rather than magic numbers. These names may not seem like much of an improvement (after all, what is "ModemOption" exactly?), but they do have one big advantage: they are the names used in the windows registry. I've made them available as module parameters. Thanks are due to Aurelio Arroyo, who noticed the relationship between these magic numbers and the entries in Phonebook.ini. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/speedtch.c | 93 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 77 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 7c7b507af29d..c870c804470f 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -55,7 +55,6 @@ static const char speedtch_driver_name[] = "speedtch"; #define OFFSET_d 9 /* size 4 */ #define OFFSET_e 13 /* size 1 */ #define OFFSET_f 14 /* size 1 */ -#define TOTAL 15 #define SIZE_7 1 #define SIZE_b 8 @@ -79,6 +78,18 @@ static int dl_512_first = DEFAULT_DL_512_FIRST; static int enable_isoc = DEFAULT_ENABLE_ISOC; static int sw_buffering = DEFAULT_SW_BUFFERING; +#define DEFAULT_B_MAX_DSL 8128 +#define DEFAULT_MODEM_MODE 11 +#define MODEM_OPTION_LENGTH 16 +static const unsigned char DEFAULT_MODEM_OPTION[MODEM_OPTION_LENGTH] = { + 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static unsigned int BMaxDSL = DEFAULT_B_MAX_DSL; +static unsigned char ModemMode = DEFAULT_MODEM_MODE; +static unsigned char ModemOption[MODEM_OPTION_LENGTH]; +static int num_ModemOption; + module_param(altsetting, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(altsetting, "Alternative setting for data interface (bulk_default: " @@ -100,6 +111,17 @@ MODULE_PARM_DESC(sw_buffering, "Enable software buffering (default: " __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); +module_param(BMaxDSL, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(BMaxDSL, + "default: " __MODULE_STRING(DEFAULT_B_MAX_DSL)); + +module_param(ModemMode, byte, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(ModemMode, + "default: " __MODULE_STRING(DEFAULT_MODEM_MODE)); + +module_param_array(ModemOption, byte, &num_ModemOption, S_IRUGO); +MODULE_PARM_DESC(ModemOption, "default: 0x10,0x00,0x00,0x00,0x20"); + #define INTERFACE_DATA 1 #define ENDPOINT_INT 0x81 #define ENDPOINT_BULK_DATA 0x07 @@ -108,10 +130,17 @@ MODULE_PARM_DESC(sw_buffering, #define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) +struct speedtch_params { + unsigned int altsetting; + unsigned int BMaxDSL; + unsigned char ModemMode; + unsigned char ModemOption[MODEM_OPTION_LENGTH]; +}; + struct speedtch_instance_data { struct usbatm_data *usbatm; - unsigned int altsetting; + struct speedtch_params params; /* set in probe, constant afterwards */ struct work_struct status_checker; @@ -123,7 +152,7 @@ struct speedtch_instance_data { struct urb *int_urb; unsigned char int_data[16]; - unsigned char scratch_buffer[TOTAL]; + unsigned char scratch_buffer[16]; }; /*************** @@ -186,6 +215,34 @@ static void speedtch_test_sequence(struct speedtch_instance_data *instance) 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT); if (ret < 0) usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret); + + /* Extra initialisation in recent drivers - gives higher speeds */ + + /* URBext1 */ + buf[0] = instance->params.ModemMode; + ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), + 0x01, 0x40, 0x11, 0x00, buf, 1, CTRL_TIMEOUT); + if (ret < 0) + usb_warn(usbatm, "%s failed on URBext1: %d\n", __func__, ret); + + /* URBext2 */ + /* This seems to be the one which actually triggers the higher sync + rate -- it does require the new firmware too, although it works OK + with older firmware */ + ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), + 0x01, 0x40, 0x14, 0x00, + instance->params.ModemOption, + MODEM_OPTION_LENGTH, CTRL_TIMEOUT); + if (ret < 0) + usb_warn(usbatm, "%s failed on URBext2: %d\n", __func__, ret); + + /* URBext3 */ + buf[0] = instance->params.BMaxDSL & 0xff; + buf[1] = instance->params.BMaxDSL >> 8; + ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0), + 0x01, 0x40, 0x12, 0x00, buf, 2, CTRL_TIMEOUT); + if (ret < 0) + usb_warn(usbatm, "%s failed on URBext3: %d\n", __func__, ret); } static int speedtch_upload_firmware(struct speedtch_instance_data *instance, @@ -285,8 +342,8 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance, because we're in our own kernel thread anyway. */ msleep_interruptible(1000); - if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { - usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret); + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) { + usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->params.altsetting, ret); goto out_free; } @@ -372,7 +429,7 @@ static int speedtch_read_status(struct speedtch_instance_data *instance) unsigned char *buf = instance->scratch_buffer; int ret; - memset(buf, 0, TOTAL); + memset(buf, 0, 16); ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, @@ -746,17 +803,21 @@ static int speedtch_bind(struct usbatm_data *usbatm, instance->usbatm = usbatm; - /* altsetting and enable_isoc may change at any moment, so take a snapshot */ - instance->altsetting = altsetting; + /* module parameters may change at any moment, so take a snapshot */ + instance->params.altsetting = altsetting; + instance->params.BMaxDSL = BMaxDSL; + instance->params.ModemMode = ModemMode; + memcpy(instance->params.ModemOption, DEFAULT_MODEM_OPTION, MODEM_OPTION_LENGTH); + memcpy(instance->params.ModemOption, ModemOption, num_ModemOption); use_isoc = enable_isoc; - if (instance->altsetting) - if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { - usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret); - instance->altsetting = 0; /* fall back to default */ + if (instance->params.altsetting) + if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) { + usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->params.altsetting, ret); + instance->params.altsetting = 0; /* fall back to default */ } - if (!instance->altsetting && use_isoc) + if (!instance->params.altsetting && use_isoc) if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) { usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret); use_isoc = 0; /* fall back to bulk */ @@ -783,14 +844,14 @@ static int speedtch_bind(struct usbatm_data *usbatm, usb_info(usbatm, "isochronous transfer not supported - using bulk\n"); } - if (!use_isoc && !instance->altsetting) + if (!use_isoc && !instance->params.altsetting) if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) { usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret); goto fail_free; } - if (!instance->altsetting) - instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING; + if (!instance->params.altsetting) + instance->params.altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING; usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); -- cgit v1.2.3 From 44960af1b6ab3e8fd23dc134fcf7862caf42936b Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Thu, 5 Oct 2006 11:05:50 +0200 Subject: cxacru: add the ZTE ZXDSL 852 From http://doc.ubuntu-fr.org/materiel/zxdsl852. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 3892a9e9aee3..e6565633ba0f 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -793,6 +793,9 @@ static const struct usb_device_id cxacru_usb_ids[] = { { /* V = Conexant P = ADSL modem */ USB_DEVICE(0x0572, 0xcb06), .driver_info = (unsigned long) &cxacru_cb00 }, + { /* V = Conexant P = ADSL modem (ZTE ZXDSL 852) */ + USB_DEVICE(0x0572, 0xcb07), .driver_info = (unsigned long) &cxacru_cb00 + }, { /* V = Olitec P = ADSL modem version 2 */ USB_DEVICE(0x08e3, 0x0100), .driver_info = (unsigned long) &cxacru_cafe }, -- cgit v1.2.3 From 516077c1ee8a4a47cc41634a29954b636f3975ea Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 5 Oct 2006 09:04:11 +0200 Subject: USB: fix suspend support for usblp this implements suspend support for usblp. According to the CUPS people ENODEV will make CUPS retry the job. Thus it is returned in the runtime case. My printer survives suspend/resume cycles with it. Signed-off-by: Oliver Neukum Signed-off-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 79 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a161d70e1e42..809d465eb257 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -154,6 +154,7 @@ struct usblp { unsigned char used; /* True if open */ unsigned char present; /* True if not disconnected */ unsigned char bidir; /* interface is bidirectional */ + unsigned char sleeping; /* interface is suspended */ unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ /* first 2 bytes are (big-endian) length */ }; @@ -183,6 +184,7 @@ static void usblp_dump(struct usblp *usblp) { dbg("quirks=%d", usblp->quirks); dbg("used=%d", usblp->used); dbg("bidir=%d", usblp->bidir); + dbg("sleeping=%d", usblp->sleeping); dbg("device_id_string=\"%s\"", usblp->device_id_string ? usblp->device_id_string + 2 : @@ -338,6 +340,20 @@ static int usblp_check_status(struct usblp *usblp, int err) return newerr; } +static int handle_bidir (struct usblp *usblp) +{ + if (usblp->bidir && usblp->used && !usblp->sleeping) { + usblp->readcount = 0; + usblp->readurb->dev = usblp->dev; + if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) { + usblp->used = 0; + return -EIO; + } + } + + return 0; +} + /* * File op functions. */ @@ -390,14 +406,9 @@ static int usblp_open(struct inode *inode, struct file *file) usblp->writeurb->status = 0; usblp->readurb->status = 0; - if (usblp->bidir) { - usblp->readcount = 0; - usblp->readurb->dev = usblp->dev; - if (usb_submit_urb(usblp->readurb, GFP_KERNEL) < 0) { - retval = -EIO; - usblp->used = 0; - file->private_data = NULL; - } + if (handle_bidir(usblp) < 0) { + file->private_data = NULL; + retval = -EIO; } out: mutex_unlock (&usblp_mutex); @@ -460,6 +471,11 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) goto done; } + if (usblp->sleeping) { + retval = -ENODEV; + goto done; + } + dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); @@ -658,6 +674,11 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t return -ENODEV; } + if (usblp->sleeping) { + up (&usblp->sem); + return writecount ? writecount : -ENODEV; + } + if (usblp->writeurb->status != 0) { if (usblp->quirks & USBLP_QUIRK_BIDIR) { if (!usblp->wcomplete) @@ -749,6 +770,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count, goto done; } + if (usblp->sleeping) { + count = -ENODEV; + goto done; + } + if (usblp->readurb->status) { err("usblp%d: error %d reading from printer", usblp->minor, usblp->readurb->status); @@ -1167,6 +1193,41 @@ static void usblp_disconnect(struct usb_interface *intf) mutex_unlock (&usblp_mutex); } +static int usblp_suspend (struct usb_interface *intf, pm_message_t message) +{ + struct usblp *usblp = usb_get_intfdata (intf); + + /* this races against normal access and open */ + mutex_lock (&usblp_mutex); + down (&usblp->sem); + /* we take no more IO */ + usblp->sleeping = 1; + /* we wait for anything printing */ + wait_event (usblp->wait, usblp->wcomplete || !usblp->present); + usblp_unlink_urbs(usblp); + up (&usblp->sem); + mutex_unlock (&usblp_mutex); + + return 0; +} + +static int usblp_resume (struct usb_interface *intf) +{ + struct usblp *usblp = usb_get_intfdata (intf); + int r; + + mutex_lock (&usblp_mutex); + down (&usblp->sem); + + usblp->sleeping = 0; + r = handle_bidir (usblp); + + up (&usblp->sem); + mutex_unlock (&usblp_mutex); + + return r; +} + static struct usb_device_id usblp_ids [] = { { USB_DEVICE_INFO(7, 1, 1) }, { USB_DEVICE_INFO(7, 1, 2) }, @@ -1183,6 +1244,8 @@ static struct usb_driver usblp_driver = { .name = "usblp", .probe = usblp_probe, .disconnect = usblp_disconnect, + .suspend = usblp_suspend, + .resume = usblp_resume, .id_table = usblp_ids, }; -- cgit v1.2.3 From 96a518928e1fd00a6d0eb344f420ea82aeec8ab9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 9 Oct 2006 12:24:49 -0700 Subject: USB: ftdi-elan: fix sparse warnings Deleted some unused code that could do bad things on non-x86 platforms. Also fixed some minor formatting errors. Thanks to Al Viro for pointing out the sparse errors. Cc: Tony Olech Cc: Al Viro Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 0eb26a26115b..37d1f4e90d5a 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1186,11 +1186,8 @@ static ssize_t ftdi_elan_write(struct file *file, int retval = 0; struct urb *urb; char *buf; - char data[30 *3 + 4]; - char *d = data; - const char __user *s = user_buffer; - int m = (sizeof(data) - 1) / 3; - struct usb_ftdi *ftdi = (struct usb_ftdi *)file->private_data; + struct usb_ftdi *ftdi = file->private_data; + if (ftdi->disconnected > 0) { return -ENODEV; } @@ -1220,27 +1217,18 @@ static ssize_t ftdi_elan_write(struct file *file, if (retval) { dev_err(&ftdi->udev->dev, "failed submitting write urb, error %" "d\n", retval); - goto error_4; + goto error_3; } usb_free_urb(urb); - exit:; - if (count > m) { - int I = m - 1; - while (I-- > 0) { - d += sprintf(d, " %02X", 0x000000FF & *s++); - } - d += sprintf(d, " .."); - } else { - int I = count; - while (I-- > 0) { - d += sprintf(d, " %02X", 0x000000FF & *s++); - } - } + +exit: return count; - error_4: error_3:usb_buffer_free(ftdi->udev, count, buf, - urb->transfer_dma); - error_2:usb_free_urb(urb); - error_1:return retval; +error_3: + usb_buffer_free(ftdi->udev, count, buf, urb->transfer_dma); +error_2: + usb_free_urb(urb); +error_1: + return retval; } static struct file_operations ftdi_elan_fops = { -- cgit v1.2.3 From b62df4516981745d4b5de01ceec1d65a9174a524 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Oct 2006 10:54:00 -0400 Subject: UHCI: workaround for Asus motherboard This patch (as798) adds a workaround to uhci-hcd. At least one Asus motherboard is wired in such a way that any device attached to a suspended UHCI controller will prevent the system from entering suspend-to-RAM by immediately waking it up. The only way around the problem is to turn the controller off instead of suspending it. This fixes Bugzilla #6193. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-hcd.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 45ee6920a850..226bf3de8edd 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -196,12 +197,42 @@ static int resume_detect_interrupts_are_broken(struct uhci_hcd *uhci) return 0; } +static int remote_wakeup_is_broken(struct uhci_hcd *uhci) +{ + static struct dmi_system_id broken_wakeup_table[] = { + { + .ident = "Asus A7V8X", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK"), + DMI_MATCH(DMI_BOARD_NAME, "A7V8X"), + DMI_MATCH(DMI_BOARD_VERSION, "REV 1.xx"), + } + }, + { } + }; + int port; + + /* One of Asus's motherboards has a bug which causes it to + * wake up immediately from suspend-to-RAM if any of the ports + * are connected. In such cases we will not set EGSM. + */ + if (dmi_check_system(broken_wakeup_table)) { + for (port = 0; port < uhci->rh_numports; ++port) { + if (inw(uhci->io_addr + USBPORTSC1 + port * 2) & + USBPORTSC_CCS) + return 1; + } + } + + return 0; +} + static void suspend_rh(struct uhci_hcd *uhci, enum uhci_rh_state new_state) __releases(uhci->lock) __acquires(uhci->lock) { int auto_stop; - int int_enable; + int int_enable, egsm_enable; auto_stop = (new_state == UHCI_RH_AUTO_STOPPED); dev_dbg(&uhci_to_hcd(uhci)->self.root_hub->dev, @@ -217,15 +248,18 @@ __acquires(uhci->lock) } /* Enable resume-detect interrupts if they work. - * Then enter Global Suspend mode, still configured. + * Then enter Global Suspend mode if _it_ works, still configured. */ + egsm_enable = USBCMD_EGSM; uhci->working_RD = 1; int_enable = USBINTR_RESUME; - if (resume_detect_interrupts_are_broken(uhci)) { + if (remote_wakeup_is_broken(uhci)) + egsm_enable = 0; + if (resume_detect_interrupts_are_broken(uhci) || !egsm_enable) uhci->working_RD = int_enable = 0; - } + outw(int_enable, uhci->io_addr + USBINTR); - outw(USBCMD_EGSM | USBCMD_CF, uhci->io_addr + USBCMD); + outw(egsm_enable | USBCMD_CF, uhci->io_addr + USBCMD); mb(); udelay(5); -- cgit v1.2.3 From c40fd5ea565587c05b0e2c49c02cad2c35fd85c6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Oct 2006 11:55:47 -0400 Subject: usbcore: fix refcount bug in endpoint removal This patch (as799) fixes a nasty refcount error in the USB endpoint class. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 3ebb90149e93..40ba76a17571 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -282,8 +282,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint) sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); device_unregister(&endpoint->ep_dev->dev); endpoint->ep_dev = NULL; + destroy_endpoint_class(); } - destroy_endpoint_class(); } - - -- cgit v1.2.3 From d5477c11111467e19787f00d3cab20fb48c2699e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Oct 2006 11:56:26 -0400 Subject: usbcore: fix endpoint device creation This patch (as800) straightens out the USB endpoint class device creation routine, fixing a refcount bug in the process. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 40ba76a17571..3b2d137912be 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -223,7 +223,7 @@ int usb_create_ep_files(struct device *parent, ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); if (!ep_dev) { retval = -ENOMEM; - goto exit; + goto error_alloc; } /* fun calculation to determine the minor of this endpoint */ @@ -241,33 +241,31 @@ int usb_create_ep_files(struct device *parent, retval = device_register(&ep_dev->dev); if (retval) - goto error; + goto error_register; retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); if (retval) goto error_group; - endpoint->ep_dev = ep_dev; - /* create the symlink to the old-style "ep_XX" directory */ sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); - retval = sysfs_create_link(&parent->kobj, - &endpoint->ep_dev->dev.kobj, name); + retval = sysfs_create_link(&parent->kobj, &ep_dev->dev.kobj, name); if (retval) goto error_link; -exit: + endpoint->ep_dev = ep_dev; return retval; error_link: sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); - error_group: device_unregister(&ep_dev->dev); - endpoint->ep_dev = NULL; destroy_endpoint_class(); return retval; -error: + +error_register: kfree(ep_dev); +error_alloc: destroy_endpoint_class(); +exit: return retval; } -- cgit v1.2.3 From f8ac232ad7388bfff680b26e84b3ac63889d1cea Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 8 Oct 2006 16:02:00 +0400 Subject: USB: drivers/usb/net/*: use BUILD_BUG_ON Signed-off-by: Alexey Dobriyan Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/cdc_ether.c | 2 +- drivers/usb/net/usbnet.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index 82ce0358d9a3..f6971b88349d 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c @@ -498,7 +498,7 @@ static struct usb_driver cdc_driver = { static int __init cdc_init(void) { - BUG_ON((sizeof(((struct usbnet *)0)->data) + BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct cdc_state))); return usb_register(&cdc_driver); diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 24bd3486ee63..af6d061dc79b 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -1225,7 +1225,7 @@ EXPORT_SYMBOL_GPL(usbnet_resume); static int __init usbnet_init(void) { /* compiler should optimize this out */ - BUG_ON (sizeof (((struct sk_buff *)0)->cb) + BUILD_BUG_ON (sizeof (((struct sk_buff *)0)->cb) < sizeof (struct skb_data)); random_ether_addr(node_id); -- cgit v1.2.3 From 27d39e2627dc7493f554bc0549d8c63953762478 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 9 Oct 2006 18:09:33 +0900 Subject: usb devio: handle class_device_create() error This patch adds missing class_device_create() error check, and makes notifier return NOTIFY_BAD. Signed-off-by: Akinobu Mita Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 724822cac2b1..fed92be63b5e 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1588,15 +1588,18 @@ const struct file_operations usbfs_device_file_operations = { .release = usbdev_release, }; -static void usbdev_add(struct usb_device *dev) +static int usbdev_add(struct usb_device *dev) { int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); dev->class_dev = class_device_create(usb_device_class, NULL, MKDEV(USB_DEVICE_MAJOR, minor), &dev->dev, "usbdev%d.%d", dev->bus->busnum, dev->devnum); + if (IS_ERR(dev->class_dev)) + return PTR_ERR(dev->class_dev); dev->class_dev->class_data = dev; + return 0; } static void usbdev_remove(struct usb_device *dev) @@ -1609,7 +1612,8 @@ static int usbdev_notify(struct notifier_block *self, unsigned long action, { switch (action) { case USB_DEVICE_ADD: - usbdev_add(dev); + if (usbdev_add(dev)) + return NOTIFY_BAD; break; case USB_DEVICE_REMOVE: usbdev_remove(dev); -- cgit v1.2.3 From 2a36d7083438ccb607055abae633f39495a99947 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 9 Oct 2006 00:08:00 +0200 Subject: USB: driver for mcs7830 (aka DeLOCK) USB ethernet adapter This driver adds support for the DeLOCK USB ethernet adapter and potentially others based on the MosChip MCS7830 chip. It is based on the usbnet and asix drivers as well as the original device driver provided by MosChip, which in turn was based on the usbnet driver. It has been tested successfully on an OHCI, but interestingly there seems to be a problem with the mcs7830 when connected to the ICH6/EHCI in my thinkpad: it keeps receiving lots of broken packets in the RX interrupt. The problem goes away when I'm using an active USB hub, so I assume it's not related to the device driver, but rather to the hardware. Signed-off-by: David Brownell Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/Kconfig | 8 + drivers/usb/net/Makefile | 1 + drivers/usb/net/mcs7830.c | 525 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 534 insertions(+) create mode 100644 drivers/usb/net/mcs7830.c (limited to 'drivers') diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 054059632a21..454a186b64ad 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -207,6 +207,14 @@ config USB_NET_PLUSB Choose this option if you're using a host-to-host cable with one of these chips. +config USB_NET_MCS7830 + tristate "MosChip MCS7830 based Ethernet adapters" + depends on USB_USBNET + help + Choose this option if you're using a 10/100 Ethernet USB2 + adapter based on the MosChip 7830 controller. This includes + adapters marketed under the DeLOCK brand. + config USB_NET_RNDIS_HOST tristate "Host for RNDIS devices (EXPERIMENTAL)" depends on USB_USBNET && EXPERIMENTAL diff --git a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile index 160f19dbdf12..7b51964de171 100644 --- a/drivers/usb/net/Makefile +++ b/drivers/usb/net/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_USB_NET_PLUSB) += plusb.o obj-$(CONFIG_USB_NET_RNDIS_HOST) += rndis_host.o obj-$(CONFIG_USB_NET_CDC_SUBSET) += cdc_subset.o obj-$(CONFIG_USB_NET_ZAURUS) += zaurus.o +obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o obj-$(CONFIG_USB_USBNET) += usbnet.o ifeq ($(CONFIG_USB_DEBUG),y) diff --git a/drivers/usb/net/mcs7830.c b/drivers/usb/net/mcs7830.c new file mode 100644 index 000000000000..0266090a1d7d --- /dev/null +++ b/drivers/usb/net/mcs7830.c @@ -0,0 +1,525 @@ +/* + * MosChips MCS7830 based USB 2.0 Ethernet Devices + * + * based on usbnet.c, asix.c and the vendor provided mcs7830 driver + * + * Copyright (C) 2006 Arnd Bergmann + * Copyright (C) 2003-2005 David Hollis + * Copyright (C) 2005 Phil Chang + * Copyright (c) 2002-2003 TiVo 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. + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "usbnet.h" + +/* requests */ +#define MCS7830_RD_BMREQ (USB_DIR_IN | USB_TYPE_VENDOR | \ + USB_RECIP_DEVICE) +#define MCS7830_WR_BMREQ (USB_DIR_OUT | USB_TYPE_VENDOR | \ + USB_RECIP_DEVICE) +#define MCS7830_RD_BREQ 0x0E +#define MCS7830_WR_BREQ 0x0D + +#define MCS7830_CTRL_TIMEOUT 1000 +#define MCS7830_MAX_MCAST 64 + +#define MCS7830_VENDOR_ID 0x9710 +#define MCS7830_PRODUCT_ID 0x7830 + +#define MCS7830_MII_ADVERTISE (ADVERTISE_PAUSE_CAP | ADVERTISE_100FULL | \ + ADVERTISE_100HALF | ADVERTISE_10FULL | \ + ADVERTISE_10HALF | ADVERTISE_CSMA) + +/* HIF_REG_XX coressponding index value */ +enum { + HIF_REG_MULTICAST_HASH = 0x00, + HIF_REG_PACKET_GAP1 = 0x08, + HIF_REG_PACKET_GAP2 = 0x09, + HIF_REG_PHY_DATA = 0x0a, + HIF_REG_PHY_CMD1 = 0x0c, + HIF_REG_PHY_CMD1_READ = 0x40, + HIF_REG_PHY_CMD1_WRITE = 0x20, + HIF_REG_PHY_CMD1_PHYADDR = 0x01, + HIF_REG_PHY_CMD2 = 0x0d, + HIF_REG_PHY_CMD2_PEND_FLAG_BIT = 0x80, + HIF_REG_PHY_CMD2_READY_FLAG_BIT = 0x40, + HIF_REG_CONFIG = 0x0e, + HIF_REG_CONFIG_CFG = 0x80, + HIF_REG_CONFIG_SPEED100 = 0x40, + HIF_REG_CONFIG_FULLDUPLEX_ENABLE = 0x20, + HIF_REG_CONFIG_RXENABLE = 0x10, + HIF_REG_CONFIG_TXENABLE = 0x08, + HIF_REG_CONFIG_SLEEPMODE = 0x04, + HIF_REG_CONFIG_ALLMULTICAST = 0x02, + HIF_REG_CONFIG_PROMISCIOUS = 0x01, + HIF_REG_ETHERNET_ADDR = 0x0f, + HIF_REG_22 = 0x15, + HIF_REG_PAUSE_THRESHOLD = 0x16, + HIF_REG_PAUSE_THRESHOLD_DEFAULT = 0, +}; + +struct mcs7830_data { + u8 multi_filter[8]; + u8 config; +}; + +static const char driver_name[] = "MOSCHIP usb-ethernet driver"; + +static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data) +{ + struct usb_device *xdev = dev->udev; + int ret; + + ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ, + MCS7830_RD_BMREQ, 0x0000, index, data, + size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT)); + return ret; +} + +static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data) +{ + struct usb_device *xdev = dev->udev; + int ret; + + ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ, + MCS7830_WR_BMREQ, 0x0000, index, data, + size, msecs_to_jiffies(MCS7830_CTRL_TIMEOUT)); + return ret; +} + +static void mcs7830_async_cmd_callback(struct urb *urb) +{ + struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context; + + if (urb->status < 0) + printk(KERN_DEBUG "mcs7830_async_cmd_callback() failed with %d", + urb->status); + + kfree(req); + usb_free_urb(urb); +} + +static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data) +{ + struct usb_ctrlrequest *req; + int ret; + struct urb *urb; + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_dbg(&dev->udev->dev, "Error allocating URB " + "in write_cmd_async!"); + return; + } + + req = kmalloc(sizeof *req, GFP_ATOMIC); + if (!req) { + dev_err(&dev->udev->dev, "Failed to allocate memory for " + "control request"); + goto out; + } + req->bRequestType = MCS7830_WR_BMREQ; + req->bRequest = MCS7830_WR_BREQ; + req->wValue = 0; + req->wIndex = cpu_to_le16(index); + req->wLength = cpu_to_le16(size); + + usb_fill_control_urb(urb, dev->udev, + usb_sndctrlpipe(dev->udev, 0), + (void *)req, data, size, + mcs7830_async_cmd_callback, req); + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret < 0) { + dev_err(&dev->udev->dev, "Error submitting the control " + "message: ret=%d", ret); + goto out; + } + return; +out: + kfree(req); + usb_free_urb(urb); +} + +static int mcs7830_get_address(struct usbnet *dev) +{ + int ret; + ret = mcs7830_get_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, + dev->net->dev_addr); + if (ret < 0) + return ret; + return 0; +} + +static int mcs7830_read_phy(struct usbnet *dev, u8 index) +{ + int ret; + int i; + __le16 val; + + u8 cmd[2] = { + HIF_REG_PHY_CMD1_READ | HIF_REG_PHY_CMD1_PHYADDR, + HIF_REG_PHY_CMD2_PEND_FLAG_BIT | index, + }; + + /* write the MII command */ + ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd); + if (ret < 0) + goto out; + + /* wait for the data to become valid, should be within < 1ms */ + for (i = 0; i < 10; i++) { + ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd); + if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT)) + break; + ret = -EIO; + msleep(1); + } + if (ret < 0) + goto out; + + /* read actual register contents */ + ret = mcs7830_get_reg(dev, HIF_REG_PHY_DATA, 2, &val); + if (ret < 0) + goto out; + ret = le16_to_cpu(val); + dev_dbg(&dev->udev->dev, "read PHY reg %02x: %04x (%d tries)\n", + index, val, i); +out: + return ret; +} + +static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val) +{ + int ret; + int i; + __le16 le_val; + + u8 cmd[2] = { + HIF_REG_PHY_CMD1_WRITE | HIF_REG_PHY_CMD1_PHYADDR, + HIF_REG_PHY_CMD2_PEND_FLAG_BIT | (index & 0x1F), + }; + + /* write the new register contents */ + le_val = cpu_to_le16(val); + ret = mcs7830_set_reg(dev, HIF_REG_PHY_DATA, 2, &le_val); + if (ret < 0) + goto out; + + /* write the MII command */ + ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd); + if (ret < 0) + goto out; + + /* wait for the command to be accepted by the PHY */ + for (i = 0; i < 10; i++) { + ret = mcs7830_get_reg(dev, HIF_REG_PHY_CMD1, 2, cmd); + if ((ret < 0) || (cmd[1] & HIF_REG_PHY_CMD2_READY_FLAG_BIT)) + break; + ret = -EIO; + msleep(1); + } + if (ret < 0) + goto out; + + ret = 0; + dev_dbg(&dev->udev->dev, "write PHY reg %02x: %04x (%d tries)\n", + index, val, i); +out: + return ret; +} + +/* + * This algorithm comes from the original mcs7830 version 1.4 driver, + * not sure if it is needed. + */ +static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode) +{ + int ret; + /* Enable all media types */ + ret = mcs7830_write_phy(dev, MII_ADVERTISE, MCS7830_MII_ADVERTISE); + + /* First reset BMCR */ + if (!ret) + ret = mcs7830_write_phy(dev, MII_BMCR, 0x0000); + /* Enable Auto Neg */ + if (!ret) + ret = mcs7830_write_phy(dev, MII_BMCR, BMCR_ANENABLE); + /* Restart Auto Neg (Keep the Enable Auto Neg Bit Set) */ + if (!ret) + ret = mcs7830_write_phy(dev, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART ); + return ret < 0 ? : 0; +} + + +/* + * if we can read register 22, the chip revision is C or higher + */ +static int mcs7830_get_rev(struct usbnet *dev) +{ + u8 dummy[2]; + int ret; + ret = mcs7830_get_reg(dev, HIF_REG_22, 2, dummy); + if (ret > 0) + return 2; /* Rev C or later */ + return 1; /* earlier revision */ +} + +/* + * On rev. C we need to set the pause threshold + */ +static void mcs7830_rev_C_fixup(struct usbnet *dev) +{ + u8 pause_threshold = HIF_REG_PAUSE_THRESHOLD_DEFAULT; + int retry; + + for (retry = 0; retry < 2; retry++) { + if (mcs7830_get_rev(dev) == 2) { + dev_info(&dev->udev->dev, "applying rev.C fixup\n"); + mcs7830_set_reg(dev, HIF_REG_PAUSE_THRESHOLD, + 1, &pause_threshold); + } + msleep(1); + } +} + +static int mcs7830_init_dev(struct usbnet *dev) +{ + int ret; + int retry; + + /* Read MAC address from EEPROM */ + ret = -EINVAL; + for (retry = 0; retry < 5 && ret; retry++) + ret = mcs7830_get_address(dev); + if (ret) { + dev_warn(&dev->udev->dev, "Cannot read MAC address\n"); + goto out; + } + + /* Set up PHY */ + ret = mcs7830_set_autoneg(dev, 0); + if (ret) { + dev_info(&dev->udev->dev, "Cannot set autoneg\n"); + goto out; + } + + mcs7830_rev_C_fixup(dev); + ret = 0; +out: + return ret; +} + +static int mcs7830_mdio_read(struct net_device *netdev, int phy_id, + int location) +{ + struct usbnet *dev = netdev->priv; + return mcs7830_read_phy(dev, location); +} + +static void mcs7830_mdio_write(struct net_device *netdev, int phy_id, + int location, int val) +{ + struct usbnet *dev = netdev->priv; + mcs7830_write_phy(dev, location, val); +} + +static int mcs7830_ioctl(struct net_device *net, struct ifreq *rq, int cmd) +{ + struct usbnet *dev = netdev_priv(net); + return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); +} + +/* credits go to asix_set_multicast */ +static void mcs7830_set_multicast(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + struct mcs7830_data *data = (struct mcs7830_data *)&dev->data; + + data->config = HIF_REG_CONFIG_TXENABLE; + + /* this should not be needed, but it doesn't work otherwise */ + data->config |= HIF_REG_CONFIG_ALLMULTICAST; + + if (net->flags & IFF_PROMISC) { + data->config |= HIF_REG_CONFIG_PROMISCIOUS; + } else if (net->flags & IFF_ALLMULTI + || net->mc_count > MCS7830_MAX_MCAST) { + data->config |= HIF_REG_CONFIG_ALLMULTICAST; + } else if (net->mc_count == 0) { + /* just broadcast and directed */ + } else { + /* We use the 20 byte dev->data + * for our 8 byte filter buffer + * to avoid allocating memory that + * is tricky to free later */ + struct dev_mc_list *mc_list = net->mc_list; + u32 crc_bits; + int i; + + memset(data->multi_filter, 0, sizeof data->multi_filter); + + /* Build the multicast hash filter. */ + for (i = 0; i < net->mc_count; i++) { + crc_bits = ether_crc(ETH_ALEN, mc_list->dmi_addr) >> 26; + data->multi_filter[crc_bits >> 3] |= 1 << (crc_bits & 7); + mc_list = mc_list->next; + } + + mcs7830_set_reg_async(dev, HIF_REG_MULTICAST_HASH, + sizeof data->multi_filter, + data->multi_filter); + } + + mcs7830_set_reg_async(dev, HIF_REG_CONFIG, 1, &data->config); +} + +static int mcs7830_get_regs_len(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + + switch (mcs7830_get_rev(dev)) { + case 1: + return 21; + case 2: + return 32; + } + return 0; +} + +static void mcs7830_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *drvinfo) +{ + usbnet_get_drvinfo(net, drvinfo); + drvinfo->regdump_len = mcs7830_get_regs_len(net); +} + +static void mcs7830_get_regs(struct net_device *net, struct ethtool_regs *regs, void *data) +{ + struct usbnet *dev = netdev_priv(net); + + regs->version = mcs7830_get_rev(dev); + mcs7830_get_reg(dev, 0, regs->len, data); +} + +static struct ethtool_ops mcs7830_ethtool_ops = { + .get_drvinfo = mcs7830_get_drvinfo, + .get_regs_len = mcs7830_get_regs_len, + .get_regs = mcs7830_get_regs, + + /* common usbnet calls */ + .get_msglevel = usbnet_get_msglevel, + .set_msglevel = usbnet_set_msglevel, +}; + +static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) +{ + struct net_device *net = dev->net; + int ret; + + ret = mcs7830_init_dev(dev); + if (ret) + goto out; + + net->do_ioctl = mcs7830_ioctl; + net->ethtool_ops = &mcs7830_ethtool_ops; + net->set_multicast_list = mcs7830_set_multicast; + mcs7830_set_multicast(net); + + /* reserve space for the status byte on rx */ + dev->rx_urb_size = ETH_FRAME_LEN + 1; + + dev->mii.mdio_read = mcs7830_mdio_read; + dev->mii.mdio_write = mcs7830_mdio_write; + dev->mii.dev = net; + dev->mii.phy_id_mask = 0x3f; + dev->mii.reg_num_mask = 0x1f; + dev->mii.phy_id = *((u8 *) net->dev_addr + 1); + + ret = usbnet_get_endpoints(dev, udev); +out: + return ret; +} + +/* The chip always appends a status bytes that we need to strip */ +static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + u8 status; + + if (skb->len == 0) { + dev_err(&dev->udev->dev, "unexpected empty rx frame\n"); + return 0; + } + + skb_trim(skb, skb->len - 1); + status = skb->data[skb->len]; + + if (status != 0x20) + dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status); + + return skb->len > 0; +} + +static const struct driver_info moschip_info = { + .description = "MOSCHIP 7830 usb-NET adapter", + .bind = mcs7830_bind, + .rx_fixup = mcs7830_rx_fixup, + .flags = FLAG_ETHER, + .in = 1, + .out = 2, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID), + .driver_info = (unsigned long) &moschip_info, + }, + {}, +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver mcs7830_driver = { + .name = driver_name, + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init mcs7830_init(void) +{ + return usb_register(&mcs7830_driver); +} +module_init(mcs7830_init); + +static void __exit mcs7830_exit(void) +{ + usb_deregister(&mcs7830_driver); +} +module_exit(mcs7830_exit); + +MODULE_DESCRIPTION("USB to network adapter MCS7830)"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From c41286fd42f3545513f8de9f61028120b6d38e89 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 9 Oct 2006 00:08:01 +0200 Subject: usbnet: improve generic ethtool support This adds generic support for the ethtool commands get_settings, set_settings, get_link and nway_reset to usbnet. These are now implemented using mii functions when a low-level driver supports mdio_read/mdio_write and does not override the usbnet ethtool commands with its own. Currently, this applies to the asix and the mcs7830 drivers. I have tested it on mcs7830. Signed-off-by: Arnd Bergmann Acked-by: David Hollis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/asix.c | 44 ++++++++------------------------------- drivers/usb/net/mcs7830.c | 4 ++++ drivers/usb/net/usbnet.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++- drivers/usb/net/usbnet.h | 4 ++++ 4 files changed, 68 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index c73dd224aa76..5edd0534c7ab 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -700,32 +700,6 @@ static void asix_get_drvinfo (struct net_device *net, info->eedump_len = data->eeprom_len; } -static int asix_get_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - - return mii_ethtool_gset(&dev->mii,cmd); -} - -static int asix_set_settings(struct net_device *net, struct ethtool_cmd *cmd) -{ - struct usbnet *dev = netdev_priv(net); - int res = mii_ethtool_sset(&dev->mii,cmd); - - /* link speed/duplex might have changed */ - if (dev->driver_info->link_reset) - dev->driver_info->link_reset(dev); - - return res; -} - -static int asix_nway_reset(struct net_device *net) -{ - struct usbnet *dev = netdev_priv(net); - - return mii_nway_restart(&dev->mii); -} - static u32 asix_get_link(struct net_device *net) { struct usbnet *dev = netdev_priv(net); @@ -746,15 +720,15 @@ static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) static struct ethtool_ops ax88172_ethtool_ops = { .get_drvinfo = asix_get_drvinfo, .get_link = asix_get_link, - .nway_reset = asix_nway_reset, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, .get_wol = asix_get_wol, .set_wol = asix_set_wol, .get_eeprom_len = asix_get_eeprom_len, .get_eeprom = asix_get_eeprom, - .get_settings = asix_get_settings, - .set_settings = asix_set_settings, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, }; static void ax88172_set_multicast(struct net_device *net) @@ -885,15 +859,15 @@ out1: static struct ethtool_ops ax88772_ethtool_ops = { .get_drvinfo = asix_get_drvinfo, .get_link = asix_get_link, - .nway_reset = asix_nway_reset, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, .get_wol = asix_get_wol, .set_wol = asix_set_wol, .get_eeprom_len = asix_get_eeprom_len, .get_eeprom = asix_get_eeprom, - .get_settings = asix_get_settings, - .set_settings = asix_set_settings, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, }; static int ax88772_link_reset(struct usbnet *dev) @@ -1046,15 +1020,15 @@ out1: static struct ethtool_ops ax88178_ethtool_ops = { .get_drvinfo = asix_get_drvinfo, .get_link = asix_get_link, - .nway_reset = asix_nway_reset, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, .get_wol = asix_get_wol, .set_wol = asix_set_wol, .get_eeprom_len = asix_get_eeprom_len, .get_eeprom = asix_get_eeprom, - .get_settings = asix_get_settings, - .set_settings = asix_set_settings, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, }; static int marvell_phy_init(struct usbnet *dev) diff --git a/drivers/usb/net/mcs7830.c b/drivers/usb/net/mcs7830.c index 0266090a1d7d..23a80667f17e 100644 --- a/drivers/usb/net/mcs7830.c +++ b/drivers/usb/net/mcs7830.c @@ -430,8 +430,12 @@ static struct ethtool_ops mcs7830_ethtool_ops = { .get_regs = mcs7830_get_regs, /* common usbnet calls */ + .get_link = usbnet_get_link, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, + .nway_reset = usbnet_nway_reset, }; static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index af6d061dc79b..decc1b179246 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -669,6 +669,37 @@ done: * they'll probably want to use this base set. */ +int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd) +{ + struct usbnet *dev = netdev_priv(net); + + if (!dev->mii.mdio_read) + return -EOPNOTSUPP; + + return mii_ethtool_gset(&dev->mii, cmd); +} +EXPORT_SYMBOL_GPL(usbnet_get_settings); + +int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd) +{ + struct usbnet *dev = netdev_priv(net); + int retval; + + if (!dev->mii.mdio_write) + return -EOPNOTSUPP; + + retval = mii_ethtool_sset(&dev->mii, cmd); + + /* link speed/duplex might have changed */ + if (dev->driver_info->link_reset) + dev->driver_info->link_reset(dev); + + return retval; + +} +EXPORT_SYMBOL_GPL(usbnet_set_settings); + + void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { struct usbnet *dev = netdev_priv(net); @@ -682,7 +713,7 @@ void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) } EXPORT_SYMBOL_GPL(usbnet_get_drvinfo); -static u32 usbnet_get_link (struct net_device *net) +u32 usbnet_get_link (struct net_device *net) { struct usbnet *dev = netdev_priv(net); @@ -690,9 +721,14 @@ static u32 usbnet_get_link (struct net_device *net) if (dev->driver_info->check_connect) return dev->driver_info->check_connect (dev) == 0; + /* if the device has mii operations, use those */ + if (dev->mii.mdio_read) + return mii_link_ok(&dev->mii); + /* Otherwise, say we're up (to avoid breaking scripts) */ return 1; } +EXPORT_SYMBOL_GPL(usbnet_get_link); u32 usbnet_get_msglevel (struct net_device *net) { @@ -710,10 +746,24 @@ void usbnet_set_msglevel (struct net_device *net, u32 level) } EXPORT_SYMBOL_GPL(usbnet_set_msglevel); +int usbnet_nway_reset(struct net_device *net) +{ + struct usbnet *dev = netdev_priv(net); + + if (!dev->mii.mdio_write) + return -EOPNOTSUPP; + + return mii_nway_restart(&dev->mii); +} +EXPORT_SYMBOL_GPL(usbnet_nway_reset); + /* drivers may override default ethtool_ops in their bind() routine */ static struct ethtool_ops usbnet_ethtool_ops = { + .get_settings = usbnet_get_settings, + .set_settings = usbnet_set_settings, .get_drvinfo = usbnet_get_drvinfo, .get_link = usbnet_get_link, + .nway_reset = usbnet_nway_reset, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, }; diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h index c0746f0454af..743947c3fb83 100644 --- a/drivers/usb/net/usbnet.h +++ b/drivers/usb/net/usbnet.h @@ -168,9 +168,13 @@ extern void usbnet_defer_kevent (struct usbnet *, int); extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); extern void usbnet_unlink_rx_urbs(struct usbnet *); +extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd); +extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd); +extern u32 usbnet_get_link (struct net_device *net); extern u32 usbnet_get_msglevel (struct net_device *); extern void usbnet_set_msglevel (struct net_device *, u32); extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *); +extern int usbnet_nway_reset(struct net_device *net); /* messaging support includes the interface name, so it must not be * used before it has one ... notably, in minidriver bind() calls. -- cgit v1.2.3 From a9fc6338bd51a3d5735839e756fe7b741c2e6fad Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 9 Oct 2006 00:08:02 +0200 Subject: usbnet: add a mutex around phy register access When working on the mcs7830, I noticed the need for a mutex in its mdio_read/mdio_write functions. A related problem seems to be present in the asix driver in the respective functions. This introduces a mutex in the common usbnet driver and uses it from the two hardware specific drivers. Acked-by: David Hollis Signed-off-by: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/asix.c | 4 ++++ drivers/usb/net/mcs7830.c | 5 +++++ drivers/usb/net/usbnet.c | 1 + drivers/usb/net/usbnet.h | 1 + 4 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 5edd0534c7ab..881841e600de 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -569,10 +569,12 @@ static int asix_mdio_read(struct net_device *netdev, int phy_id, int loc) struct usbnet *dev = netdev_priv(netdev); u16 res; + mutex_lock(&dev->phy_mutex); asix_set_sw_mii(dev); asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res); asix_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); devdbg(dev, "asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x", phy_id, loc, le16_to_cpu(res & 0xffff)); @@ -586,10 +588,12 @@ asix_mdio_write(struct net_device *netdev, int phy_id, int loc, int val) u16 res = cpu_to_le16(val); devdbg(dev, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x", phy_id, loc, val); + mutex_lock(&dev->phy_mutex); asix_set_sw_mii(dev); asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, (u16 *)&res); asix_set_hw_mii(dev); + mutex_unlock(&dev->phy_mutex); } /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ diff --git a/drivers/usb/net/mcs7830.c b/drivers/usb/net/mcs7830.c index 23a80667f17e..6240b978fe3d 100644 --- a/drivers/usb/net/mcs7830.c +++ b/drivers/usb/net/mcs7830.c @@ -184,6 +184,7 @@ static int mcs7830_read_phy(struct usbnet *dev, u8 index) HIF_REG_PHY_CMD2_PEND_FLAG_BIT | index, }; + mutex_lock(&dev->phy_mutex); /* write the MII command */ ret = mcs7830_set_reg(dev, HIF_REG_PHY_CMD1, 2, cmd); if (ret < 0) @@ -208,6 +209,7 @@ static int mcs7830_read_phy(struct usbnet *dev, u8 index) dev_dbg(&dev->udev->dev, "read PHY reg %02x: %04x (%d tries)\n", index, val, i); out: + mutex_unlock(&dev->phy_mutex); return ret; } @@ -222,6 +224,8 @@ static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val) HIF_REG_PHY_CMD2_PEND_FLAG_BIT | (index & 0x1F), }; + mutex_lock(&dev->phy_mutex); + /* write the new register contents */ le_val = cpu_to_le16(val); ret = mcs7830_set_reg(dev, HIF_REG_PHY_DATA, 2, &le_val); @@ -248,6 +252,7 @@ static int mcs7830_write_phy(struct usbnet *dev, u8 index, u16 val) dev_dbg(&dev->udev->dev, "write PHY reg %02x: %04x (%d tries)\n", index, val, i); out: + mutex_unlock(&dev->phy_mutex); return ret; } diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index decc1b179246..cf3d20eb781c 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -1144,6 +1144,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) dev->delay.function = usbnet_bh; dev->delay.data = (unsigned long) dev; init_timer (&dev->delay); + mutex_init (&dev->phy_mutex); SET_MODULE_OWNER (net); dev->net = net; diff --git a/drivers/usb/net/usbnet.h b/drivers/usb/net/usbnet.h index 743947c3fb83..07c70abbe0ec 100644 --- a/drivers/usb/net/usbnet.h +++ b/drivers/usb/net/usbnet.h @@ -30,6 +30,7 @@ struct usbnet { struct usb_device *udev; struct driver_info *driver_info; wait_queue_head_t *wait; + struct mutex phy_mutex; /* i/o info: pipes etc */ unsigned in, out; -- cgit v1.2.3 From 9fcde235270e6783600d1aee5bcda78c8282bcdd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Oct 2006 13:47:35 -0700 Subject: USB: move trancevibrator.c to the proper usb directory It's not a input driver, so it doesn't belong in the input directory. Cc: Sam Hocevar Cc: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 2 +- drivers/usb/input/Kconfig | 10 --- drivers/usb/input/Makefile | 1 - drivers/usb/input/trancevibrator.c | 159 ------------------------------------- drivers/usb/misc/Kconfig | 10 +++ drivers/usb/misc/Makefile | 1 + drivers/usb/misc/trancevibrator.c | 159 +++++++++++++++++++++++++++++++++++++ 7 files changed, 171 insertions(+), 171 deletions(-) delete mode 100644 drivers/usb/input/trancevibrator.c create mode 100644 drivers/usb/misc/trancevibrator.c (limited to 'drivers') diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 97d57cfc343b..825bf884537a 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_USB_KBTAB) += input/ obj-$(CONFIG_USB_MOUSE) += input/ obj-$(CONFIG_USB_MTOUCH) += input/ obj-$(CONFIG_USB_POWERMATE) += input/ -obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/ obj-$(CONFIG_USB_WACOM) += input/ obj-$(CONFIG_USB_XPAD) += input/ @@ -66,6 +65,7 @@ obj-$(CONFIG_USB_PHIDGETSERVO) += misc/ obj-$(CONFIG_USB_RIO500) += misc/ obj-$(CONFIG_USB_SISUSBVGA) += misc/ obj-$(CONFIG_USB_TEST) += misc/ +obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/ obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_ATM) += atm/ diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 21cd22640080..20db36448ab3 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -348,13 +348,3 @@ config USB_APPLETOUCH To compile this driver as a module, choose M here: the module will be called appletouch. - -config USB_TRANCEVIBRATOR - tristate "PlayStation 2 Trance Vibrator driver support" - depends on USB - help - Say Y here if you want to connect a PlayStation 2 Trance Vibrator - device to your computer's USB port. - - To compile this driver as a module, choose M here: the - module will be called trancevibrator. diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 71437db7e9b1..d946d5213b30 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile @@ -48,7 +48,6 @@ obj-$(CONFIG_USB_ACECAD) += acecad.o obj-$(CONFIG_USB_YEALINK) += yealink.o obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_APPLETOUCH) += appletouch.o -obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o ifeq ($(CONFIG_USB_DEBUG),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/usb/input/trancevibrator.c b/drivers/usb/input/trancevibrator.c deleted file mode 100644 index 33cd91d11eca..000000000000 --- a/drivers/usb/input/trancevibrator.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - * PlayStation 2 Trance Vibrator driver - * - * Copyright (C) 2006 Sam Hocevar - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Standard include files */ -#include -#include -#include -#include -#include - -/* Version Information */ -#define DRIVER_VERSION "v1.1" -#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org" -#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver" - -#define TRANCEVIBRATOR_VENDOR_ID 0x0b49 /* ASCII Corporation */ -#define TRANCEVIBRATOR_PRODUCT_ID 0x064f /* Trance Vibrator */ - -static struct usb_device_id id_table [] = { - { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, - { }, -}; -MODULE_DEVICE_TABLE (usb, id_table); - -/* Driver-local specific stuff */ -struct trancevibrator { - struct usb_device *udev; - unsigned int speed; -}; - -static ssize_t show_speed(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct trancevibrator *tv = usb_get_intfdata(intf); - - return sprintf(buf, "%d\n", tv->speed); -} - -static ssize_t set_speed(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct usb_interface *intf = to_usb_interface(dev); - struct trancevibrator *tv = usb_get_intfdata(intf); - int temp, retval; - - temp = simple_strtoul(buf, NULL, 10); - if (temp > 255) - temp = 255; - else if (temp < 0) - temp = 0; - tv->speed = temp; - - dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed); - - /* Set speed */ - retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), - 0x01, /* vendor request: set speed */ - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, - tv->speed, /* speed value */ - 0, NULL, 0, USB_CTRL_GET_TIMEOUT); - if (retval) { - dev_dbg(&tv->udev->dev, "retval = %d\n", retval); - return retval; - } - return count; -} - -static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed); - -static int tv_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct trancevibrator *dev; - int retval; - - dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); - retval = -ENOMEM; - goto error; - } - - dev->udev = usb_get_dev(udev); - usb_set_intfdata(interface, dev); - retval = device_create_file(&interface->dev, &dev_attr_speed); - if (retval) - goto error_create_file; - - return 0; - -error_create_file: - usb_put_dev(udev); - usb_set_intfdata(interface, NULL); -error: - kfree(dev); - return retval; -} - -static void tv_disconnect(struct usb_interface *interface) -{ - struct trancevibrator *dev; - - dev = usb_get_intfdata (interface); - usb_set_intfdata(interface, NULL); - device_remove_file(&interface->dev, &dev_attr_speed); - usb_put_dev(dev->udev); - kfree(dev); -} - -/* USB subsystem object */ -static struct usb_driver tv_driver = { - .name = "trancevibrator", - .probe = tv_probe, - .disconnect = tv_disconnect, - .id_table = id_table, -}; - -static int __init tv_init(void) -{ - int retval = usb_register(&tv_driver); - if (retval) { - err("usb_register failed. Error number %d", retval); - return retval; - } - - info(DRIVER_VERSION ":" DRIVER_DESC); - return 0; -} - -static void __exit tv_exit(void) -{ - usb_deregister(&tv_driver); -} - -module_init (tv_init); -module_exit (tv_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index c29658f69e2a..a74bf8617e7f 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -223,6 +223,16 @@ config USB_LD To compile this driver as a module, choose M here: the module will be called ldusb. +config USB_TRANCEVIBRATOR + tristate "PlayStation 2 Trance Vibrator driver support" + depends on USB + help + Say Y here if you want to connect a PlayStation 2 Trance Vibrator + device to your computer's USB port. + + To compile this driver as a module, choose M here: the + module will be called trancevibrator. + config USB_TEST tristate "USB testing driver (DEVELOPMENT)" depends on USB && USB_DEVICEFS && EXPERIMENTAL diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 2be70fa259bf..11dc59540cda 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o +obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o obj-$(CONFIG_USB_USS720) += uss720.o obj-$(CONFIG_USB_SISUSBVGA) += sisusbvga/ diff --git a/drivers/usb/misc/trancevibrator.c b/drivers/usb/misc/trancevibrator.c new file mode 100644 index 000000000000..33cd91d11eca --- /dev/null +++ b/drivers/usb/misc/trancevibrator.c @@ -0,0 +1,159 @@ +/* + * PlayStation 2 Trance Vibrator driver + * + * Copyright (C) 2006 Sam Hocevar + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Standard include files */ +#include +#include +#include +#include +#include + +/* Version Information */ +#define DRIVER_VERSION "v1.1" +#define DRIVER_AUTHOR "Sam Hocevar, sam@zoy.org" +#define DRIVER_DESC "PlayStation 2 Trance Vibrator driver" + +#define TRANCEVIBRATOR_VENDOR_ID 0x0b49 /* ASCII Corporation */ +#define TRANCEVIBRATOR_PRODUCT_ID 0x064f /* Trance Vibrator */ + +static struct usb_device_id id_table [] = { + { USB_DEVICE(TRANCEVIBRATOR_VENDOR_ID, TRANCEVIBRATOR_PRODUCT_ID) }, + { }, +}; +MODULE_DEVICE_TABLE (usb, id_table); + +/* Driver-local specific stuff */ +struct trancevibrator { + struct usb_device *udev; + unsigned int speed; +}; + +static ssize_t show_speed(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct trancevibrator *tv = usb_get_intfdata(intf); + + return sprintf(buf, "%d\n", tv->speed); +} + +static ssize_t set_speed(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct usb_interface *intf = to_usb_interface(dev); + struct trancevibrator *tv = usb_get_intfdata(intf); + int temp, retval; + + temp = simple_strtoul(buf, NULL, 10); + if (temp > 255) + temp = 255; + else if (temp < 0) + temp = 0; + tv->speed = temp; + + dev_dbg(&tv->udev->dev, "speed = %d\n", tv->speed); + + /* Set speed */ + retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0), + 0x01, /* vendor request: set speed */ + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER, + tv->speed, /* speed value */ + 0, NULL, 0, USB_CTRL_GET_TIMEOUT); + if (retval) { + dev_dbg(&tv->udev->dev, "retval = %d\n", retval); + return retval; + } + return count; +} + +static DEVICE_ATTR(speed, S_IWUGO | S_IRUGO, show_speed, set_speed); + +static int tv_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct trancevibrator *dev; + int retval; + + dev = kzalloc(sizeof(struct trancevibrator), GFP_KERNEL); + if (dev == NULL) { + dev_err(&interface->dev, "Out of memory\n"); + retval = -ENOMEM; + goto error; + } + + dev->udev = usb_get_dev(udev); + usb_set_intfdata(interface, dev); + retval = device_create_file(&interface->dev, &dev_attr_speed); + if (retval) + goto error_create_file; + + return 0; + +error_create_file: + usb_put_dev(udev); + usb_set_intfdata(interface, NULL); +error: + kfree(dev); + return retval; +} + +static void tv_disconnect(struct usb_interface *interface) +{ + struct trancevibrator *dev; + + dev = usb_get_intfdata (interface); + usb_set_intfdata(interface, NULL); + device_remove_file(&interface->dev, &dev_attr_speed); + usb_put_dev(dev->udev); + kfree(dev); +} + +/* USB subsystem object */ +static struct usb_driver tv_driver = { + .name = "trancevibrator", + .probe = tv_probe, + .disconnect = tv_disconnect, + .id_table = id_table, +}; + +static int __init tv_init(void) +{ + int retval = usb_register(&tv_driver); + if (retval) { + err("usb_register failed. Error number %d", retval); + return retval; + } + + info(DRIVER_VERSION ":" DRIVER_DESC); + return 0; +} + +static void __exit tv_exit(void) +{ + usb_deregister(&tv_driver); +} + +module_init (tv_init); +module_exit (tv_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 0f64478cbc7a008fe7b7e9ae79a73d8a6904ead8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Apr 2002 12:14:34 -0700 Subject: USB: add USB serial mos7720 driver Add support for Moschip 7720 USB dual port usb to serial device. This driver is originally based on the drivers/usb/io_edgeport.c driver. Cleaned up and forward ported by me. Cc: VijayaKumar Cc: AjayKumar Cc: Gurudeva Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 10 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/mos7720.c | 1683 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1694 insertions(+) create mode 100644 drivers/usb/serial/mos7720.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 5076b9d97057..8ca6d3f01e85 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -422,6 +422,16 @@ config USB_SERIAL_MCT_U232 To compile this driver as a module, choose M here: the module will be called mct_u232. +config USB_SERIAL_MOS7720 + tristate "USB Moschip 7720 Single Port Serial Driver" + depends on USB_SERIAL + ---help--- + Say Y here if you want to use a USB Serial single port adapter from + Moschip Semiconductor Tech. + + To compile this driver as a module, choose M here: the + module will be called mos7720. + config USB_SERIAL_MOS7840 tristate "USB Moschip 7840/7820 USB Serial Driver" depends on USB_SERIAL diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 8dce83340e31..a5047dc599bb 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN_PDA) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o +obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c new file mode 100644 index 000000000000..82cd15b894b0 --- /dev/null +++ b/drivers/usb/serial/mos7720.c @@ -0,0 +1,1683 @@ +/* + * mos7720.c + * Controls the Moschip 7720 usb to dual port serial convertor + * + * Copyright 2006 Moschip Semiconductor Tech. Ltd. + * + * 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, version 2 of the License. + * + * Developed by: + * VijayaKumar.G.N. + * AjayKumar + * Gurudeva.N. + * + * Cleaned up from the original by: + * Greg Kroah-Hartman + * + * Originally based on drivers/usb/serial/io_edgeport.c which is: + * Copyright (C) 2000 Inside Out Networks, All rights reserved. + * Copyright (C) 2001-2002 Greg Kroah-Hartman + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Version Information + */ +#define DRIVER_VERSION "1.0.0.4F" +#define DRIVER_AUTHOR "Aspire Communications pvt Ltd." +#define DRIVER_DESC "Moschip USB Serial Driver" + +/* default urb timeout */ +#define MOS_WDR_TIMEOUT (HZ * 5) + +#define MOS_PORT1 0x0200 +#define MOS_PORT2 0x0300 +#define MOS_VENREG 0x0000 +#define MOS_MAX_PORT 0x02 +#define MOS_WRITE 0x0E +#define MOS_READ 0x0D + +/* Interrupt Rotinue Defines */ +#define SERIAL_IIR_RLS 0x06 +#define SERIAL_IIR_RDA 0x04 +#define SERIAL_IIR_CTI 0x0c +#define SERIAL_IIR_THR 0x02 +#define SERIAL_IIR_MS 0x00 + +#define NUM_URBS 16 /* URB Count */ +#define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ + +/* This structure holds all of the local port information */ +struct moschip_port +{ + __u8 shadowLCR; /* last LCR value received */ + __u8 shadowMCR; /* last MCR value received */ + __u8 shadowMSR; /* last MSR value received */ + char open; + struct async_icount icount; + struct usb_serial_port *port; /* loop back to the owner */ + struct urb *write_urb_pool[NUM_URBS]; +}; + +/* This structure holds all of the individual serial device information */ +struct moschip_serial +{ + int interrupt_started; +}; + +static int debug; + +#define USB_VENDOR_ID_MOSCHIP 0x9710 +#define MOSCHIP_DEVICE_ID_7720 0x7720 +#define MOSCHIP_DEVICE_ID_7715 0x7715 + +static struct usb_device_id moschip_port_id_table [] = { + { USB_DEVICE(USB_VENDOR_ID_MOSCHIP,MOSCHIP_DEVICE_ID_7720) }, + { } /* terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, moschip_port_id_table); + + +/* + * mos7720_interrupt_callback + * this is the callback function for when we have received data on the + * interrupt endpoint. + */ +static void mos7720_interrupt_callback(struct urb *urb) +{ + int result; + int length; + __u32 *data; + unsigned int status; + __u8 sp1; + __u8 sp2; + __u8 st; + + dbg("%s"," : Entering\n"); + + if (!urb) { + dbg("%s","Invalid Pointer !!!!:\n"); + return; + } + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __FUNCTION__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __FUNCTION__, + urb->status); + goto exit; + } + + length = urb->actual_length; + data = urb->transfer_buffer; + + /* Moschip get 4 bytes + * Byte 1 IIR Port 1 (port.number is 0) + * Byte 2 IIR Port 2 (port.number is 1) + * Byte 3 -------------- + * Byte 4 FIFO status for both */ + if (length && length > 4) { + dbg("Wrong data !!!"); + return; + } + + status = *data; + + sp1 = (status & 0xff000000)>>24; + sp2 = (status & 0x00ff0000)>>16; + st = status & 0x000000ff; + + if ((sp1 & 0x01) || (sp2 & 0x01)) { + /* No Interrupt Pending in both the ports */ + dbg("No Interrupt !!!"); + } else { + switch (sp1 & 0x0f) { + case SERIAL_IIR_RLS: + dbg("Serial Port 1: Receiver status error or address " + "bit detected in 9-bit mode\n"); + break; + case SERIAL_IIR_CTI: + dbg("Serial Port 1: Receiver time out"); + break; + case SERIAL_IIR_MS: + dbg("Serial Port 1: Modem status change"); + break; + } + + switch (sp2 & 0x0f) { + case SERIAL_IIR_RLS: + dbg("Serial Port 2: Receiver status error or address " + "bit detected in 9-bit mode"); + break; + case SERIAL_IIR_CTI: + dbg("Serial Port 2: Receiver time out"); + break; + case SERIAL_IIR_MS: + dbg("Serial Port 2: Modem status change"); + break; + } + } + +exit: + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) + dev_err(&urb->dev->dev, + "%s - Error %d submitting control urb\n", + __FUNCTION__, result); + return; +} + +/* + * mos7720_bulk_in_callback + * this is the callback function for when we have received data on the + * bulk in endpoint. + */ +static void mos7720_bulk_in_callback(struct urb *urb) +{ + int status; + unsigned char *data ; + struct usb_serial_port *port; + struct moschip_port *mos7720_port; + struct tty_struct *tty; + + if (urb->status) { + dbg("nonzero read bulk status received: %d",urb->status); + return; + } + + mos7720_port = urb->context; + if (!mos7720_port) { + dbg("%s","NULL mos7720_port pointer \n"); + return ; + } + + port = mos7720_port->port; + + dbg("Entering...%s", __FUNCTION__); + + data = urb->transfer_buffer; + + tty = port->tty; + if (tty && urb->actual_length) { + tty_buffer_request_room(tty, urb->actual_length); + tty_insert_flip_string(tty, data, urb->actual_length); + tty_flip_buffer_push(tty); + } + + if (!port->read_urb) { + dbg("URB KILLED !!!"); + return; + } + + if (port->read_urb->status != -EINPROGRESS) { + port->read_urb->dev = port->serial->dev; + + status = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (status) + dbg("usb_submit_urb(read bulk) failed, status = %d", + status); + } +} + +/* + * mos7720_bulk_out_data_callback + * this is the callback function for when we have finished sending serial + * data on the bulk out endpoint. + */ +static void mos7720_bulk_out_data_callback(struct urb *urb) +{ + struct moschip_port *mos7720_port; + struct tty_struct *tty; + + if (urb->status) { + dbg("nonzero write bulk status received:%d", urb->status); + return; + } + + mos7720_port = urb->context; + if (!mos7720_port) { + dbg("NULL mos7720_port pointer"); + return ; + } + + dbg("Entering ........."); + + tty = mos7720_port->port->tty; + + if (tty && mos7720_port->open) { + /* let the tty driver wakeup if it has a special * + * write_wakeup function */ + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + + /* tell the tty driver that something has changed */ + wake_up_interruptible(&tty->write_wait); + } + + /* schedule_work(&mos7720_port->port->work); */ +} + +/* + * send_mos_cmd + * this function will be used for sending command to device + */ +static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, + __u16 index, void *data) +{ + int status; + unsigned int pipe; + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); + __u8 requesttype; + __u16 size = 0x0000; + + if (value < MOS_MAX_PORT) { + if (product == MOSCHIP_DEVICE_ID_7715) { + value = value*0x100+0x100; + } else { + value = value*0x100+0x200; + } + } else { + value = 0x0000; + if ((product == MOSCHIP_DEVICE_ID_7715) && + (index != 0x08)) { + dbg("serial->product== MOSCHIP_DEVICE_ID_7715"); + //index = 0x01 ; + } + } + + if (request == MOS_WRITE) { + request = (__u8)MOS_WRITE; + requesttype = (__u8)0x40; + value = value + (__u16)*((unsigned char *)data); + data = NULL; + pipe = usb_sndctrlpipe(serial->dev, 0); + } else { + request = (__u8)MOS_READ; + requesttype = (__u8)0xC0; + size = 0x01; + pipe = usb_rcvctrlpipe(serial->dev,0); + } + + status = usb_control_msg(serial->dev, pipe, request, requesttype, + value, index, data, size, MOS_WDR_TIMEOUT); + + if (status < 0) + dbg("Command Write failed Value %x index %x\n",value,index); + + return status; +} + +static int mos7720_open(struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial; + struct usb_serial_port *port0; + struct urb *urb; + struct moschip_serial *mos7720_serial; + struct moschip_port *mos7720_port; + int response; + int port_number; + char data; + int j; + + serial = port->serial; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) + return -ENODEV; + + port0 = serial->port[0]; + + mos7720_serial = usb_get_serial_data(serial); + + if (mos7720_serial == NULL || port0 == NULL) + return -ENODEV; + + usb_clear_halt(serial->dev, port->write_urb->pipe); + usb_clear_halt(serial->dev, port->read_urb->pipe); + + /* Initialising the write urb pool */ + for (j = 0; j < NUM_URBS; ++j) { + urb = usb_alloc_urb(0,SLAB_ATOMIC); + mos7720_port->write_urb_pool[j] = urb; + + if (urb == NULL) { + err("No more urbs???"); + continue; + } + + urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, + GFP_KERNEL); + if (!urb->transfer_buffer) { + err("%s-out of memory for urb buffers.", __FUNCTION__); + continue; + } + } + + /* Initialize MCS7720 -- Write Init values to corresponding Registers + * + * Register Index + * 1 : IER + * 2 : FCR + * 3 : LCR + * 4 : MCR + * + * 0x08 : SP1/2 Control Reg + */ + port_number = port->number - port->serial->minor; + send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); + dbg("SS::%p LSR:%x\n",mos7720_port, data); + + dbg("Check:Sending Command .........."); + + data = 0x02; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data); + data = 0x02; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data); + + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); + + data = 0xCF; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); + data = 0x03; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); + data = 0x0b; + mos7720_port->shadowMCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x0b; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + + data = 0x00; + send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); + +/* data = 0x00; + send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data); + data = 0x03; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); + data = 0x00; + send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); +*/ + data = 0x00; + send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); + + data = data | (port->number - port->serial->minor + 1); + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); + + data = 0x83; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + data = 0x03; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + +//Matrix + + /* force low_latency on so that our tty_push actually forces * + * the data through,otherwise it is scheduled, and with * + * high data rates (like with OHCI) data can get lost. */ + + if (port->tty) + port->tty->low_latency = 1; + + /* see if we've set up our endpoint info yet * + * (can't set it up in mos7720_startup as the * + * structures were not set up at that time.) */ + if (!mos7720_serial->interrupt_started) { + dbg("Interrupt buffer NULL !!!"); + + /* not set up yet, so do it now */ + mos7720_serial->interrupt_started = 1; + + dbg("To Submit URB !!!"); + + /* set up our interrupt urb */ + usb_fill_int_urb(port0->interrupt_in_urb, serial->dev, + usb_rcvintpipe(serial->dev, + port->interrupt_in_endpointAddress), + port0->interrupt_in_buffer, + port0->interrupt_in_urb->transfer_buffer_length, + mos7720_interrupt_callback, mos7720_port, + port0->interrupt_in_urb->interval); + + /* start interrupt read for this mos7720 this interrupt * + * will continue as long as the mos7720 is connected */ + dbg("Submit URB over !!!"); + response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL); + if (response) + dev_err(&port->dev, + "%s - Error %d submitting control urb", + __FUNCTION__, response); + } + + /* set up our bulk in urb */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->bulk_in_buffer, + port->read_urb->transfer_buffer_length, + mos7720_bulk_in_callback, mos7720_port); + response = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (response) + dev_err(&port->dev, + "%s - Error %d submitting read urb", __FUNCTION__, response); + + /* initialize our icount structure */ + memset(&(mos7720_port->icount), 0x00, sizeof(mos7720_port->icount)); + + /* initialize our port settings */ + mos7720_port->shadowMCR = UART_MCR_OUT2; /* Must set to enable ints! */ + + /* send a open port command */ + mos7720_port->open = 1; + + return 0; +} + +/* + * mos7720_chars_in_buffer + * this function is called by the tty driver when it wants to know how many + * bytes of data we currently have outstanding in the port (data that has + * been written, but hasn't made it out the port yet) + * If successful, we return the number of bytes left to be written in the + * system, + * Otherwise we return a negative error number. + */ +static int mos7720_chars_in_buffer(struct usb_serial_port *port) +{ + int i; + int chars = 0; + struct moschip_port *mos7720_port; + + dbg("%s:entering ...........", __FUNCTION__); + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) { + dbg("%s:leaving ...........", __FUNCTION__); + return -ENODEV; + } + + for (i = 0; i < NUM_URBS; ++i) { + if (mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) + chars += URB_TRANSFER_BUFFER_SIZE; + } + dbg("%s - returns %d", __FUNCTION__, chars); + return chars; +} + +static void mos7720_close(struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial; + struct moschip_port *mos7720_port; + char data; + int j; + + dbg("mos7720_close:entering..."); + + serial = port->serial; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) + return; + + for (j = 0; j < NUM_URBS; ++j) + usb_kill_urb(mos7720_port->write_urb_pool[j]); + + /* Freeing Write URBs */ + for (j = 0; j < NUM_URBS; ++j) { + if (mos7720_port->write_urb_pool[j]) { + kfree(mos7720_port->write_urb_pool[j]->transfer_buffer); + usb_free_urb(mos7720_port->write_urb_pool[j]); + } + } + + /* While closing port, shutdown all bulk read, write * + * and interrupt read if they exists */ + if (serial->dev) { + dbg("Shutdown bulk write"); + usb_kill_urb(port->write_urb); + dbg("Shutdown bulk read"); + usb_kill_urb(port->read_urb); + } + + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, + 0x04, &data); + + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, + 0x01, &data); + + mos7720_port->open = 0; + + dbg("Leaving %s", __FUNCTION__); +} + +static void mos7720_break(struct usb_serial_port *port, int break_state) +{ + unsigned char data; + struct usb_serial *serial; + struct moschip_port *mos7720_port; + + dbg("Entering %s", __FUNCTION__); + + serial = port->serial; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) + return; + + if (break_state == -1) + data = mos7720_port->shadowLCR | UART_LCR_SBC; + else + data = mos7720_port->shadowLCR & ~UART_LCR_SBC; + + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, + 0x03, &data); + + return; +} + +/* + * mos7720_write_room + * this function is called by the tty driver when it wants to know how many + * bytes of data we can accept for a specific port. + * If successful, we return the amount of room that we have for this port + * Otherwise we return a negative error number. + */ +static int mos7720_write_room(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + int room = 0; + int i; + + dbg("%s:entering ...........", __FUNCTION__); + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) { + dbg("%s:leaving ...........", __FUNCTION__); + return -ENODEV; + } + + for (i = 0; i < NUM_URBS; ++i) { + if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) + room += URB_TRANSFER_BUFFER_SIZE; + } + + dbg("%s - returns %d", __FUNCTION__, room); + return room; +} + +static int mos7720_write(struct usb_serial_port *port, + const unsigned char *data, int count) +{ + int status; + int i; + int bytes_sent = 0; + int transfer_size; + + struct moschip_port *mos7720_port; + struct usb_serial *serial; + struct urb *urb; + const unsigned char *current_position = data; + + dbg("%s:entering ...........", __FUNCTION__); + + serial = port->serial; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) { + dbg("mos7720_port is NULL"); + return -ENODEV; + } + + /* try to find a free urb in the list */ + urb = NULL; + + for (i = 0; i < NUM_URBS; ++i) { + if (mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { + urb = mos7720_port->write_urb_pool[i]; + dbg("URB:%d",i); + break; + } + } + + if (urb == NULL) { + dbg("%s - no more free urbs", __FUNCTION__); + goto exit; + } + + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = kmalloc(URB_TRANSFER_BUFFER_SIZE, + GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err("%s no more kernel memory...", __FUNCTION__); + goto exit; + } + } + transfer_size = min (count, URB_TRANSFER_BUFFER_SIZE); + + memcpy(urb->transfer_buffer, current_position, transfer_size); + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, + urb->transfer_buffer); + + /* fill urb with data and submit */ + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + urb->transfer_buffer, transfer_size, + mos7720_bulk_out_data_callback, mos7720_port); + + /* send it down the pipe */ + status = usb_submit_urb(urb,GFP_ATOMIC); + if (status) { + err("%s - usb_submit_urb(write bulk) failed with status = %d", + __FUNCTION__, status); + bytes_sent = status; + goto exit; + } + bytes_sent = transfer_size; + +exit: + return bytes_sent; +} + +static void mos7720_throttle(struct usb_serial_port *port) +{ + struct moschip_port *mos7720_port; + struct tty_struct *tty; + int status; + + dbg("%s- port %d\n", __FUNCTION__, port->number); + + mos7720_port = usb_get_serial_port_data(port); + + if (mos7720_port == NULL) + return; + + if (!mos7720_port->open) { + dbg("port not opened"); + return; + } + + dbg("%s: Entering ..........", __FUNCTION__); + + tty = port->tty; + if (!tty) { + dbg("%s - no tty available", __FUNCTION__); + return; + } + + /* if we are implementing XON/XOFF, send the stop character */ + if (I_IXOFF(tty)) { + unsigned char stop_char = STOP_CHAR(tty); + status = mos7720_write(port, &stop_char, 1); + if (status <= 0) + return; + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + mos7720_port->shadowMCR &= ~UART_MCR_RTS; + status = send_mos_cmd(port->serial, MOS_WRITE, + port->number - port->serial->minor, + UART_MCR, &mos7720_port->shadowMCR); + if (status != 0) + return; + } +} + +static void mos7720_unthrottle(struct usb_serial_port *port) +{ + struct tty_struct *tty; + int status; + struct moschip_port *mos7720_port = usb_get_serial_port_data(port); + + if (mos7720_port == NULL) + return; + + if (!mos7720_port->open) { + dbg("%s - port not opened", __FUNCTION__); + return; + } + + dbg("%s: Entering ..........", __FUNCTION__); + + tty = port->tty; + if (!tty) { + dbg("%s - no tty available", __FUNCTION__); + return; + } + + /* if we are implementing XON/XOFF, send the start character */ + if (I_IXOFF(tty)) { + unsigned char start_char = START_CHAR(tty); + status = mos7720_write(port, &start_char, 1); + if (status <= 0) + return; + } + + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + mos7720_port->shadowMCR |= UART_MCR_RTS; + status = send_mos_cmd(port->serial, MOS_WRITE, + port->number - port->serial->minor, + UART_MCR, &mos7720_port->shadowMCR); + if (status != 0) + return; + } +} + +static int set_higher_rates(struct moschip_port *mos7720_port, + unsigned int baud) +{ + unsigned char data; + struct usb_serial_port *port; + struct usb_serial *serial; + int port_number; + + if (mos7720_port == NULL) + return -EINVAL; + + port = mos7720_port->port; + serial = port->serial; + + /*********************************************** + * Init Sequence for higher rates + ***********************************************/ + dbg("Sending Setting Commands .........."); + port_number = port->number - port->serial->minor; + + data = 0x000; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + data = 0x000; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); + data = 0x0CF; + send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data); + data = 0x00b; + mos7720_port->shadowMCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x00b; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + + data = 0x000; + send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); + data = 0x000; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); + + + /*********************************************** + * Set for higher rates * + ***********************************************/ + + data = baud * 0x10; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1,&data); + + data = 0x003; + send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); + data = 0x003; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); + + data = 0x02b; + mos7720_port->shadowMCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x02b; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + + /*********************************************** + * Set DLL/DLM + ***********************************************/ + + data = mos7720_port->shadowLCR | UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); + + data = 0x001; /* DLL */ + send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); + data = 0x000; /* DLM */ + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + + data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); + + return 0; +} + +/* baud rate information */ +struct divisor_table_entry +{ + __u32 baudrate; + __u16 divisor; +}; + +/* Define table of divisors for moschip 7720 hardware * + * These assume a 3.6864MHz crystal, the standard /16, and * + * MCR.7 = 0. */ +static struct divisor_table_entry divisor_table[] = { + { 50, 2304}, + { 110, 1047}, /* 2094.545455 => 230450 => .0217 % over */ + { 134, 857}, /* 1713.011152 => 230398.5 => .00065% under */ + { 150, 768}, + { 300, 384}, + { 600, 192}, + { 1200, 96}, + { 1800, 64}, + { 2400, 48}, + { 4800, 24}, + { 7200, 16}, + { 9600, 12}, + { 19200, 6}, + { 38400, 3}, + { 57600, 2}, + { 115200, 1}, +}; + +/***************************************************************************** + * calc_baud_rate_divisor + * this function calculates the proper baud rate divisor for the specified + * baud rate. + *****************************************************************************/ +static int calc_baud_rate_divisor(int baudrate, int *divisor) +{ + int i; + __u16 custom; + __u16 round1; + __u16 round; + + + dbg("%s - %d", __FUNCTION__, baudrate); + + for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { + if (divisor_table[i].baudrate == baudrate) { + *divisor = divisor_table[i].divisor; + return 0; + } + } + + /* After trying for all the standard baud rates * + * Try calculating the divisor for this baud rate */ + if (baudrate > 75 && baudrate < 230400) { + /* get the divisor */ + custom = (__u16)(230400L / baudrate); + + /* Check for round off */ + round1 = (__u16)(2304000L / baudrate); + round = (__u16)(round1 - (custom * 10)); + if (round > 4) + custom++; + *divisor = custom; + + dbg("Baud %d = %d",baudrate, custom); + return 0; + } + + dbg("Baud calculation Failed..."); + return -EINVAL; +} + +/* + * send_cmd_write_baud_rate + * this function sends the proper command to change the baud rate of the + * specified port. + */ +static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, + int baudrate) +{ + struct usb_serial_port *port; + struct usb_serial *serial; + int divisor; + int status; + unsigned char data; + unsigned char number; + + if (mos7720_port == NULL) + return -1; + + port = mos7720_port->port; + serial = port->serial; + + dbg("%s: Entering ..........", __FUNCTION__); + + number = port->number - port->serial->minor; + dbg("%s - port = %d, baud = %d", __FUNCTION__, port->number, baudrate); + + /* Calculate the Divisor */ + status = calc_baud_rate_divisor(baudrate, &divisor); + if (status) { + err("%s - bad baud rate", __FUNCTION__); + return status; + } + + /* Enable access to divisor latch */ + data = mos7720_port->shadowLCR | UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); + + /* Write the divisor */ + data = ((unsigned char)(divisor & 0xff)); + send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); + + data = ((unsigned char)((divisor & 0xff00) >> 8)); + send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); + + /* Disable access to divisor latch */ + data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; + mos7720_port->shadowLCR = data; + send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); + + return status; +} + +/* + * change_port_settings + * This routine is called to set the UART on the device to match + * the specified new settings. + */ +static void change_port_settings(struct moschip_port *mos7720_port, + struct termios *old_termios) +{ + struct usb_serial_port *port; + struct usb_serial *serial; + struct tty_struct *tty; + int baud; + unsigned cflag; + unsigned iflag; + __u8 mask = 0xff; + __u8 lData; + __u8 lParity; + __u8 lStop; + int status; + int port_number; + char data; + + if (mos7720_port == NULL) + return ; + + port = mos7720_port->port; + serial = port->serial; + port_number = port->number - port->serial->minor; + + dbg("%s - port %d", __FUNCTION__, port->number); + + if (!mos7720_port->open) { + dbg("%s - port not opened", __FUNCTION__); + return; + } + + tty = mos7720_port->port->tty; + + if ((!tty) || (!tty->termios)) { + dbg("%s - no tty structures", __FUNCTION__); + return; + } + + dbg("%s: Entering ..........", __FUNCTION__); + + lData = UART_LCR_WLEN8; + lStop = 0x00; /* 1 stop bit */ + lParity = 0x00; /* No parity */ + + cflag = tty->termios->c_cflag; + iflag = tty->termios->c_iflag; + + /* Change the number of bits */ + switch (cflag & CSIZE) { + case CS5: + lData = UART_LCR_WLEN5; + mask = 0x1f; + break; + + case CS6: + lData = UART_LCR_WLEN6; + mask = 0x3f; + break; + + case CS7: + lData = UART_LCR_WLEN7; + mask = 0x7f; + break; + default: + case CS8: + lData = UART_LCR_WLEN8; + break; + } + + /* Change the Parity bit */ + if (cflag & PARENB) { + if (cflag & PARODD) { + lParity = UART_LCR_PARITY; + dbg("%s - parity = odd", __FUNCTION__); + } else { + lParity = (UART_LCR_EPAR | UART_LCR_PARITY); + dbg("%s - parity = even", __FUNCTION__); + } + + } else { + dbg("%s - parity = none", __FUNCTION__); + } + + if (cflag & CMSPAR) + lParity = lParity | 0x20; + + /* Change the Stop bit */ + if (cflag & CSTOPB) { + lStop = UART_LCR_STOP; + dbg("%s - stop bits = 2", __FUNCTION__); + } else { + lStop = 0x00; + dbg("%s - stop bits = 1", __FUNCTION__); + } + +#define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ +#define LCR_STOP_MASK 0x04 /* Mask for stop bits field */ +#define LCR_PAR_MASK 0x38 /* Mask for parity field */ + + /* Update the LCR with the correct value */ + mos7720_port->shadowLCR &= ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); + mos7720_port->shadowLCR |= (lData | lParity | lStop); + + + /* Disable Interrupts */ + data = 0x00; + send_mos_cmd(serial,MOS_WRITE,port->number - port->serial->minor, UART_IER, &data); + + data = 0x00; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); + + data = 0xcf; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); + + /* Send the updated LCR value to the mos7720 */ + data = mos7720_port->shadowLCR; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); + + data = 0x00b; + mos7720_port->shadowMCR = data; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + data = 0x00b; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); + + /* set up the MCR register and send it to the mos7720 */ + mos7720_port->shadowMCR = UART_MCR_OUT2; + if (cflag & CBAUD) + mos7720_port->shadowMCR |= (UART_MCR_DTR | UART_MCR_RTS); + + if (cflag & CRTSCTS) { + mos7720_port->shadowMCR |= (UART_MCR_XONANY); + + /* To set hardware flow control to the specified * + * serial port, in SP1/2_CONTROL_REG */ + if (port->number) { + data = 0x001; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, + 0x08, &data); + } else { + data = 0x002; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, + 0x08, &data); + } + } else { + mos7720_port->shadowMCR &= ~(UART_MCR_XONANY); + } + + data = mos7720_port->shadowMCR; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data); + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(tty); + if (!baud) { + /* pick a default, any default... */ + dbg("Picked default baud..."); + baud = 9600; + } + + if (baud >= 230400) { + set_higher_rates(mos7720_port, baud); + /* Enable Interrupts */ + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); + return; + } + + dbg("%s - baud rate = %d", __FUNCTION__, baud); + status = send_cmd_write_baud_rate(mos7720_port, baud); + + /* Enable Interrupts */ + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); + + if (port->read_urb->status != -EINPROGRESS) { + port->read_urb->dev = serial->dev; + + status = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (status) + dbg("usb_submit_urb(read bulk) failed, status = %d", + status); + } + return; +} + +/* + * mos7720_set_termios + * this function is called by the tty driver when it wants to change the + * termios structure. + */ +static void mos7720_set_termios(struct usb_serial_port *port, + struct termios *old_termios) +{ + int status; + unsigned int cflag; + struct usb_serial *serial; + struct moschip_port *mos7720_port; + struct tty_struct *tty; + + serial = port->serial; + + mos7720_port = usb_get_serial_port_data(port); + + if (mos7720_port == NULL) + return; + + tty = port->tty; + + if (!port->tty || !port->tty->termios) { + dbg("%s - no tty or termios", __FUNCTION__); + return; + } + + if (!mos7720_port->open) { + dbg("%s - port not opened", __FUNCTION__); + return; + } + + dbg("%s\n","setting termios - ASPIRE"); + + cflag = tty->termios->c_cflag; + + if (!cflag) { + printk("%s %s\n",__FUNCTION__,"cflag is NULL"); + return; + } + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(tty->termios->c_iflag) == + RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg("Nothing to change"); + return; + } + } + + dbg("%s - clfag %08x iflag %08x", __FUNCTION__, + tty->termios->c_cflag, + RELEVANT_IFLAG(tty->termios->c_iflag)); + + if (old_termios) + dbg("%s - old clfag %08x old iflag %08x", __FUNCTION__, + old_termios->c_cflag, + RELEVANT_IFLAG(old_termios->c_iflag)); + + dbg("%s - port %d", __FUNCTION__, port->number); + + /* change the port settings to the new ones specified */ + change_port_settings(mos7720_port, old_termios); + + if(!port->read_urb) { + dbg("%s","URB KILLED !!!!!\n"); + return; + } + + if(port->read_urb->status != -EINPROGRESS) { + port->read_urb->dev = serial->dev; + status = usb_submit_urb(port->read_urb, GFP_ATOMIC); + if (status) + dbg("usb_submit_urb(read bulk) failed, status = %d", + status); + } + return; +} + +/* + * get_lsr_info - get line status register info + * + * Purpose: Let user call ioctl() to get info when the UART physically + * is emptied. On bus types like RS485, the transmitter must + * release the bus after transmitting. This must be done when + * the transmit shift register is empty, not be done when the + * transmit holding register is empty. This functionality + * allows an RS485 driver to be written in user space. + */ +static int get_lsr_info(struct moschip_port *mos7720_port, + unsigned int __user *value) +{ + int count; + unsigned int result = 0; + + count = mos7720_chars_in_buffer(mos7720_port->port); + if (count == 0) { + dbg("%s -- Empty", __FUNCTION__); + result = TIOCSER_TEMT; + } + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +/* + * get_number_bytes_avail - get number of bytes available + * + * Purpose: Let user call ioctl to get the count of number of bytes available. + */ +static int get_number_bytes_avail(struct moschip_port *mos7720_port, + unsigned int __user *value) +{ + unsigned int result = 0; + struct tty_struct *tty = mos7720_port->port->tty; + + if (!tty) + return -ENOIOCTLCMD; + + result = tty->read_cnt; + + dbg("%s(%d) = %d", __FUNCTION__, mos7720_port->port->number, result); + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + + return -ENOIOCTLCMD; +} + +static int set_modem_info(struct moschip_port *mos7720_port, unsigned int cmd, + unsigned int __user *value) +{ + unsigned int mcr ; + unsigned int arg; + unsigned char data; + + struct usb_serial_port *port; + + if (mos7720_port == NULL) + return -1; + + port = (struct usb_serial_port*)mos7720_port->port; + mcr = mos7720_port->shadowMCR; + + if (copy_from_user(&arg, value, sizeof(int))) + return -EFAULT; + + switch (cmd) { + case TIOCMBIS: + if (arg & TIOCM_RTS) + mcr |= UART_MCR_RTS; + if (arg & TIOCM_DTR) + mcr |= UART_MCR_RTS; + if (arg & TIOCM_LOOP) + mcr |= UART_MCR_LOOP; + break; + + case TIOCMBIC: + if (arg & TIOCM_RTS) + mcr &= ~UART_MCR_RTS; + if (arg & TIOCM_DTR) + mcr &= ~UART_MCR_RTS; + if (arg & TIOCM_LOOP) + mcr &= ~UART_MCR_LOOP; + break; + + case TIOCMSET: + /* turn off the RTS and DTR and LOOPBACK + * and then only turn on what was asked to */ + mcr &= ~(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_LOOP); + mcr |= ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0); + mcr |= ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0); + mcr |= ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0); + break; + } + + mos7720_port->shadowMCR = mcr; + + data = mos7720_port->shadowMCR; + send_mos_cmd(port->serial, MOS_WRITE, + port->number - port->serial->minor, UART_MCR, &data); + + return 0; +} + +static int get_modem_info(struct moschip_port *mos7720_port, + unsigned int __user *value) +{ + unsigned int result = 0; + unsigned int msr = mos7720_port->shadowMSR; + unsigned int mcr = mos7720_port->shadowMCR; + + result = ((mcr & UART_MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ + | ((mcr & UART_MCR_RTS) ? TIOCM_RTS: 0) /* 0x004 */ + | ((msr & UART_MSR_CTS) ? TIOCM_CTS: 0) /* 0x020 */ + | ((msr & UART_MSR_DCD) ? TIOCM_CAR: 0) /* 0x040 */ + | ((msr & UART_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ + | ((msr & UART_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ + + + dbg("%s -- %x", __FUNCTION__, result); + + if (copy_to_user(value, &result, sizeof(int))) + return -EFAULT; + return 0; +} + +static int get_serial_info(struct moschip_port *mos7720_port, + struct serial_struct __user *retinfo) +{ + struct serial_struct tmp; + + if (!retinfo) + return -EFAULT; + + memset(&tmp, 0, sizeof(tmp)); + + tmp.type = PORT_16550A; + tmp.line = mos7720_port->port->serial->minor; + tmp.port = mos7720_port->port->number; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = NUM_URBS * URB_TRANSFER_BUFFER_SIZE; + tmp.baud_base = 9600; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; + + if (copy_to_user(retinfo, &tmp, sizeof(*retinfo))) + return -EFAULT; + return 0; +} + +static int mos7720_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct moschip_port *mos7720_port; + struct async_icount cnow; + struct async_icount cprev; + struct serial_icounter_struct icount; + + mos7720_port = usb_get_serial_port_data(port); + if (mos7720_port == NULL) + return -ENODEV; + + dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); + + switch (cmd) { + case TIOCINQ: + /* return number of bytes available */ + dbg("%s (%d) TIOCINQ", __FUNCTION__, port->number); + return get_number_bytes_avail(mos7720_port, + (unsigned int __user *)arg); + break; + + case TIOCSERGETLSR: + dbg("%s (%d) TIOCSERGETLSR", __FUNCTION__, port->number); + return get_lsr_info(mos7720_port, (unsigned int __user *)arg); + return 0; + + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__, + port->number); + return set_modem_info(mos7720_port, cmd, + (unsigned int __user *)arg); + + case TIOCMGET: + dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number); + return get_modem_info(mos7720_port, + (unsigned int __user *)arg); + + case TIOCGSERIAL: + dbg("%s (%d) TIOCGSERIAL", __FUNCTION__, port->number); + return get_serial_info(mos7720_port, + (struct serial_struct __user *)arg); + + case TIOCSSERIAL: + dbg("%s (%d) TIOCSSERIAL", __FUNCTION__, port->number); + break; + + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __FUNCTION__, port->number); + cprev = mos7720_port->icount; + while (1) { + if (signal_pending(current)) + return -ERESTARTSYS; + cnow = mos7720_port->icount; + if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && + cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) + return -EIO; /* no change => error */ + if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || + ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || + ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || + ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { + return 0; + } + cprev = cnow; + } + /* NOTREACHED */ + break; + + case TIOCGICOUNT: + cnow = mos7720_port->icount; + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __FUNCTION__, + port->number, icount.rx, icount.tx ); + if (copy_to_user((void __user *)arg, &icount, sizeof(icount))) + return -EFAULT; + return 0; + } + + return -ENOIOCTLCMD; +} + +static int mos7720_startup(struct usb_serial *serial) +{ + struct moschip_serial *mos7720_serial; + struct moschip_port *mos7720_port; + struct usb_device *dev; + int i; + char data; + + dbg("%s: Entering ..........", __FUNCTION__); + + if (!serial) { + dbg("Invalid Handler"); + return -ENODEV; + } + + dev = serial->dev; + + /* create our private serial structure */ + mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL); + if (mos7720_serial == NULL) { + err("%s - Out of memory", __FUNCTION__); + return -ENOMEM; + } + + usb_set_serial_data(serial, mos7720_serial); + + /* we set up the pointers to the endpoints in the mos7720_open * + * function, as the structures aren't created yet. */ + + /* set up port private structures */ + for (i = 0; i < serial->num_ports; ++i) { + mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); + if (mos7720_port == NULL) { + err("%s - Out of memory", __FUNCTION__); + usb_set_serial_data(serial, NULL); + kfree(mos7720_serial); + return -ENOMEM; + } + + /* Initialize all port interrupt end point to port 0 int + * endpoint. Our device has only one interrupt endpoint + * comman to all ports */ + serial->port[i]->interrupt_in_endpointAddress = serial->port[0]->interrupt_in_endpointAddress; + + mos7720_port->port = serial->port[i]; + usb_set_serial_port_data(serial->port[i], mos7720_port); + + dbg("port number is %d", serial->port[i]->number); + dbg("serial number is %d", serial->minor); + } + + + /* setting configuration feature to one */ + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + (__u8)0x03, 0x00,0x01,0x00, NULL, 0x00, 5*HZ); + + send_mos_cmd(serial,MOS_READ,0x00, UART_LSR, &data); // LSR For Port 1 + dbg("LSR:%x",data); + + send_mos_cmd(serial,MOS_READ,0x01, UART_LSR, &data); // LSR For Port 2 + dbg("LSR:%x",data); + + return 0; +} + +static void mos7720_shutdown(struct usb_serial *serial) +{ + int i; + + /* free private structure allocated for serial port */ + for (i=0; i < serial->num_ports; ++i) { + kfree(usb_get_serial_port_data(serial->port[i])); + usb_set_serial_port_data(serial->port[i], NULL); + } + + /* free private structure allocated for serial device */ + kfree(usb_get_serial_data(serial)); + usb_set_serial_data(serial, NULL); +} + +static struct usb_serial_driver moschip7720_2port_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "moschip7720", + }, + .description = "Moschip 2 port adapter", + .id_table = moschip_port_id_table, + .num_interrupt_in = 1, + .num_bulk_in = 2, + .num_bulk_out = 2, + .num_ports = 2, + .open = mos7720_open, + .close = mos7720_close, + .throttle = mos7720_throttle, + .unthrottle = mos7720_unthrottle, + .attach = mos7720_startup, + .shutdown = mos7720_shutdown, + .ioctl = mos7720_ioctl, + .set_termios = mos7720_set_termios, + .write = mos7720_write, + .write_room = mos7720_write_room, + .chars_in_buffer = mos7720_chars_in_buffer, + .break_ctl = mos7720_break, + .read_bulk_callback = mos7720_bulk_in_callback, +}; + +static struct usb_driver usb_driver = { + .name = "moschip7720", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = moschip_port_id_table, +}; + +static int __init moschip7720_init(void) +{ + int retval; + + dbg("%s: Entering ..........", __FUNCTION__); + + /* Register with the usb serial */ + retval = usb_serial_register(&moschip7720_2port_driver); + if (retval) + goto failed_port_device_register; + + info(DRIVER_DESC " " DRIVER_VERSION); + + /* Register with the usb */ + retval = usb_register(&usb_driver); + if (retval) + goto failed_usb_register; + + return 0; + +failed_usb_register: + usb_serial_deregister(&moschip7720_2port_driver); + +failed_port_device_register: + return retval; +} + +static void __exit moschip7720_exit(void) +{ + usb_deregister(&usb_driver); + usb_serial_deregister(&moschip7720_2port_driver); +} + +module_init(moschip7720_init); +module_exit(moschip7720_exit); + +/* Module information */ +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From a65dc301c7448a9a8d24bf1cbfe292541d1fa390 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 6 Oct 2006 00:09:29 +0200 Subject: USB: fix dereference in drivers/usb/misc/adutux.c in two of the error cases, dev is still NULL, and we dereference it. Spotted by coverity (cid#1428, 1429) Signed-off-by: Eric Sesterhenn Cc: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index aecd633fe9f6..af2934e016a7 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -370,7 +370,8 @@ static int adu_release(struct inode *inode, struct file *file) retval = adu_release_internal(dev); exit: - up(&dev->sem); + if (dev) + up(&dev->sem); dbg(2," %s : leave, return value %d", __FUNCTION__, retval); return retval; } -- cgit v1.2.3 From 1ff15e8efc1703eaae1eeec6fc09db6af1e4049f Mon Sep 17 00:00:00 2001 From: Tobias Lorenz Date: Sun, 8 Oct 2006 22:56:40 -0700 Subject: USB: Mitsumi USB FDD 061M: UNUSUAL_DEV multilun fix From: Tobias Lorenz Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0a846e4a101e..0093d9fd0234 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -55,7 +55,8 @@ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), -UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0100, +/* modified by Tobias Lorenz */ +UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0200, "Mitsumi", "USB FDD", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From c19ecd654209725444d1f47a4422e6f48846b53c Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 9 Oct 2006 01:16:24 +0200 Subject: USB: ftdi-elan.c: remove dead code The Coverity checker spotted this obviously dead code. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 37d1f4e90d5a..9b591b8b9369 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -513,8 +513,6 @@ static void ftdi_elan_respond_work(void *data) ftdi->disconnected += 1; } else if (retval == -ENODEV) { ftdi->disconnected += 1; - } else if (retval == -ENODEV) { - ftdi->disconnected += 1; } else if (retval == -EILSEQ) { ftdi->disconnected += 1; } else { -- cgit v1.2.3 From ad18027f4909c8fc107056460c97dbedb6635128 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 9 Oct 2006 01:16:32 +0200 Subject: USB: mos7840.c: fix a check-after-dereference This patch fixes an obvious check-after-dereference spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 021be39fe16e..5b71962d0351 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2413,11 +2413,12 @@ static int mos7840_ioctl(struct usb_serial_port *port, struct file *file, } mos7840_port = mos7840_get_port_private(port); - tty = mos7840_port->port->tty; if (mos7840_port == NULL) return -1; + tty = mos7840_port->port->tty; + dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd); switch (cmd) { -- cgit v1.2.3 From 3ccf25ce185d4798e66a91812a7622f7fe6987df Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 13 Oct 2006 09:59:17 -0400 Subject: USB: unusual_devs entry for Nokia 6234 This patch (as803) adds an unusual_devs entry for the Nokia 6234 mobile phone. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 0093d9fd0234..802f3a35c51d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -190,6 +190,13 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0370, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), +/* Reported by Alex Corcoles */ +UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, + "Nokia", + "6234", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64 ), + /* Reported by Olaf Hering from novell bug #105878 */ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, "SMSC", -- cgit v1.2.3 From 521b600b58376b7c85a7c615ee32fae185c20b16 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 10 Oct 2006 14:42:46 -0700 Subject: USB: fix usbatm tiny race ia64: drivers/usb/atm/usbatm.c: In function `usbatm_do_heavy_init': drivers/usb/atm/usbatm.c:1004: warning: implicit declaration of function `get_current' drivers/usb/atm/usbatm.c:1004: error: invalid type argument of `->' Signed-off-by: Duncan Sands Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/usbatm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index ab091fa4c86b..ec63b0ee0743 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -1001,7 +1001,7 @@ static int usbatm_do_heavy_init(void *arg) daemonize(instance->driver->driver_name); allow_signal(SIGTERM); - instance->thread_pid = get_current()->pid; + instance->thread_pid = current->pid; complete(&instance->thread_started); -- cgit v1.2.3 From c0fc0ee06f6c9ab37f53afc62b0d94a700fa7a97 Mon Sep 17 00:00:00 2001 From: Jan Mate Date: Tue, 10 Oct 2006 14:42:47 -0700 Subject: USB Storage: unusual_devs.h entry for Sony Ericsson P990i USB Storage: this patch adds support for Sony Ericsson P990i Signed-off-by: Jan Mate Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 802f3a35c51d..37ed8e0f2dc8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1306,6 +1306,13 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Jan Mate */ +UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, + "Sony Ericsson", + "P990i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. -- cgit v1.2.3 From 0e185b7922ac81516c5c4653dcf6aacbf6341e73 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 10 Oct 2006 14:42:50 -0700 Subject: USB: Memory leak in drivers/usb/serial/airprime.c the commit http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=5dda171202f94127e49c12daf780cdae1b4e668b added a memory leak. In case we cant allocate an urb, we dont free the buffer and leak it. Coverity id #1438 Signed-off-by: Eric Sesterhenn Acked-by: Andy Gay Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 392a5129af64..ba93c72cdba0 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -134,6 +134,7 @@ static int airprime_open(struct usb_serial_port *port, struct file *filp) } urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) { + kfree(buffer); dev_err(&port->dev, "%s - no more urbs?\n", __FUNCTION__); result = -ENOMEM; -- cgit v1.2.3 From 4550718f6c75c9abe8b987fa4c625fd041aa95a2 Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Tue, 10 Oct 2006 14:42:51 -0700 Subject: USB: input: extract() and implement() are bit field manipulation routines extract() and implement() have brain damaged attempts to handle 32-bit wide "fields". The problem is the index math in the original code didn't clear all the relevant bits. (offset >> 5) only compensated for 32-bit index. We need (offset >> 6) if we want to use 64-bit loads. But it was also wrong in that it tried to use quasi-aligned loads. Ie "report" was only incremented in multiples of 4 bytes and then the offset was masked off for values greater than 4 bytes. The right way is to pretend "report" points at a byte array. And offset is then only minor adjustment for < 8 bits of offset. "n" (field width) can then be as big as 24 (assuming 32-bit loads) since "offset" will never be bigger than 7. If someone needs either function to handle more than 24-bits, please document why - point at a specification or specific USB hid device - in comments in the code. extract/implement() are also an eyesore to read. Please banish whoever wrote it to read CodingStyle 3 times in a row to a classroom full of 1st graders armed with rubberbands. Or just flame them. Whatever. Globbing all the code together on two lines does NOT make it faster and is Just Wrong. I've tested this patch on j6000 (dual 750Mhz PA-RISC, 32-bit 2.6.12-rc5). Kyle McMartin tested on c3000 (up 400Mhz PA-RISC, same kernel). "p2-mate" (Peter De Schrijver?) tested on sb1250 (dual core Mips, broadcom "swarm" eval board). Signed-off-by: Grant Grundler Signed-off-by: Matthew Wilcox Cc: Vojtech Pavlik Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index a6738a83ff5b..feabda73a6f9 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -750,21 +750,31 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) } /* - * Extract/implement a data field from/to a report. + * Extract/implement a data field from/to a little endian report (bit array). */ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) { - report += (offset >> 5) << 2; offset &= 31; - return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); + u32 x; + + report += offset >> 3; /* adjust byte index */ + offset &= 8 - 1; + x = get_unaligned((u32 *) report); + x = le32_to_cpu(x); + x = (x >> offset) & ((1 << n) - 1); + return x; } static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) { - report += (offset >> 5) << 2; offset &= 31; - put_unaligned((get_unaligned((__le64*)report) - & cpu_to_le64(~((((__u64) 1 << n) - 1) << offset))) - | cpu_to_le64((__u64)value << offset), (__le64*)report); + u32 x; + + report += offset >> 3; + offset &= 8 - 1; + x = get_unaligned((u32 *)report); + x &= cpu_to_le32(~((((__u32) 1 << n) - 1) << offset)); + x |= cpu_to_le32(value << offset); + put_unaligned(x,(u32 *)report); } /* -- cgit v1.2.3 From deb8ee43a23d48116cb23eb8dd1de2348efb1e80 Mon Sep 17 00:00:00 2001 From: Dominic Cerquetti Date: Tue, 10 Oct 2006 14:42:48 -0700 Subject: USB: xpad: dance pad support Adds support for dance pads to the xpad driver. Dance pads require the d-pad to be mapped to four buttons instead of two axes, so that combinations of up/down and left/right can be hit simultaneously. Known dance pads are detected, and there is a module parameter added to default unknown xpad devices to map the d-pad to buttons if this is desired. (dpad_to_buttons). Minor modifications were made to port the changes in the original patch to a newer kernel version. This patch was originally from Dominic Cerquetti originally written for kernel 2.6.11.4, with minor modifications (API changes for USB, spelling fixes to the documentation added in the original patch) made to apply to the current kernel. I have modified Dominic's original patch per some suggestions from Dmitry Torokhov. (There was nothing in the patch format description about multiple From: lines, so I haven't added myself.) [akpm@osdl.org: cleanups] Signed-off-by: Adam Buchbinder Acked-by: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/input/xpad.txt | 115 +++++++++++++++++++++++++++-------- drivers/usb/input/xpad.c | 139 +++++++++++++++++++++++++++++-------------- 2 files changed, 186 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/Documentation/input/xpad.txt b/Documentation/input/xpad.txt index b9111a703ce0..5427bdf225ed 100644 --- a/Documentation/input/xpad.txt +++ b/Documentation/input/xpad.txt @@ -3,20 +3,37 @@ xpad - Linux USB driver for X-Box gamepads This is the very first release of a driver for X-Box gamepads. Basically, this was hacked away in just a few hours, so don't expect miracles. + In particular, there is currently NO support for the rumble pack. You won't find many ff-aware linux applications anyway. -0. Status ---------- +0. Notes +-------- + +Driver updated for kernel 2.6.17.11. (Based on a patch for 2.6.11.4.) -For now, this driver has only been tested on just one Linux-Box. -This one is running a 2.4.18 kernel with usb-uhci on an amd athlon 600. +The number of buttons/axes reported varies based on 3 things: +- if you are using a known controller +- if you are using a known dance pad +- if using an unknown device (one not listed below), what you set in the + module configuration for "Map D-PAD to buttons rather than axes for unknown + pads" (module option dpad_to_buttons) -The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) reports -8 axes and 10 buttons. +If you set dpad_to_buttons to 0 and you are using an unknown device (one +not listed below), the driver will map the directional pad to axes (X/Y), +if you said N it will map the d-pad to buttons, which is needed for dance +style games to function correctly. The default is Y. + +dpad_to_buttons has no effect for known pads. + +0.1 Normal Controllers +---------------------- +With a normal controller, the directional pad is mapped to its own X/Y axes. +The jstest-program from joystick-1.2.15 (jstest-version 2.1.0) will report 8 +axes and 10 buttons. -Alls 8 axes work, though they all have the same range (-32768..32767) +All 8 axes work, though they all have the same range (-32768..32767) and the zero-setting is not correct for the triggers (I don't know if that is some limitation of jstest, since the input device setup should be fine. I didn't have a look at jstest itself yet). @@ -30,16 +47,50 @@ in game functionality were OK. However, I find it rather difficult to play first person shooters with a pad. Your mileage may vary. +0.2 Xbox Dance Pads +------------------- +When using a known dance pad, jstest will report 6 axes and 14 buttons. + +For dance style pads (like the redoctane pad) several changes +have been made. The old driver would map the d-pad to axes, resulting +in the driver being unable to report when the user was pressing both +left+right or up+down, making DDR style games unplayable. + +Known dance pads automatically map the d-pad to buttons and will work +correctly out of the box. + +If your dance pad is recognized by the driver but is using axes instead +of buttons, see section 0.3 - Unknown Controllers + +I've tested this with Stepmania, and it works quite well. + + +0.3 Unkown Controllers +---------------------- +If you have an unkown xbox controller, it should work just fine with +the default settings. + +HOWEVER if you have an unknown dance pad not listed below, it will not +work UNLESS you set "dpad_to_buttons" to 1 in the module configuration. + +PLEASE if you have an unkown controller, email Dom with +a dump from /proc/bus/usb and a description of the pad (manufacturer, country, +whether it is a dance pad or normal controller) so that we can add your pad +to the list of supported devices, ensuring that it will work out of the +box in the future. + + 1. USB adapter -------------- Before you can actually use the driver, you need to get yourself an -adapter cable to connect the X-Box controller to your Linux-Box. +adapter cable to connect the X-Box controller to your Linux-Box. You +can buy these online fairly cheap, or build your own. -Such a cable is pretty easy to build. The Controller itself is a USB compound -device (a hub with three ports for two expansion slots and the controller -device) with the only difference in a nonstandard connector (5 pins vs. 4 on -standard USB connector). +Such a cable is pretty easy to build. The Controller itself is a USB +compound device (a hub with three ports for two expansion slots and +the controller device) with the only difference in a nonstandard connector +(5 pins vs. 4 on standard USB connector). You just need to solder a USB connector onto the cable and keep the yellow wire unconnected. The other pins have the same order on both @@ -51,36 +102,36 @@ original one. You can buy an extension cable and cut that instead. That way, you can still use the controller with your X-Box, if you have one ;) -2. driver installation +2. Driver Installation ---------------------- Once you have the adapter cable and the controller is connected, you need to load your USB subsystem and should cat /proc/bus/usb/devices. There should be an entry like the one at the end [4]. -Currently (as of version 0.0.4), the following three devices are included: +Currently (as of version 0.0.6), the following devices are included: original Microsoft XBOX controller (US), vendor=0x045e, product=0x0202 + smaller Microsoft XBOX controller (US), vendor=0x045e, product=0x0289 original Microsoft XBOX controller (Japan), vendor=0x045e, product=0x0285 InterAct PowerPad Pro (Germany), vendor=0x05fd, product=0x107a + RedOctane Xbox Dance Pad (US), vendor=0x0c12, product=0x8809 -If you have another controller that is not listed above and is not recognized -by the driver, please drop me a line with the appropriate info (that is, include -the name, vendor and product ID, as well as the country where you bought it; -sending the whole dump out of /proc/bus/usb/devices along would be even better). +The driver should work with xbox pads not listed above as well, however +you will need to do something extra for dance pads to work. -In theory, the driver should work with other controllers than mine -(InterAct PowerPad pro, bought in Germany) just fine, but I cannot test this -for I only have this one controller. +If you have a controller not listed above, see 0.3 - Unknown Controllers If you compiled and installed the driver, test the functionality: > modprobe xpad > modprobe joydev > jstest /dev/js0 -There should be a single line showing 18 inputs (8 axes, 10 buttons), and -it's values should change if you move the sticks and push the buttons. +If you're using a normal controller, there should be a single line showing +18 inputs (8 axes, 10 buttons), and its values should change if you move +the sticks and push the buttons. If you're using a dance pad, it should +show 20 inputs (6 axes, 14 buttons). -It works? Voila, your done ;) +It works? Voila, you're done ;) 3. Thanks @@ -111,6 +162,22 @@ I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=(none) E: Ad=81(I) Atr=03(Int.) MxPS= 32 Ivl= 10ms E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl= 10ms +5. /proc/bus/usb/devices - dump from Redoctane Xbox Dance Pad (US): + +T: Bus=01 Lev=02 Prnt=09 Port=00 Cnt=01 Dev#= 10 Spd=12 MxCh= 0 +D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1 +P: Vendor=0c12 ProdID=8809 Rev= 0.01 +S: Product=XBOX DDR +C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA +I: If#= 0 Alt= 0 #EPs= 2 Cls=58(unk. ) Sub=42 Prot=00 Driver=xpad +E: Ad=82(I) Atr=03(Int.) MxPS= 32 Ivl=4ms +E: Ad=02(O) Atr=03(Int.) MxPS= 32 Ivl=4ms + -- Marko Friedemann 2002-07-16 + - original doc + +Dominic Cerquetti +2005-03-19 + - added stuff for dance pads, new d-pad->axes mappings diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index cebb6c463bfb..6a12a943b938 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -1,8 +1,9 @@ /* - * X-Box gamepad - v0.0.5 + * X-Box gamepad - v0.0.6 * * Copyright (c) 2002 Marko Friedemann - * + * 2005 Dominic Cerquetti + * 2006 Adam Buchbinder * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,9 +31,10 @@ * - Greg Kroah-Hartman - usb-skeleton driver * * TODO: - * - fine tune axes + * - fine tune axes (especially trigger axes) * - fix "analog" buttons (reported as digital now) * - get rumble working + * - need USB IDs for other dance pads * * History: * @@ -57,25 +59,40 @@ #include #include #include +#include #include +#include #include #include -#define DRIVER_VERSION "v0.0.5" +#define DRIVER_VERSION "v0.0.6" #define DRIVER_AUTHOR "Marko Friedemann " #define DRIVER_DESC "X-Box pad driver" #define XPAD_PKT_LEN 32 +/* xbox d-pads should map to buttons, as is required for DDR pads + but we map them to axes when possible to simplify things */ +#define MAP_DPAD_TO_BUTTONS 0 +#define MAP_DPAD_TO_AXES 1 +#define MAP_DPAD_UNKNOWN -1 + +static int dpad_to_buttons; +module_param(dpad_to_buttons, bool, S_IRUGO); +MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); + static const struct xpad_device { u16 idVendor; u16 idProduct; char *name; + u8 dpad_mapping; } xpad_device[] = { - { 0x045e, 0x0202, "Microsoft X-Box pad (US)" }, - { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)" }, - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)" }, - { 0x0000, 0x0000, "X-Box pad" } + { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, + { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, + { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, + { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, + { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, + { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } }; static const signed short xpad_btn[] = { @@ -84,11 +101,23 @@ static const signed short xpad_btn[] = { -1 /* terminating entry */ }; +/* only used if MAP_DPAD_TO_BUTTONS */ +static const signed short xpad_btn_pad[] = { + BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ + BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ + -1 /* terminating entry */ +}; + static const signed short xpad_abs[] = { ABS_X, ABS_Y, /* left stick */ ABS_RX, ABS_RY, /* right stick */ ABS_Z, ABS_RZ, /* triggers left/right */ - ABS_HAT0X, ABS_HAT0Y, /* digital pad */ + -1 /* terminating entry */ +}; + +/* only used if MAP_DPAD_TO_AXES */ +static const signed short xpad_abs_pad[] = { + ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ -1 /* terminating entry */ }; @@ -100,14 +129,16 @@ static struct usb_device_id xpad_table [] = { MODULE_DEVICE_TABLE (usb, xpad_table); struct usb_xpad { - struct input_dev *dev; /* input device interface */ - struct usb_device *udev; /* usb device */ + struct input_dev *dev; /* input device interface */ + struct usb_device *udev; /* usb device */ - struct urb *irq_in; /* urb for interrupt in report */ - unsigned char *idata; /* input data */ + struct urb *irq_in; /* urb for interrupt in report */ + unsigned char *idata; /* input data */ dma_addr_t idata_dma; - char phys[65]; /* physical device path */ + char phys[65]; /* physical device path */ + + int dpad_mapping; /* map d-pad to buttons or to axes */ }; /* @@ -137,14 +168,21 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d input_report_abs(dev, ABS_RZ, data[11]); /* digital pad */ - input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); - input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); + if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { + input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); + input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); + } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { + input_report_key(dev, BTN_LEFT, data[2] & 0x04); + input_report_key(dev, BTN_RIGHT, data[2] & 0x08); + input_report_key(dev, BTN_0, data[2] & 0x01); // up + input_report_key(dev, BTN_1, data[2] & 0x02); // down + } /* start/back buttons and stick press left/right */ - input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); - input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); - input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); - input_report_key(dev, BTN_THUMBR, data[2] >> 7); + input_report_key(dev, BTN_START, data[2] & 0x10); + input_report_key(dev, BTN_BACK, data[2] & 0x20); + input_report_key(dev, BTN_THUMBL, data[2] & 0x40); + input_report_key(dev, BTN_THUMBR, data[2] & 0x80); /* "analog" buttons A, B, X, Y */ input_report_key(dev, BTN_A, data[4]); @@ -206,6 +244,28 @@ static void xpad_close (struct input_dev *dev) usb_kill_urb(xpad->irq_in); } +static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) +{ + set_bit(abs, input_dev->absbit); + + switch (abs) { + case ABS_X: + case ABS_Y: + case ABS_RX: + case ABS_RY: /* the two sticks */ + input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); + break; + case ABS_Z: + case ABS_RZ: /* the triggers */ + input_set_abs_params(input_dev, abs, 0, 255, 0, 0); + break; + case ABS_HAT0X: + case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ + input_set_abs_params(input_dev, abs, -1, 1, 0, 0); + break; + } +} + static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev (intf); @@ -235,6 +295,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id goto fail2; xpad->udev = udev; + xpad->dpad_mapping = xpad_device[i].dpad_mapping; + if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) + xpad->dpad_mapping = dpad_to_buttons; xpad->dev = input_dev; usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); @@ -249,32 +312,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + /* set up buttons */ for (i = 0; xpad_btn[i] >= 0; i++) set_bit(xpad_btn[i], input_dev->keybit); + if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) + for (i = 0; xpad_btn_pad[i] >= 0; i++) + set_bit(xpad_btn_pad[i], input_dev->keybit); - for (i = 0; xpad_abs[i] >= 0; i++) { - - signed short t = xpad_abs[i]; - - set_bit(t, input_dev->absbit); - - switch (t) { - case ABS_X: - case ABS_Y: - case ABS_RX: - case ABS_RY: /* the two sticks */ - input_set_abs_params(input_dev, t, -32768, 32767, 16, 128); - break; - case ABS_Z: - case ABS_RZ: /* the triggers */ - input_set_abs_params(input_dev, t, 0, 255, 0, 0); - break; - case ABS_HAT0X: - case ABS_HAT0Y: /* the d-pad */ - input_set_abs_params(input_dev, t, -1, 1, 0, 0); - break; - } - } + /* set up axes */ + for (i = 0; xpad_abs[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs[i]); + if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) + for (i = 0; xpad_abs_pad[i] >= 0; i++) + xpad_set_up_abs(input_dev, xpad_abs_pad[i]); ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; usb_fill_int_urb(xpad->irq_in, udev, @@ -305,7 +355,8 @@ static void xpad_disconnect(struct usb_interface *intf) usb_kill_urb(xpad->irq_in); input_unregister_device(xpad->dev); usb_free_urb(xpad->irq_in); - usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, xpad->idata, xpad->idata_dma); + usb_buffer_free(interface_to_usbdev(intf), XPAD_PKT_LEN, + xpad->idata, xpad->idata_dma); kfree(xpad); } } -- cgit v1.2.3 From 9ab99c8c513313c1c5931bdbd27dcc4bc7a3b7cd Mon Sep 17 00:00:00 2001 From: matthieu castet Date: Wed, 11 Oct 2006 14:20:56 -0700 Subject: UEAGLE: fix ueagle-atm Oops The array of attribute passed to sysfs_create_group() must be NULL-terminated. The sysfs entries are created before the start of the modem state machine to avoid to stop it in case of errors in sysfs creation. Also {destroy,create}_fs_entries are removed as they do nothing. Signed-off-by: Laurent Riffard Signed-off-by: Matthieu CASTET Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 570529842231..f6b9f7e1f716 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -1648,16 +1648,12 @@ static struct attribute *attrs[] = { &dev_attr_stat_usunc.attr, &dev_attr_stat_dsunc.attr, &dev_attr_stat_firmid.attr, + NULL, }; static struct attribute_group attr_grp = { .attrs = attrs, }; -static int create_fs_entries(struct usb_interface *intf) -{ - return sysfs_create_group(&intf->dev.kobj, &attr_grp); -} - static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, const struct usb_device_id *id) { @@ -1717,31 +1713,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf, } } + ret = sysfs_create_group(&intf->dev.kobj, &attr_grp); + if (ret < 0) + goto error; + ret = uea_boot(sc); - if (ret < 0) { - kfree(sc); - return ret; - } + if (ret < 0) + goto error; - ret = create_fs_entries(intf); - if (ret) { - uea_stop(sc); - kfree(sc); - return ret; - } return 0; -} - -static void destroy_fs_entries(struct usb_interface *intf) -{ - sysfs_remove_group(&intf->dev.kobj, &attr_grp); +error: + kfree(sc); + return ret; } static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf) { struct uea_softc *sc = usbatm->driver_data; - destroy_fs_entries(intf); + sysfs_remove_group(&intf->dev.kobj, &attr_grp); uea_stop(sc); kfree(sc); } -- cgit v1.2.3 From 5dfb5f1d060a6f7dfddb78dc59f9e4d299088cc1 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Wed, 11 Oct 2006 23:40:22 +0200 Subject: usbtouchscreen: fix data reading for ITM touchscreens ITM devices seem to report only garbage when not touched. update usbtouchscreen to do data reading like itmtouch. also fix wrong mask on pressure bits. Signed-off-by: Daniel Ritz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/usbtouchscreen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index f26c1cd1129f..2902742895ad 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -256,10 +256,10 @@ static int itm_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *pr { *x = ((pkt[0] & 0x1F) << 7) | (pkt[3] & 0x7F); *y = ((pkt[1] & 0x1F) << 7) | (pkt[4] & 0x7F); - *press = ((pkt[2] & 0x1F) << 7) | (pkt[5] & 0x7F); + *press = ((pkt[2] & 0x01) << 7) | (pkt[5] & 0x7F); *touch = ~pkt[7] & 0x20; - return 1; + return *touch; } #endif -- cgit v1.2.3 From b3899dacafb10347b1b7a9f589b6c70cf8f08a3e Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 11 Oct 2006 21:50:24 -0400 Subject: USB/gadget/net2280: handle sysfs errors Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/net2280.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index d954daa8e9e0..7cfe0e5cf670 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2044,8 +2044,10 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) return retval; } - device_create_file (&dev->pdev->dev, &dev_attr_function); - device_create_file (&dev->pdev->dev, &dev_attr_queues); + retval = device_create_file (&dev->pdev->dev, &dev_attr_function); + if (retval) goto err_unbind; + retval = device_create_file (&dev->pdev->dev, &dev_attr_queues); + if (retval) goto err_func; /* ... then enable host detection and ep0; and we're ready * for set_configuration as well as eventual disconnect. @@ -2060,6 +2062,14 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) /* pci writes may still be posted */ return 0; + +err_func: + device_remove_file (&dev->pdev->dev, &dev_attr_function); +err_unbind: + driver->unbind (&dev->gadget); + dev->gadget.dev.driver = NULL; + dev->driver = NULL; + return retval; } EXPORT_SYMBOL (usb_gadget_register_driver); @@ -2974,8 +2984,10 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) : "disabled"); the_controller = dev; - device_register (&dev->gadget.dev); - device_create_file (&pdev->dev, &dev_attr_registers); + retval = device_register (&dev->gadget.dev); + if (retval) goto done; + retval = device_create_file (&pdev->dev, &dev_attr_registers); + if (retval) goto done; return 0; -- cgit v1.2.3 From 61926b975d83aa6c0124b5b0ce40c08579e6cc98 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 12 Oct 2006 22:09:56 +0100 Subject: USB-SERIAL:cp2101 Add new device ID This patch adds device ID 0xEA61. This is another factory default ID used by SILabs. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 486c7411b9a7..bbf6532c26e5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -65,6 +65,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ { } /* Terminating Entry */ }; -- cgit v1.2.3 From 5c09d144ff94706c2a5df292329ad83a27380173 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 13 Oct 2006 15:57:58 -0700 Subject: USB: ftdi_sio whitespace fixes Whitespace fixups for drivers/usb/serial/ftdi_sio.c ... removing end-of-line whitespace, and space-before-tab. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 254 +++++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d3dc1a15ec6c..bd76b4c11fcc 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1,16 +1,16 @@ /* * USB FTDI SIO driver * - * Copyright (C) 1999 - 2001 - * Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 1999 - 2001 + * Greg Kroah-Hartman (greg@kroah.com) * Bill Ryder (bryder@sgi.com) * Copyright (C) 2002 * Kuba Ober (kuba@mareimbrium.org) * - * 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 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. * * See Documentation/usb/usb-serial.txt for more information on using this driver * @@ -32,7 +32,7 @@ * Changed full name of USB-UIRT device to avoid "/" character. * Added FTDI's alternate PID (0x6006) for FT232/245 devices. * Added PID for "ELV USB Module UO100" from Stefan Frings. - * + * * (21/Oct/2003) Ian Abbott * Renamed some VID/PID macros for Matrix Orbital and Perle Systems * devices. Removed Matrix Orbital and Perle Systems devices from the @@ -69,7 +69,7 @@ * does not incure any measurable overhead. This also relies on the fact * that we have proper reference counting logic for urbs. I nicked this * from Greg KH's Visor driver. - * + * * (23/Jun/2003) Ian Abbott * Reduced flip buffer pushes and corrected a data length test in * ftdi_read_bulk_callback. @@ -77,7 +77,7 @@ * * (21/Jun/2003) Erik Nygren * Added support for Home Electronics Tira-1 IR transceiver using FT232BM chip. - * See . Only operates properly + * See . Only operates properly * at 100000 and RTS-CTS, so set custom divisor mode on startup. * Also force the Tira-1 and USB-UIRT to only use their custom baud rates. * @@ -137,17 +137,17 @@ * (17/Feb/2003) Bill Ryder * Added write urb buffer pool on a per device basis * Added more checking for open file on callbacks (fixed OOPS) - * Added CrystalFontz 632 and 634 PIDs + * Added CrystalFontz 632 and 634 PIDs * (thanx to CrystalFontz for the sample devices - they flushed out * some driver bugs) * Minor debugging message changes * Added throttle, unthrottle and chars_in_buffer functions * Fixed FTDI_SIO (the original device) bug * Fixed some shutdown handling - * - * - * - * + * + * + * + * * (07/Jun/2002) Kuba Ober * Changed FTDI_SIO_BASE_BAUD_TO_DIVISOR macro into ftdi_baud_to_divisor * function. It was getting too complex. @@ -158,7 +158,7 @@ * * (25/Jul/2002) Bill Ryder inserted Dmitri's TIOCMIWAIT patch * Not tested by me but it doesn't break anything I use. - * + * * (04/Jan/2002) Kuba Ober * Implemented 38400 baudrate kludge, where it can be substituted with other * values. That's the only way to set custom baudrates. @@ -179,7 +179,7 @@ * (the previous version caused panics) * Removed port iteration code since the device only has one I/O port and it * was wrong anyway. - * + * * (31/May/2001) gkh * Switched from using spinlock to a semaphore, which fixes lots of problems. * @@ -188,16 +188,16 @@ * Cleaned up comments for 8U232 * Added parity, framing and overrun error handling * Added receive break handling. - * + * * (04/08/2001) gb * Identify version on module load. - * + * * (18/March/2001) Bill Ryder * (Not released) * Added send break handling. (requires kernel patch too) * Fixed 8U232AM hardware RTS/CTS etc status reporting. * Added flipbuf fix copied from generic device - * + * * (12/3/2000) Bill Ryder * Added support for 8U232AM device. * Moved PID and VIDs into header file only. @@ -211,14 +211,14 @@ * Cleaned up comments. Removed multiple PID/VID definitions. * Factorised cts/dtr code * Made use of __FUNCTION__ in dbg's - * + * * (11/01/2000) Adam J. Richter * usb_device_id table support - * + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. - * + * * (09/11/2000) gkh * Removed DEBUG #ifdefs with call to usb_serial_debug_data * @@ -226,11 +226,11 @@ * Added module_init and module_exit functions to handle the fact that this * driver is a loadable module now. * - * (04/04/2000) Bill Ryder + * (04/04/2000) Bill Ryder * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are * handled elsewhere in the tty io driver chain). * - * (03/30/2000) Bill Ryder + * (03/30/2000) Bill Ryder * Implemented lots of ioctls * Fixed a race condition in write * Changed some dbg's to errs @@ -444,13 +444,13 @@ static struct usb_device_id id_table_combined [] = { /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS300PC_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_FHZ1300PC_PID) }, */ /* { USB_DEVICE(FTDI_VID, FTDI_ELV_WS500_PID) }, */ - { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, - { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, - { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, - { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, - { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, + { USB_DEVICE(FTDI_VID, LINX_SDMUSBQSS_PID) }, + { USB_DEVICE(FTDI_VID, LINX_MASTERDEVEL2_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_0_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_1_PID) }, + { USB_DEVICE(FTDI_VID, LINX_FUTURE_2_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) }, { USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) }, { USB_DEVICE(INTREPID_VID, INTREPID_VALUECAN_PID) }, { USB_DEVICE(INTREPID_VID, INTREPID_NEOVI_PID) }, @@ -522,7 +522,7 @@ static struct usb_driver ftdi_driver = { .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table_combined, - .no_dynamic_id = 1, + .no_dynamic_id = 1, }; static const char *ftdi_chip_name[] = { @@ -548,13 +548,13 @@ struct ftdi_private { int custom_divisor; /* custom_divisor kludge, this is for baud_base (different from what goes to the chip!) */ __u16 last_set_data_urb_value ; /* the last data state set - needed for doing a break */ - int write_offset; /* This is the offset in the usb data block to write the serial data - + int write_offset; /* This is the offset in the usb data block to write the serial data - * it is different between devices */ int flags; /* some ASYNC_xxxx flags are supported */ unsigned long last_dtr_rts; /* saved modem control outputs */ wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ - char prev_status, diff_status; /* Used for TIOCMIWAIT */ + char prev_status, diff_status; /* Used for TIOCMIWAIT */ __u8 rx_flags; /* receive state flags (throttling) */ spinlock_t rx_lock; /* spinlock for receive state */ struct work_struct rx_work; @@ -721,7 +721,7 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned urb_value |= FTDI_SIO_SET_RTS_HIGH; rv = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST, FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, urb_value, priv->interface, buf, 0, WDR_TIMEOUT); @@ -768,7 +768,7 @@ static int change_speed(struct usb_serial_port *port) if (priv->interface) { /* FT2232C */ urb_index = (__u16)((urb_index << 8) | priv->interface); } - + rv = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_BAUDRATE_REQUEST, @@ -827,7 +827,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) /* 3. Convert baudrate to device-specific divisor */ - if (!baud) baud = 9600; + if (!baud) baud = 9600; switch(priv->chip_type) { case SIO: /* SIO chip */ switch(baud) { @@ -843,7 +843,7 @@ static __u32 get_ftdi_divisor(struct usb_serial_port * port) case 115200: div_value = ftdi_sio_b115200; break; } /* baud */ if (div_value == 0) { - dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); + dbg("%s - Baudrate (%d) requested is not supported", __FUNCTION__, baud); div_value = ftdi_sio_b9600; div_okay = 0; } @@ -925,7 +925,7 @@ static int set_serial_info(struct usb_serial_port * port, struct serial_struct _ /* Make the changes - these are privileged changes! */ priv->flags = ((priv->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); + (new_serial.flags & ASYNC_FLAGS)); priv->custom_divisor = new_serial.custom_divisor; port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; @@ -950,7 +950,7 @@ check_and_exit: (old_priv.custom_divisor != priv->custom_divisor))) { change_speed(port); } - + return (0); } /* set_serial_info */ @@ -1022,18 +1022,18 @@ static ssize_t show_latency_timer(struct device *dev, struct device_attribute *a struct usb_device *udev; unsigned short latency = 0; int rv = 0; - + udev = to_usb_device(dev); - + dbg("%s",__FUNCTION__); - + rv = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), FTDI_SIO_GET_LATENCY_TIMER_REQUEST, FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, - 0, priv->interface, + 0, priv->interface, (char*) &latency, 1, WDR_TIMEOUT); - + if (rv < 0) { dev_err(dev, "Unable to read latency timer: %i", rv); return -EIO; @@ -1051,23 +1051,23 @@ static ssize_t store_latency_timer(struct device *dev, struct device_attribute * char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); int rv = 0; - + udev = to_usb_device(dev); - + dbg("%s: setting latency timer = %i", __FUNCTION__, v); - + rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), FTDI_SIO_SET_LATENCY_TIMER_REQUEST, FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, - v, priv->interface, + v, priv->interface, buf, 0, WDR_TIMEOUT); - + if (rv < 0) { dev_err(dev, "Unable to write latency timer: %i", rv); return -EIO; } - + return count; } @@ -1082,23 +1082,23 @@ static ssize_t store_event_char(struct device *dev, struct device_attribute *att char buf[1]; int v = simple_strtoul(valbuf, NULL, 10); int rv = 0; - + udev = to_usb_device(dev); - + dbg("%s: setting event char = %i", __FUNCTION__, v); - + rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), FTDI_SIO_SET_EVENT_CHAR_REQUEST, FTDI_SIO_SET_EVENT_CHAR_REQUEST_TYPE, - v, priv->interface, + v, priv->interface, buf, 0, WDR_TIMEOUT); - + if (rv < 0) { dbg("Unable to write event character: %i", rv); return -EIO; } - + return count; } @@ -1135,11 +1135,11 @@ static void remove_sysfs_attrs(struct usb_serial *serial) struct ftdi_private *priv; struct usb_device *udev; - dbg("%s",__FUNCTION__); + dbg("%s",__FUNCTION__); priv = usb_get_serial_port_data(serial->port[0]); udev = serial->dev; - + /* XXX see create_sysfs_attrs */ if (priv->chip_type != SIO) { device_remove_file(&udev->dev, &dev_attr_event_char); @@ -1147,7 +1147,7 @@ static void remove_sysfs_attrs(struct usb_serial *serial) device_remove_file(&udev->dev, &dev_attr_latency_timer); } } - + } /* @@ -1258,7 +1258,7 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) } /* ftdi_HE_TIRA1_setup */ -/* ftdi_shutdown is called from usbserial:usb_serial_disconnect +/* ftdi_shutdown is called from usbserial:usb_serial_disconnect * it is called when the usb device is disconnected * * usbserial:usb_serial_disconnect @@ -1269,16 +1269,16 @@ static void ftdi_HE_TIRA1_setup (struct usb_serial *serial) static void ftdi_shutdown (struct usb_serial *serial) { /* ftdi_shutdown */ - + struct usb_serial_port *port = serial->port[0]; struct ftdi_private *priv = usb_get_serial_port_data(port); dbg("%s", __FUNCTION__); remove_sysfs_attrs(serial); - - /* all open ports are closed at this point - * (by usbserial.c:__serial_close, which calls ftdi_close) + + /* all open ports are closed at this point + * (by usbserial.c:__serial_close, which calls ftdi_close) */ if (priv) { @@ -1293,7 +1293,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) struct usb_device *dev = port->serial->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); unsigned long flags; - + int result = 0; char buf[1]; /* Needed for the usb_control_msg I think */ @@ -1312,8 +1312,8 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, - FTDI_SIO_RESET_SIO, + FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, + FTDI_SIO_RESET_SIO, priv->interface, buf, 0, WDR_TIMEOUT); /* Termios defaults are set by usb_serial_init. We don't change @@ -1350,12 +1350,12 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp) -/* +/* * usbserial:__serial_close only calls ftdi_close if the point is open * * This only gets called when it is the last close - * - * + * + * */ static void ftdi_close (struct usb_serial_port *port, struct file *filp) @@ -1368,14 +1368,14 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) if (c_cflag & HUPCL){ /* Disable flow control */ - if (usb_control_msg(port->serial->dev, + if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("error from flowcontrol urb"); - } + } /* drop RTS and DTR */ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); @@ -1384,14 +1384,14 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) /* cancel any scheduled reading */ cancel_delayed_work(&priv->rx_work); flush_scheduled_work(); - + /* shutdown our bulk read */ if (port->read_urb) usb_kill_urb(port->read_urb); } /* ftdi_close */ - + /* The SIO requires the first byte to have: * B0 1 * B1 0 @@ -1423,7 +1423,7 @@ static int ftdi_write (struct usb_serial_port *port, return 0; } spin_unlock_irqrestore(&priv->tx_lock, flags); - + data_offset = priv->write_offset; dbg("data_offset set to %d",data_offset); @@ -1462,7 +1462,7 @@ static int ftdi_write (struct usb_serial_port *port, user_pktsz = todo; } /* Write the control byte at the front of the packet*/ - *first_byte = 1 | ((user_pktsz) << 2); + *first_byte = 1 | ((user_pktsz) << 2); /* Copy data for packet */ memcpy (first_byte + data_offset, current_position, user_pktsz); @@ -1479,7 +1479,7 @@ static int ftdi_write (struct usb_serial_port *port, usb_serial_debug_data(debug, &port->dev, __FUNCTION__, transfer_size, buffer); /* fill the buffer and send it */ - usb_fill_bulk_urb(urb, port->serial->dev, + usb_fill_bulk_urb(urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), buffer, transfer_size, ftdi_write_bulk_callback, port); @@ -1520,7 +1520,7 @@ static void ftdi_write_bulk_callback (struct urb *urb) kfree (urb->transfer_buffer); dbg("%s - port %d", __FUNCTION__, port->number); - + if (urb->status) { dbg("nonzero write bulk status received: %d", urb->status); return; @@ -1651,7 +1651,7 @@ static void ftdi_process_read (void *param) struct tty_struct *tty; struct ftdi_private *priv; char error_flag; - unsigned char *data; + unsigned char *data; int i; int result; @@ -1759,7 +1759,7 @@ static void ftdi_process_read (void *param) } if (length > 0) { for (i = 2; i < length+2; i++) { - /* Note that the error flag is duplicated for + /* Note that the error flag is duplicated for every character received since we don't know which character it applied to */ tty_insert_flip_char(tty, data[packet_offset+i], error_flag); @@ -1773,7 +1773,7 @@ static void ftdi_process_read (void *param) This doesn't work well since the application receives a never ending stream of bad data - even though new data hasn't been sent. Therefore I (bill) have taken this out. - However - this might make sense for framing errors and so on + However - this might make sense for framing errors and so on so I am leaving the code in for now. */ else { @@ -1827,7 +1827,7 @@ static void ftdi_process_read (void *param) /* if the port is closed stop trying to read */ if (port->open_count > 0){ /* Continue trying to always read */ - usb_fill_bulk_urb(port->read_urb, port->serial->dev, + usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, ftdi_read_bulk_callback, port); @@ -1844,9 +1844,9 @@ static void ftdi_process_read (void *param) static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) { struct ftdi_private *priv = usb_get_serial_port_data(port); - __u16 urb_value = 0; + __u16 urb_value = 0; char buf[1]; - + /* break_state = -1 to turn on break, and 0 to turn off break */ /* see drivers/char/tty_io.c to see it used */ /* last_set_data_urb_value NEVER has the break bit set in it */ @@ -1854,20 +1854,20 @@ static void ftdi_break_ctl( struct usb_serial_port *port, int break_state ) if (break_state) { urb_value = priv->last_set_data_urb_value | FTDI_SIO_SET_BREAK; } else { - urb_value = priv->last_set_data_urb_value; + urb_value = priv->last_set_data_urb_value; } - + if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), - FTDI_SIO_SET_DATA_REQUEST, + FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("%s FAILED to enable/disable break state (state was %d)", __FUNCTION__,break_state); - } + } dbg("%s break state is %d - urb is %d", __FUNCTION__,break_state, urb_value); - + } @@ -1883,12 +1883,12 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ struct ftdi_private *priv = usb_get_serial_port_data(port); __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ - + // Added for xon/xoff support unsigned int iflag = port->tty->termios->c_iflag; unsigned char vstop; unsigned char vstart; - + dbg("%s", __FUNCTION__); /* Force baud rate if this device requires it, unless it is set to B0. */ @@ -1906,20 +1906,20 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ cflag = port->tty->termios->c_cflag; - /* FIXME -For this cut I don't care if the line is really changing or - not - so just do the change regardless - should be able to + /* FIXME -For this cut I don't care if the line is really changing or + not - so just do the change regardless - should be able to compare old_termios and tty->termios */ - /* NOTE These routines can get interrupted by - ftdi_sio_read_bulk_callback - need to examine what this + /* NOTE These routines can get interrupted by + ftdi_sio_read_bulk_callback - need to examine what this means - don't see any problems yet */ - + /* Set number of data bits, parity, stop bits */ - + urb_value = 0; urb_value |= (cflag & CSTOPB ? FTDI_SIO_SET_DATA_STOP_BITS_2 : FTDI_SIO_SET_DATA_STOP_BITS_1); - urb_value |= (cflag & PARENB ? - (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : + urb_value |= (cflag & PARENB ? + (cflag & PARODD ? FTDI_SIO_SET_DATA_PARITY_ODD : FTDI_SIO_SET_DATA_PARITY_EVEN) : FTDI_SIO_SET_DATA_PARITY_NONE); if (cflag & CSIZE) { @@ -1936,25 +1936,25 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ /* This is needed by the break command since it uses the same command - but is * or'ed with this value */ priv->last_set_data_urb_value = urb_value; - + if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - FTDI_SIO_SET_DATA_REQUEST, + FTDI_SIO_SET_DATA_REQUEST, FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, buf, 0, WDR_SHORT_TIMEOUT) < 0) { err("%s FAILED to set databits/stopbits/parity", __FUNCTION__); - } + } /* Now do the baudrate */ if ((cflag & CBAUD) == B0 ) { /* Disable flow control */ if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, priv->interface, + 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("%s error from disable flowcontrol urb", __FUNCTION__); - } + } /* Drop RTS and DTR */ clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } else { @@ -1972,16 +1972,16 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ if (cflag & CRTSCTS) { dbg("%s Setting to CRTSCTS flow control", __FUNCTION__); - if (usb_control_msg(dev, + if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to set to rts/cts flow control"); - } - - } else { + } + + } else { /* * Xon/Xoff code * @@ -2011,16 +2011,16 @@ static void ftdi_set_termios (struct usb_serial_port *port, struct termios *old_ /* else clause to only run if cfag ! CRTSCTS and iflag ! XOFF */ /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ dbg("%s Turning off hardware flow control", __FUNCTION__); - if (usb_control_msg(dev, + if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, priv->interface, + 0, priv->interface, buf, 0, WDR_TIMEOUT) < 0) { err("urb failed to clear flow control"); - } + } } - + } return; } /* ftdi_termios */ @@ -2036,11 +2036,11 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) switch (priv->chip_type) { case SIO: /* Request the status from the device */ - if ((ret = usb_control_msg(port->serial->dev, + if ((ret = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, + 0, 0, buf, 1, WDR_TIMEOUT)) < 0 ) { err("%s Could not get modem status of device - err: %d", __FUNCTION__, ret); @@ -2052,11 +2052,11 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) case FT2232C: /* the 8U232AM returns a two byte value (the sio is a 1 byte value) - in the same format as the data returned from the in point */ - if ((ret = usb_control_msg(port->serial->dev, + if ((ret = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST, FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, priv->interface, + 0, priv->interface, buf, 2, WDR_TIMEOUT)) < 0 ) { err("%s Could not get modem status of device - err: %d", __FUNCTION__, ret); @@ -2067,12 +2067,12 @@ static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file) return -EFAULT; break; } - + return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | (buf[0] & FTDI_SIO_CTS_MASK ? TIOCM_CTS : 0) | (buf[0] & FTDI_SIO_RI_MASK ? TIOCM_RI : 0) | (buf[0] & FTDI_SIO_RLSD_MASK ? TIOCM_CD : 0) | - priv->last_dtr_rts; + priv->last_dtr_rts; } static int ftdi_tiocmset(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear) @@ -2138,11 +2138,11 @@ static int ftdi_ioctl (struct usb_serial_port *port, struct file * file, unsigne break; default: break; - + } - /* This is not necessarily an error - turns out the higher layers will do + /* This is not necessarily an error - turns out the higher layers will do * some ioctls itself (see comment above) */ dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __FUNCTION__, cmd); @@ -2199,7 +2199,7 @@ static int __init ftdi_init (void) if (retval) goto failed_sio_register; retval = usb_register(&ftdi_driver); - if (retval) + if (retval) goto failed_usb_register; info(DRIVER_VERSION ":" DRIVER_DESC); -- cgit v1.2.3 From 033a3fb980b041c5b1c865d3e9dce9217d1dc94b Mon Sep 17 00:00:00 2001 From: Kevin Lloyd Date: Fri, 13 Oct 2006 23:53:21 -0700 Subject: USB: Sierra Wireless driver update The largest feature in this patch is that it adds significant throughput increase to the Sierra driver and adds support for modem status line control (e.g. the DTR line). This patch also updates the current sierra.c driver so that it supports both 3-port Sierra devices and 1-port legacy devices and removes Sierra's references in other related files (Kconfig and airprime.c). Signed-off-by: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 3 +- drivers/usb/serial/airprime.c | 5 - drivers/usb/serial/sierra.c | 729 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 699 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 8ca6d3f01e85..9a6ec1b5e3d5 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -537,8 +537,7 @@ config USB_SERIAL_OPTION The USB bus on these cards is not accessible externally. Supported devices include (some of?) those made by: - Option, Huawei, Audiovox, Sierra Wireless, Novatel Wireless, or - Anydata. + Option, Huawei, Audiovox, Novatel Wireless, or Anydata. To compile this driver as a module, choose M here: the module will be called option. diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index ba93c72cdba0..7f5d546da39a 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -18,11 +18,6 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ - { USB_DEVICE(0x0f3d, 0x0112) }, /* AirPrime CDMA Wireless PC Card */ - { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ - { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ - { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless Aircard 580 */ - { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ { }, diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index d29638daa987..39799d21b855 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -1,21 +1,59 @@ /* - * Sierra Wireless CDMA Wireless Serial USB driver - * - * Current Copy modified by: Kevin Lloyd - * Original Copyright (C) 2005-2006 Greg Kroah-Hartman - * - * 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. - */ + USB Driver for Sierra Wireless + + Copyright (C) 2006 Kevin Lloyd + + IMPORTANT DISCLAIMER: This driver is not commercially supported by + Sierra Wireless. Use at your own risk. + + This driver is free software; you can redistribute it and/or modify + it under the terms of Version 2 of the GNU General Public License as + published by the Free Software Foundation. + + Portions based on the option driver by Matthias Urlichs + Whom based his on the Keyspan driver by Hugh Blemings + + History: +*/ + +#define DRIVER_VERSION "v.1.0.5" +#define DRIVER_AUTHOR "Kevin Lloyd " +#define DRIVER_DESC "USB Driver for Sierra Wireless USB modems" #include -#include +#include +#include #include +#include #include #include #include +/* Function prototypes */ +static int sierra_open(struct usb_serial_port *port, struct file *filp); +static void sierra_close(struct usb_serial_port *port, struct file *filp); +static int sierra_startup(struct usb_serial *serial); +static void sierra_shutdown(struct usb_serial *serial); +static void sierra_rx_throttle(struct usb_serial_port *port); +static void sierra_rx_unthrottle(struct usb_serial_port *port); +static int sierra_write_room(struct usb_serial_port *port); + +static void sierra_instat_callback(struct urb *urb); + +static int sierra_write(struct usb_serial_port *port, + const unsigned char *buf, int count); + +static int sierra_chars_in_buffer(struct usb_serial_port *port); +static int sierra_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg); +static void sierra_set_termios(struct usb_serial_port *port, + struct termios *old); +static void sierra_break_ctl(struct usb_serial_port *port, int break_state); +static int sierra_tiocmget(struct usb_serial_port *port, struct file *file); +static int sierra_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear); +static int sierra_send_setup(struct usb_serial_port *port); + static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ @@ -25,51 +63,680 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ - /* Following devices are supported in the airprime.c driver */ - /* { USB_DEVICE(0x1199, 0x0112) }, */ /* Sierra Wireless AirCard 580 */ - /* { USB_DEVICE(0x0F3D, 0x0112) }, */ /* AirPrime/Sierra PC 5220 */ + + { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ + { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */ + { } +}; + +static struct usb_device_id id_table_1port [] = { + { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ + { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */ { } }; + +static struct usb_device_id id_table_3port [] = { + { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ + { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ + { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ + { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ + { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ + { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ + { } +}; + + MODULE_DEVICE_TABLE(usb, id_table); static struct usb_driver sierra_driver = { - .name = "sierra_wireless", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, + .name = "sierra", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 3, +}; + + +//static struct usb_serial_driver *sierra_device; + +static struct usb_serial_driver sierra_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "sierra1", + }, + .description = "Sierra USB modem (1 port)", + .id_table = id_table_1port, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = sierra_open, + .close = sierra_close, + .write = sierra_write, + .write_room = sierra_write_room, + .chars_in_buffer = sierra_chars_in_buffer, + .throttle = sierra_rx_throttle, + .unthrottle = sierra_rx_unthrottle, + .ioctl = sierra_ioctl, + .set_termios = sierra_set_termios, + .break_ctl = sierra_break_ctl, + .tiocmget = sierra_tiocmget, + .tiocmset = sierra_tiocmset, + .attach = sierra_startup, + .shutdown = sierra_shutdown, + .read_int_callback = sierra_instat_callback, }; -static struct usb_serial_driver sierra_device = { +static struct usb_serial_driver sierra_3port_device = { .driver = { - .owner = THIS_MODULE, - .name = "Sierra_Wireless", + .owner = THIS_MODULE, + .name = "sierra3", }, - .id_table = id_table, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = NUM_DONT_CARE, - .num_bulk_out = NUM_DONT_CARE, - .num_ports = 3, + .description = "Sierra USB modem (3 port)", + .id_table = id_table_3port, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 3, + .num_bulk_out = 3, + .num_ports = 3, + .open = sierra_open, + .close = sierra_close, + .write = sierra_write, + .write_room = sierra_write_room, + .chars_in_buffer = sierra_chars_in_buffer, + .throttle = sierra_rx_throttle, + .unthrottle = sierra_rx_unthrottle, + .ioctl = sierra_ioctl, + .set_termios = sierra_set_termios, + .break_ctl = sierra_break_ctl, + .tiocmget = sierra_tiocmget, + .tiocmset = sierra_tiocmset, + .attach = sierra_startup, + .shutdown = sierra_shutdown, + .read_int_callback = sierra_instat_callback, }; +#ifdef CONFIG_USB_DEBUG +static int debug; +#else +#define debug 0 +#endif + +/* per port private data */ + +#define N_IN_URB 4 +#define N_OUT_URB 1 +#define IN_BUFLEN 4096 +#define OUT_BUFLEN 128 + +struct sierra_port_private { + /* Input endpoints and buffer for this port */ + struct urb *in_urbs[N_IN_URB]; + char in_buffer[N_IN_URB][IN_BUFLEN]; + /* Output endpoints and buffer for this port */ + struct urb *out_urbs[N_OUT_URB]; + char out_buffer[N_OUT_URB][OUT_BUFLEN]; + + /* Settings for the port */ + int rts_state; /* Handshaking pins (outputs) */ + int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; + + unsigned long tx_start_time[N_OUT_URB]; +}; + +/* Functions used by new usb-serial code. */ static int __init sierra_init(void) { int retval; - - retval = usb_serial_register(&sierra_device); + retval = usb_serial_register(&sierra_1port_device); + if (retval) + goto failed_1port_device_register; + retval = usb_serial_register(&sierra_3port_device); if (retval) - return retval; + goto failed_3port_device_register; + + retval = usb_register(&sierra_driver); if (retval) - usb_serial_deregister(&sierra_device); + goto failed_driver_register; + + info(DRIVER_DESC ": " DRIVER_VERSION); + + return 0; + +failed_driver_register: + usb_serial_deregister(&sierra_3port_device); +failed_3port_device_register: + usb_serial_deregister(&sierra_1port_device); +failed_1port_device_register: return retval; } static void __exit sierra_exit(void) { - usb_deregister(&sierra_driver); - usb_serial_deregister(&sierra_device); + usb_deregister (&sierra_driver); + usb_serial_deregister(&sierra_1port_device); + usb_serial_deregister(&sierra_3port_device); } module_init(sierra_init); module_exit(sierra_exit); + +static void sierra_rx_throttle(struct usb_serial_port *port) +{ + dbg("%s", __FUNCTION__); +} + +static void sierra_rx_unthrottle(struct usb_serial_port *port) +{ + dbg("%s", __FUNCTION__); +} + +static void sierra_break_ctl(struct usb_serial_port *port, int break_state) +{ + /* Unfortunately, I don't know how to send a break */ + dbg("%s", __FUNCTION__); +} + +static void sierra_set_termios(struct usb_serial_port *port, + struct termios *old_termios) +{ + dbg("%s", __FUNCTION__); + + sierra_send_setup(port); +} + +static int sierra_tiocmget(struct usb_serial_port *port, struct file *file) +{ + unsigned int value; + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + + value = ((portdata->rts_state) ? TIOCM_RTS : 0) | + ((portdata->dtr_state) ? TIOCM_DTR : 0) | + ((portdata->cts_state) ? TIOCM_CTS : 0) | + ((portdata->dsr_state) ? TIOCM_DSR : 0) | + ((portdata->dcd_state) ? TIOCM_CAR : 0) | + ((portdata->ri_state) ? TIOCM_RNG : 0); + + return value; +} + +static int sierra_tiocmset(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear) +{ + struct sierra_port_private *portdata; + + portdata = usb_get_serial_port_data(port); + + if (set & TIOCM_RTS) + portdata->rts_state = 1; + if (set & TIOCM_DTR) + portdata->dtr_state = 1; + + if (clear & TIOCM_RTS) + portdata->rts_state = 0; + if (clear & TIOCM_DTR) + portdata->dtr_state = 0; + return sierra_send_setup(port); +} + +static int sierra_ioctl(struct usb_serial_port *port, struct file *file, + unsigned int cmd, unsigned long arg) +{ + return -ENOIOCTLCMD; +} + +/* Write */ +static int sierra_write(struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct sierra_port_private *portdata; + int i; + int left, todo; + struct urb *this_urb = NULL; /* spurious */ + int err; + + portdata = usb_get_serial_port_data(port); + + dbg("%s: write (%d chars)", __FUNCTION__, count); + + i = 0; + left = count; + for (i=0; left > 0 && i < N_OUT_URB; i++) { + todo = left; + if (todo > OUT_BUFLEN) + todo = OUT_BUFLEN; + + this_urb = portdata->out_urbs[i]; + if (this_urb->status == -EINPROGRESS) { + if (time_before(jiffies, + portdata->tx_start_time[i] + 10 * HZ)) + continue; + usb_unlink_urb(this_urb); + continue; + } + if (this_urb->status != 0) + dbg("usb_write %p failed (err=%d)", + this_urb, this_urb->status); + + dbg("%s: endpoint %d buf %d", __FUNCTION__, + usb_pipeendpoint(this_urb->pipe), i); + + /* send the data */ + memcpy (this_urb->transfer_buffer, buf, todo); + this_urb->transfer_buffer_length = todo; + + this_urb->dev = port->serial->dev; + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err) { + dbg("usb_submit_urb %p (write bulk) failed " + "(%d, has %d)", this_urb, + err, this_urb->status); + continue; + } + portdata->tx_start_time[i] = jiffies; + buf += todo; + left -= todo; + } + + count -= left; + dbg("%s: wrote (did %d)", __FUNCTION__, count); + return count; +} + +static void sierra_indat_callback(struct urb *urb) +{ + int err; + int endpoint; + struct usb_serial_port *port; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + + dbg("%s: %p", __FUNCTION__, urb); + + endpoint = usb_pipeendpoint(urb->pipe); + port = (struct usb_serial_port *) urb->context; + + if (urb->status) { + dbg("%s: nonzero status: %d on endpoint %02x.", + __FUNCTION__, urb->status, endpoint); + } else { + tty = port->tty; + if (urb->actual_length) { + tty_buffer_request_room(tty, urb->actual_length); + tty_insert_flip_string(tty, data, urb->actual_length); + tty_flip_buffer_push(tty); + } else { + dbg("%s: empty read urb received", __FUNCTION__); + } + + /* Resubmit urb so we continue receiving */ + if (port->open_count && urb->status != -ESHUTDOWN) { + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) + printk(KERN_ERR "%s: resubmit read urb failed. " + "(%d)", __FUNCTION__, err); + } + } + return; +} + +static void sierra_outdat_callback(struct urb *urb) +{ + struct usb_serial_port *port; + + dbg("%s", __FUNCTION__); + + port = (struct usb_serial_port *) urb->context; + + usb_serial_port_softint(port); +} + +static void sierra_instat_callback(struct urb *urb) +{ + int err; + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + struct sierra_port_private *portdata = usb_get_serial_port_data(port); + struct usb_serial *serial = port->serial; + + dbg("%s", __FUNCTION__); + dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata); + + if (urb->status == 0) { + struct usb_ctrlrequest *req_pkt = + (struct usb_ctrlrequest *)urb->transfer_buffer; + + if (!req_pkt) { + dbg("%s: NULL req_pkt\n", __FUNCTION__); + return; + } + if ((req_pkt->bRequestType == 0xA1) && + (req_pkt->bRequest == 0x20)) { + int old_dcd_state; + unsigned char signals = *((unsigned char *) + urb->transfer_buffer + + sizeof(struct usb_ctrlrequest)); + + dbg("%s: signal x%x", __FUNCTION__, signals); + + old_dcd_state = portdata->dcd_state; + portdata->cts_state = 1; + portdata->dcd_state = ((signals & 0x01) ? 1 : 0); + portdata->dsr_state = ((signals & 0x02) ? 1 : 0); + portdata->ri_state = ((signals & 0x08) ? 1 : 0); + + if (port->tty && !C_CLOCAL(port->tty) && + old_dcd_state && !portdata->dcd_state) + tty_hangup(port->tty); + } else { + dbg("%s: type %x req %x", __FUNCTION__, + req_pkt->bRequestType,req_pkt->bRequest); + } + } else + dbg("%s: error %d", __FUNCTION__, urb->status); + + /* Resubmit urb so we continue receiving IRQ data */ + if (urb->status != -ESHUTDOWN) { + urb->dev = serial->dev; + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) + dbg("%s: resubmit intr urb failed. (%d)", + __FUNCTION__, err); + } +} + +static int sierra_write_room(struct usb_serial_port *port) +{ + struct sierra_port_private *portdata; + int i; + int data_len = 0; + struct urb *this_urb; + + portdata = usb_get_serial_port_data(port); + + for (i=0; i < N_OUT_URB; i++) { + this_urb = portdata->out_urbs[i]; + if (this_urb && this_urb->status != -EINPROGRESS) + data_len += OUT_BUFLEN; + } + + dbg("%s: %d", __FUNCTION__, data_len); + return data_len; +} + +static int sierra_chars_in_buffer(struct usb_serial_port *port) +{ + struct sierra_port_private *portdata; + int i; + int data_len = 0; + struct urb *this_urb; + + portdata = usb_get_serial_port_data(port); + + for (i=0; i < N_OUT_URB; i++) { + this_urb = portdata->out_urbs[i]; + if (this_urb && this_urb->status == -EINPROGRESS) + data_len += this_urb->transfer_buffer_length; + } + dbg("%s: %d", __FUNCTION__, data_len); + return data_len; +} + +static int sierra_open(struct usb_serial_port *port, struct file *filp) +{ + struct sierra_port_private *portdata; + struct usb_serial *serial = port->serial; + int i, err; + struct urb *urb; + + portdata = usb_get_serial_port_data(port); + + dbg("%s", __FUNCTION__); + + /* Set some sane defaults */ + portdata->rts_state = 1; + portdata->dtr_state = 1; + + /* Reset low level data toggle and start reading from endpoints */ + for (i = 0; i < N_IN_URB; i++) { + urb = portdata->in_urbs[i]; + if (! urb) + continue; + if (urb->dev != serial->dev) { + dbg("%s: dev %p != %p", __FUNCTION__, + urb->dev, serial->dev); + continue; + } + + /* + * make sure endpoint data toggle is synchronized with the + * device + */ + usb_clear_halt(urb->dev, urb->pipe); + + err = usb_submit_urb(urb, GFP_KERNEL); + if (err) { + dbg("%s: submit urb %d failed (%d) %d", + __FUNCTION__, i, err, + urb->transfer_buffer_length); + } + } + + /* Reset low level data toggle on out endpoints */ + for (i = 0; i < N_OUT_URB; i++) { + urb = portdata->out_urbs[i]; + if (! urb) + continue; + urb->dev = serial->dev; + /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), + usb_pipeout(urb->pipe), 0); */ + } + + port->tty->low_latency = 1; + + sierra_send_setup(port); + + return (0); +} + +static inline void stop_urb(struct urb *urb) +{ + if (urb && urb->status == -EINPROGRESS) + usb_kill_urb(urb); +} + +static void sierra_close(struct usb_serial_port *port, struct file *filp) +{ + int i; + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + + dbg("%s", __FUNCTION__); + portdata = usb_get_serial_port_data(port); + + portdata->rts_state = 0; + portdata->dtr_state = 0; + + if (serial->dev) { + sierra_send_setup(port); + + /* Stop reading/writing urbs */ + for (i = 0; i < N_IN_URB; i++) + stop_urb(portdata->in_urbs[i]); + for (i = 0; i < N_OUT_URB; i++) + stop_urb(portdata->out_urbs[i]); + } + port->tty = NULL; +} + +/* Helper functions used by sierra_setup_urbs */ +static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, + int dir, void *ctx, char *buf, int len, + void (*callback)(struct urb *)) +{ + struct urb *urb; + + if (endpoint == -1) + return NULL; /* endpoint not needed */ + + urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ + if (urb == NULL) { + dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint); + return NULL; + } + + /* Fill URB using supplied data. */ + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, endpoint) | dir, + buf, len, callback, ctx); + + return urb; +} + +/* Setup urbs */ +static void sierra_setup_urbs(struct usb_serial *serial) +{ + int i,j; + struct usb_serial_port *port; + struct sierra_port_private *portdata; + + dbg("%s", __FUNCTION__); + + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + + /* Do indat endpoints first */ + for (j = 0; j < N_IN_URB; ++j) { + portdata->in_urbs[j] = sierra_setup_urb (serial, + port->bulk_in_endpointAddress, USB_DIR_IN, port, + portdata->in_buffer[j], IN_BUFLEN, sierra_indat_callback); + } + + /* outdat endpoints */ + for (j = 0; j < N_OUT_URB; ++j) { + portdata->out_urbs[j] = sierra_setup_urb (serial, + port->bulk_out_endpointAddress, USB_DIR_OUT, port, + portdata->out_buffer[j], OUT_BUFLEN, sierra_outdat_callback); + } + } +} + +static int sierra_send_setup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; + + dbg("%s", __FUNCTION__); + + portdata = usb_get_serial_port_data(port); + + if (port->tty) { + int val = 0; + if (portdata->dtr_state) + val |= 0x01; + if (portdata->rts_state) + val |= 0x02; + + return usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); + } + + return 0; +} + +static int sierra_startup(struct usb_serial *serial) +{ + int i, err; + struct usb_serial_port *port; + struct sierra_port_private *portdata; + + dbg("%s", __FUNCTION__); + + /* Now setup per port private data */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) { + dbg("%s: kmalloc for sierra_port_private (%d) failed!.", + __FUNCTION__, i); + return (1); + } + + usb_set_serial_port_data(port, portdata); + + if (! port->interrupt_in_urb) + continue; + err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (err) + dbg("%s: submit irq_in urb failed %d", + __FUNCTION__, err); + } + + sierra_setup_urbs(serial); + + return (0); +} + +static void sierra_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct sierra_port_private *portdata; + + dbg("%s", __FUNCTION__); + + /* Stop reading/writing urbs */ + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + for (j = 0; j < N_IN_URB; j++) + stop_urb(portdata->in_urbs[j]); + for (j = 0; j < N_OUT_URB; j++) + stop_urb(portdata->out_urbs[j]); + } + + /* Now free them */ + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + + for (j = 0; j < N_IN_URB; j++) { + if (portdata->in_urbs[j]) { + usb_free_urb(portdata->in_urbs[j]); + portdata->in_urbs[j] = NULL; + } + } + for (j = 0; j < N_OUT_URB; j++) { + if (portdata->out_urbs[j]) { + usb_free_urb(portdata->out_urbs[j]); + portdata->out_urbs[j] = NULL; + } + } + } + + /* Now free per port private data */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + kfree(usb_get_serial_port_data(port)); + } +} + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); + +#ifdef CONFIG_USB_DEBUG +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug messages"); +#endif + -- cgit v1.2.3 From 964ee1deb3eac802902cd758ddb94b6a95c77987 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Oct 2006 10:17:58 -0700 Subject: USB: cleanup sierra wireless driver a bit This saves over 30 lines and fixes a warning from sparse and allows debugging to work dynamically like all other usb-serial drivers. Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 269 +++++++++++++++++++------------------------- 1 file changed, 118 insertions(+), 151 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 39799d21b855..6bdb11717e53 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -29,30 +29,6 @@ #include #include -/* Function prototypes */ -static int sierra_open(struct usb_serial_port *port, struct file *filp); -static void sierra_close(struct usb_serial_port *port, struct file *filp); -static int sierra_startup(struct usb_serial *serial); -static void sierra_shutdown(struct usb_serial *serial); -static void sierra_rx_throttle(struct usb_serial_port *port); -static void sierra_rx_unthrottle(struct usb_serial_port *port); -static int sierra_write_room(struct usb_serial_port *port); - -static void sierra_instat_callback(struct urb *urb); - -static int sierra_write(struct usb_serial_port *port, - const unsigned char *buf, int count); - -static int sierra_chars_in_buffer(struct usb_serial_port *port); -static int sierra_ioctl(struct usb_serial_port *port, struct file *file, - unsigned int cmd, unsigned long arg); -static void sierra_set_termios(struct usb_serial_port *port, - struct termios *old); -static void sierra_break_ctl(struct usb_serial_port *port, int break_state); -static int sierra_tiocmget(struct usb_serial_port *port, struct file *file); -static int sierra_tiocmset(struct usb_serial_port *port, struct file *file, - unsigned int set, unsigned int clear); -static int sierra_send_setup(struct usb_serial_port *port); static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ @@ -68,6 +44,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x0F3D, 0x0112) }, /* AirPrime/Sierra PC 5220 */ { } }; +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_device_id id_table_1port [] = { { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ @@ -87,88 +64,22 @@ static struct usb_device_id id_table_3port [] = { { } }; - -MODULE_DEVICE_TABLE(usb, id_table); - static struct usb_driver sierra_driver = { .name = "sierra", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, - .no_dynamic_id = 3, + .no_dynamic_id = 1, }; -//static struct usb_serial_driver *sierra_device; - -static struct usb_serial_driver sierra_1port_device = { - .driver = { - .owner = THIS_MODULE, - .name = "sierra1", - }, - .description = "Sierra USB modem (1 port)", - .id_table = id_table_1port, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = 1, - .num_bulk_out = 1, - .num_ports = 1, - .open = sierra_open, - .close = sierra_close, - .write = sierra_write, - .write_room = sierra_write_room, - .chars_in_buffer = sierra_chars_in_buffer, - .throttle = sierra_rx_throttle, - .unthrottle = sierra_rx_unthrottle, - .ioctl = sierra_ioctl, - .set_termios = sierra_set_termios, - .break_ctl = sierra_break_ctl, - .tiocmget = sierra_tiocmget, - .tiocmset = sierra_tiocmset, - .attach = sierra_startup, - .shutdown = sierra_shutdown, - .read_int_callback = sierra_instat_callback, -}; - -static struct usb_serial_driver sierra_3port_device = { - .driver = { - .owner = THIS_MODULE, - .name = "sierra3", - }, - .description = "Sierra USB modem (3 port)", - .id_table = id_table_3port, - .num_interrupt_in = NUM_DONT_CARE, - .num_bulk_in = 3, - .num_bulk_out = 3, - .num_ports = 3, - .open = sierra_open, - .close = sierra_close, - .write = sierra_write, - .write_room = sierra_write_room, - .chars_in_buffer = sierra_chars_in_buffer, - .throttle = sierra_rx_throttle, - .unthrottle = sierra_rx_unthrottle, - .ioctl = sierra_ioctl, - .set_termios = sierra_set_termios, - .break_ctl = sierra_break_ctl, - .tiocmget = sierra_tiocmget, - .tiocmset = sierra_tiocmset, - .attach = sierra_startup, - .shutdown = sierra_shutdown, - .read_int_callback = sierra_instat_callback, -}; - -#ifdef CONFIG_USB_DEBUG static int debug; -#else -#define debug 0 -#endif /* per port private data */ - -#define N_IN_URB 4 -#define N_OUT_URB 1 -#define IN_BUFLEN 4096 -#define OUT_BUFLEN 128 +#define N_IN_URB 4 +#define N_OUT_URB 1 +#define IN_BUFLEN 4096 +#define OUT_BUFLEN 128 struct sierra_port_private { /* Input endpoints and buffer for this port */ @@ -189,44 +100,30 @@ struct sierra_port_private { unsigned long tx_start_time[N_OUT_URB]; }; -/* Functions used by new usb-serial code. */ -static int __init sierra_init(void) +static int sierra_send_setup(struct usb_serial_port *port) { - int retval; - retval = usb_serial_register(&sierra_1port_device); - if (retval) - goto failed_1port_device_register; - retval = usb_serial_register(&sierra_3port_device); - if (retval) - goto failed_3port_device_register; - + struct usb_serial *serial = port->serial; + struct sierra_port_private *portdata; - retval = usb_register(&sierra_driver); - if (retval) - goto failed_driver_register; + dbg("%s", __FUNCTION__); - info(DRIVER_DESC ": " DRIVER_VERSION); + portdata = usb_get_serial_port_data(port); - return 0; + if (port->tty) { + int val = 0; + if (portdata->dtr_state) + val |= 0x01; + if (portdata->rts_state) + val |= 0x02; -failed_driver_register: - usb_serial_deregister(&sierra_3port_device); -failed_3port_device_register: - usb_serial_deregister(&sierra_1port_device); -failed_1port_device_register: - return retval; -} + return usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); + } -static void __exit sierra_exit(void) -{ - usb_deregister (&sierra_driver); - usb_serial_deregister(&sierra_1port_device); - usb_serial_deregister(&sierra_3port_device); + return 0; } -module_init(sierra_init); -module_exit(sierra_exit); - static void sierra_rx_throttle(struct usb_serial_port *port) { dbg("%s", __FUNCTION__); @@ -578,8 +475,8 @@ static void sierra_close(struct usb_serial_port *port, struct file *filp) /* Helper functions used by sierra_setup_urbs */ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, - int dir, void *ctx, char *buf, int len, - void (*callback)(struct urb *)) + int dir, void *ctx, char *buf, int len, + usb_complete_t callback) { struct urb *urb; @@ -629,30 +526,6 @@ static void sierra_setup_urbs(struct usb_serial *serial) } } -static int sierra_send_setup(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - struct sierra_port_private *portdata; - - dbg("%s", __FUNCTION__); - - portdata = usb_get_serial_port_data(port); - - if (port->tty) { - int val = 0; - if (portdata->dtr_state) - val |= 0x01; - if (portdata->rts_state) - val |= 0x02; - - return usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT); - } - - return 0; -} - static int sierra_startup(struct usb_serial *serial) { int i, err; @@ -730,6 +603,100 @@ static void sierra_shutdown(struct usb_serial *serial) } } +static struct usb_serial_driver sierra_1port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "sierra1", + }, + .description = "Sierra USB modem (1 port)", + .id_table = id_table_1port, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 1, + .num_bulk_out = 1, + .num_ports = 1, + .open = sierra_open, + .close = sierra_close, + .write = sierra_write, + .write_room = sierra_write_room, + .chars_in_buffer = sierra_chars_in_buffer, + .throttle = sierra_rx_throttle, + .unthrottle = sierra_rx_unthrottle, + .ioctl = sierra_ioctl, + .set_termios = sierra_set_termios, + .break_ctl = sierra_break_ctl, + .tiocmget = sierra_tiocmget, + .tiocmset = sierra_tiocmset, + .attach = sierra_startup, + .shutdown = sierra_shutdown, + .read_int_callback = sierra_instat_callback, +}; + +static struct usb_serial_driver sierra_3port_device = { + .driver = { + .owner = THIS_MODULE, + .name = "sierra3", + }, + .description = "Sierra USB modem (3 port)", + .id_table = id_table_3port, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = 3, + .num_bulk_out = 3, + .num_ports = 3, + .open = sierra_open, + .close = sierra_close, + .write = sierra_write, + .write_room = sierra_write_room, + .chars_in_buffer = sierra_chars_in_buffer, + .throttle = sierra_rx_throttle, + .unthrottle = sierra_rx_unthrottle, + .ioctl = sierra_ioctl, + .set_termios = sierra_set_termios, + .break_ctl = sierra_break_ctl, + .tiocmget = sierra_tiocmget, + .tiocmset = sierra_tiocmset, + .attach = sierra_startup, + .shutdown = sierra_shutdown, + .read_int_callback = sierra_instat_callback, +}; + +/* Functions used by new usb-serial code. */ +static int __init sierra_init(void) +{ + int retval; + retval = usb_serial_register(&sierra_1port_device); + if (retval) + goto failed_1port_device_register; + retval = usb_serial_register(&sierra_3port_device); + if (retval) + goto failed_3port_device_register; + + + retval = usb_register(&sierra_driver); + if (retval) + goto failed_driver_register; + + info(DRIVER_DESC ": " DRIVER_VERSION); + + return 0; + +failed_driver_register: + usb_serial_deregister(&sierra_3port_device); +failed_3port_device_register: + usb_serial_deregister(&sierra_1port_device); +failed_1port_device_register: + return retval; +} + +static void __exit sierra_exit(void) +{ + usb_deregister (&sierra_driver); + usb_serial_deregister(&sierra_1port_device); + usb_serial_deregister(&sierra_3port_device); +} + +module_init(sierra_init); +module_exit(sierra_exit); + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); -- cgit v1.2.3 From ab352c2687a4361aec06a184ddb20deb1e5091eb Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Tue, 17 Oct 2006 00:09:00 +0200 Subject: USB: Add device id for Sierra Wireless MC8755 Adds the device id used by the UMTS cards in Lenovo X60s notebooks sold in Europe. Signed-off-by: Jan Luebbe Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 6bdb11717e53..ea16572d19f8 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -37,6 +37,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ -- cgit v1.2.3 From 9950421c1e90d08d52ef47df1fcebe6078b04af3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 17 Oct 2006 18:03:33 -0700 Subject: Fix USB gadget net2280.c compile It would fail the compile due to the newly added error checking testing a bad macro for a "return value" unless USB_GADGET_DEBUG_FILES was enabled. Pointed out by Stephen Hemminger. Acked-by: Stephen Hemminger Signed-off-by: Linus Torvalds --- drivers/usb/gadget/net2280.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 7cfe0e5cf670..3acc896a5d4c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1774,8 +1774,8 @@ static DEVICE_ATTR (queues, S_IRUGO, show_queues, NULL); #else -#define device_create_file(a,b) do {} while (0) -#define device_remove_file device_create_file +#define device_create_file(a,b) (0) +#define device_remove_file(a,b) do { } while (0) #endif -- cgit v1.2.3 From b48194bf0dc0f8e2b617fab10df885513fbb3bad Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Tue, 17 Oct 2006 19:11:31 -0700 Subject: [SPARC]: Fix some section mismatch warnings in sparc drivers. Signed-off-by: Ben Collins Signed-off-by: David S. Miller --- drivers/net/myri_code.h | 8 ++++---- drivers/net/myri_sbus.c | 4 ++-- drivers/net/sunbmac.c | 2 +- drivers/scsi/qlogicpti.c | 2 +- drivers/scsi/qlogicpti_asm.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h index e21ec9b2c706..ba7b8652c501 100644 --- a/drivers/net/myri_code.h +++ b/drivers/net/myri_code.h @@ -1,8 +1,8 @@ /* This is the Myrinet MCP code for LANai4.x */ /* Generated by cat $MYRI_HOME/lib/lanai/mcp4.dat > myri_code4.h */ -static unsigned int lanai4_code_off = 0x0000; /* half-word offset */ -static unsigned char lanai4_code[76256] __initdata = { +static unsigned int __devinitdata lanai4_code_off = 0x0000; /* half-word offset */ +static unsigned char __devinitdata lanai4_code[76256] = { 0xF2,0x0E, 0xFE,0x00, 0xC2,0x90, 0x00,0x00, 0x07,0x88, 0x00,0x08, 0xE0,0x01, 0x01,0x4C, 0x97,0x93, 0xFF,0xFC, 0xE0,0x00, 0x00,0x14, 0x00,0x00, 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x92,0x93, @@ -4774,8 +4774,8 @@ static unsigned char lanai4_code[76256] __initdata = { /* This is the LANai data */ -static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */ -static unsigned char lanai4_data[20472] __initdata; +static unsigned int __devinitdata lanai4_data_off = 0x94F0; /* half-word offset */ +static unsigned char __devinitdata lanai4_data[20472]; #ifdef SYMBOL_DEFINES_COMPILED diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 466b484c9fa4..7747bfd99f91 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -168,7 +168,7 @@ static int myri_do_handshake(struct myri_eth *mp) return 0; } -static int myri_load_lanai(struct myri_eth *mp) +static int __devinit myri_load_lanai(struct myri_eth *mp) { struct net_device *dev = mp->dev; struct myri_shmem __iomem *shmem = mp->shmem; @@ -891,7 +891,7 @@ static void dump_eeprom(struct myri_eth *mp) } #endif -static int __init myri_ether_init(struct sbus_dev *sdev) +static int __devinit myri_ether_init(struct sbus_dev *sdev) { static int num; static unsigned version_printed; diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 6439b0cef1e4..18f88853e1e5 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c @@ -42,7 +42,7 @@ #define DRV_RELDATE "11/24/03" #define DRV_AUTHOR "David S. Miller (davem@redhat.com)" -static char version[] __initdata = +static char version[] = DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; MODULE_VERSION(DRV_VERSION); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index ed58bb489889..9b827ceec501 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -461,7 +461,7 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host) #define PTI_RESET_LIMIT 400 -static int __init qlogicpti_load_firmware(struct qlogicpti *qpti) +static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti) { struct Scsi_Host *host = qpti->qhost; unsigned short csum = 0; diff --git a/drivers/scsi/qlogicpti_asm.c b/drivers/scsi/qlogicpti_asm.c index 1545b30681b4..19aa84f46018 100644 --- a/drivers/scsi/qlogicpti_asm.c +++ b/drivers/scsi/qlogicpti_asm.c @@ -1,5 +1,5 @@ /* Version 1.31.00 ISP1000 Initiator RISC firmware */ -unsigned short sbus_risc_code01[] __initdata = { +unsigned short sbus_risc_code01[] __devinitdata = { 0x0078, 0x1030, 0x0000, 0x2419, 0x0000, 0x12ff, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, @@ -1157,4 +1157,4 @@ unsigned short sbus_risc_code01[] __initdata = { 0x003c, 0x0040, 0x3415, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c, 0x92a7 }; -unsigned short sbus_risc_code_length01 = 0x2419; +unsigned short __devinitdata sbus_risc_code_length01 = 0x2419; -- cgit v1.2.3 From 872ec6484720e7ddfebb8e15c232fa7ca158ef2e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 17 Oct 2006 19:19:08 -0700 Subject: [SPARC] {bbc_,}envctrl: Use call_usermodehelper(). We should not be calling kernel_execve() directly and this causes module build failures because kernel_execve() is not exported to modules. Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_envctrl.c | 4 ++-- drivers/sbus/char/envctrl.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 0d3660c28f7d..a54e4140683a 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c @@ -5,8 +5,8 @@ */ #include -#include #include +#include #include #include @@ -195,7 +195,7 @@ static void do_envctrl_shutdown(struct bbc_cpu_temperature *tp) printk(KERN_CRIT "kenvctrld: Shutting down the system now.\n"); shutting_down = 1; - if (kernel_execve("/sbin/shutdown", argv, envp) < 0) + if (call_usermodehelper("/sbin/shutdown", argv, envp, 0) < 0) printk(KERN_CRIT "envctrl: shutdown execution failed\n"); } diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 6b6a855f3795..fff4660cdf96 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -976,7 +976,7 @@ static void envctrl_do_shutdown(void) inprog = 1; printk(KERN_CRIT "kenvctrld: WARNING: Shutting down the system now.\n"); - ret = kernel_execve("/sbin/shutdown", argv, envp); + ret = call_usermodehelper("/sbin/shutdown", argv, envp, 0); if (ret < 0) { printk(KERN_CRIT "kenvctrld: WARNING: system shutdown failed!\n"); inprog = 0; /* unlikely to succeed, but we could try again */ -- cgit v1.2.3 From 5cacb9f8bca1ac67cc1f933a4e89b5130ffd1460 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:24:30 -0400 Subject: [alim7101] Add pci dev table for auto module loading. Also fixes comment for nowayout module param. Signed-off-by: Ben Collins --- drivers/char/watchdog/alim7101_wdt.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c index 5948863b592b..bf25d0a55a99 100644 --- a/drivers/char/watchdog/alim7101_wdt.c +++ b/drivers/char/watchdog/alim7101_wdt.c @@ -77,7 +77,8 @@ static struct pci_dev *alim7101_pmu; static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" + __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")"); /* * Whack the dog @@ -415,6 +416,16 @@ err_out: module_init(alim7101_wdt_init); module_exit(alim7101_wdt_unload); +static struct pci_device_id alim7101_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; + +MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl); + MODULE_AUTHOR("Steve Hill"); MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4596c75c23dde2623cbeec69357d5eb13d28387e Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:33:03 -0400 Subject: [mv643xx] Add pci device table for auto module loading. Signed-off-by: Ben Collins --- drivers/net/mv643xx_eth.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 9997081c6dae..a4f861bf32d6 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1557,6 +1557,12 @@ static void __exit mv643xx_cleanup_module(void) module_init(mv643xx_init_module); module_exit(mv643xx_cleanup_module); +static struct pci_device_id pci_marvell_mv64360[] = { + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) }, + {} +}; +MODULE_DEVICE_TABLE(pci, pci_marvell_mv64360); + MODULE_LICENSE("GPL"); MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani" " and Dale Farnsworth"); -- cgit v1.2.3 From 745b5715fafccc8f0f992a7cccdd1eb2b1f5d23f Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:36:57 -0400 Subject: [BusLogic] Add pci dev table for auto module loading. Signed-off-by: Ben Collins --- drivers/scsi/BusLogic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index 7c59bba98798..cdd033724786 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -3600,5 +3600,16 @@ static void __exit BusLogic_exit(void) __setup("BusLogic=", BusLogic_Setup); +static struct pci_device_id BusLogic_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_BUSLOGIC, PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; +MODULE_DEVICE_TABLE(pci, BusLogic_pci_tbl); + module_init(BusLogic_init); module_exit(BusLogic_exit); -- cgit v1.2.3 From 3985b977441f857404bb604a4b15911bbb0b9c5b Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:38:41 -0400 Subject: [fdomain] Add pci dev table for module auto loading. Signed-off-by: Ben Collins --- drivers/scsi/fdomain.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 72794a7b6dcc..65e6e7b7ba07 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -1736,6 +1736,15 @@ struct scsi_host_template fdomain_driver_template = { }; #ifndef PCMCIA + +static struct pci_device_id fdomain_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, + { } +}; +MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl); + #define driver_template fdomain_driver_template #include "scsi_module.c" + #endif -- cgit v1.2.3 From 012887327875915f76a6208e81fe0d67a682ec15 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:40:57 -0400 Subject: [initio] Add pci dev table for module auto loading. Signed-off-by: Ben Collins --- drivers/scsi/initio.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c index 911f2ff4a1f2..afed293dd7b9 100644 --- a/drivers/scsi/initio.c +++ b/drivers/scsi/initio.c @@ -142,8 +142,6 @@ #define i91u_MAXQUEUE 2 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a" -#define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */ -#define DMX_VENDOR_ID 0x134a /* Domex's PCI vendor ID */ #define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */ #define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */ #define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */ @@ -171,13 +169,16 @@ static int setup_debug = 0; static void i91uSCBPost(BYTE * pHcb, BYTE * pScb); -static const PCI_ID i91u_pci_devices[] = { - { INI_VENDOR_ID, I950_DEVICE_ID }, - { INI_VENDOR_ID, I940_DEVICE_ID }, - { INI_VENDOR_ID, I935_DEVICE_ID }, - { INI_VENDOR_ID, I920_DEVICE_ID }, - { DMX_VENDOR_ID, I920_DEVICE_ID }, +/* PCI Devices supported by this driver */ +static struct pci_device_id i91u_pci_devices[] __devinitdata = { + { PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_INIT, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_DOMEX, I920_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } }; +MODULE_DEVICE_TABLE(pci, i91u_pci_devices); #define DEBUG_INTERRUPT 0 #define DEBUG_QUEUE 0 @@ -2771,7 +2772,7 @@ static int tul_NewReturnNumberOfAdapters(void) for (i = 0; i < ARRAY_SIZE(i91u_pci_devices); i++) { - while ((pDev = pci_find_device(i91u_pci_devices[i].vendor_id, i91u_pci_devices[i].device_id, pDev)) != NULL) { + while ((pDev = pci_find_device(i91u_pci_devices[i].vendor, i91u_pci_devices[i].device, pDev)) != NULL) { if (pci_enable_device(pDev)) continue; pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue); -- cgit v1.2.3 From d77f09e51f5793583ede9733a93bd31a324d051c Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:45:30 -0400 Subject: [ixj] Add pci dev table for module auto loading. Signed-off-by: Ben Collins --- drivers/telephony/ixj.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index f6b2948ab288..1b601b6cf2a2 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c @@ -284,6 +284,14 @@ static int samplerate = 100; module_param(ixjdebug, int, 0); +static struct pci_device_id ixj_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_QUICKNET, PCI_DEVICE_ID_QUICKNET_XJ, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; + +MODULE_DEVICE_TABLE(pci, ixj_pci_tbl); + /************************************************************************ * * ixjdebug meanings are now bit mapped instead of level based @@ -7683,7 +7691,8 @@ static int __init ixj_probe_pci(int *cnt) IXJ *j = NULL; for (i = 0; i < IXJMAX - *cnt; i++) { - pci = pci_find_device(0x15E2, 0x0500, pci); + pci = pci_find_device(PCI_VENDOR_ID_QUICKNET, + PCI_DEVICE_ID_QUICKNET_XJ, pci); if (!pci) break; -- cgit v1.2.3 From d57cdcffe1180cf9b8d1fce048f80d8c6b159827 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:47:37 -0400 Subject: [hid-core] TurboX Keyboard needs NOGET quirk. Signed-off-by: Ben Collins --- drivers/usb/input/hid-core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index feabda73a6f9..45f44fe33bfe 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1391,6 +1391,9 @@ void hid_close(struct hid_device *hid) #define USB_VENDOR_ID_PANJIT 0x134c +#define USB_VENDOR_ID_TURBOX 0x062a +#define USB_DEVICE_ID_TURBOX_KEYBOARD 0x0201 + /* * Initialize all reports */ @@ -1778,6 +1781,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET }, + { 0, 0 } }; -- cgit v1.2.3 From 4938d3f4f8f1ffd744fa3626df8085118aeb1d79 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:49:31 -0400 Subject: [controlfb] Ifdef for when CONFIG_NVRAM isn't enabled. Signed-off-by: Ben Collins --- drivers/video/controlfb.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 8cc6c0e2d27a..04c6d928189b 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -415,13 +415,15 @@ static int __init init_control(struct fb_info_control *p) full = p->total_vram == 0x400000; /* Try to pick a video mode out of NVRAM if we have one. */ +#ifdef CONFIG_NVRAM if (default_cmode == CMODE_NVRAM){ cmode = nvram_read_byte(NV_CMODE); if(cmode < CMODE_8 || cmode > CMODE_32) cmode = CMODE_8; } else +#endif cmode=default_cmode; - +#ifdef CONFIG_NVRAM if (default_vmode == VMODE_NVRAM) { vmode = nvram_read_byte(NV_VMODE); if (vmode < 1 || vmode > VMODE_MAX || @@ -432,7 +434,9 @@ static int __init init_control(struct fb_info_control *p) if (control_mac_modes[vmode - 1].m[full] < cmode) vmode = VMODE_640_480_60; } - } else { + } else +#endif + { vmode=default_vmode; if (control_mac_modes[vmode - 1].m[full] < cmode) { if (cmode > CMODE_8) -- cgit v1.2.3 From b023429ca30fc18b17a7b3e279b55bd652e9a989 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:50:49 -0400 Subject: [igafb] Add pci dev table for module auto loading. Signed-off-by: Ben Collins --- drivers/video/igafb.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/video/igafb.c b/drivers/video/igafb.c index 67f384f86758..e6df492c22a5 100644 --- a/drivers/video/igafb.c +++ b/drivers/video/igafb.c @@ -573,3 +573,10 @@ int __init igafb_setup(char *options) module_init(igafb_init); MODULE_LICENSE("GPL"); +static struct pci_device_id igafb_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { } +}; + +MODULE_DEVICE_TABLE(pci, igafb_pci_tbl); -- cgit v1.2.3 From f3f6f9aaced9c8453ef45956a23295e5c2328124 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:52:48 -0400 Subject: [platinumfb] Ifdef for when CONFIG_NVRAM isn't enabled. Signed-off-by: Ben Collins --- drivers/video/platinumfb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index 983be3ec2345..fdb33cd21a27 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -339,11 +339,12 @@ static int __devinit platinum_init_fb(struct fb_info *info) sense = read_platinum_sense(pinfo); printk(KERN_INFO "platinumfb: Monitor sense value = 0x%x, ", sense); - if (default_vmode == VMODE_NVRAM) { +#ifdef CONFIG_NVRAM default_vmode = nvram_read_byte(NV_VMODE); if (default_vmode <= 0 || default_vmode > VMODE_MAX || !platinum_reg_init[default_vmode-1]) +#endif default_vmode = VMODE_CHOOSE; } if (default_vmode == VMODE_CHOOSE) { @@ -351,8 +352,10 @@ static int __devinit platinum_init_fb(struct fb_info *info) } if (default_vmode <= 0 || default_vmode > VMODE_MAX) default_vmode = VMODE_640_480_60; +#ifdef CONFIG_NVRAM if (default_cmode == CMODE_NVRAM) default_cmode = nvram_read_byte(NV_CMODE); +#endif if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; /* -- cgit v1.2.3 From 996f324767fd24b7cc682801277add2a4f276635 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Wed, 18 Oct 2006 08:53:37 -0400 Subject: [valkyriefb] Ifdef for when CONFIG_NVRAM isn't enabled. Signed-off-by: Ben Collins --- drivers/video/valkyriefb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 47f27924a7d7..06fc19a61192 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -284,7 +284,7 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p) printk(KERN_INFO "Monitor sense value = 0x%x\n", p->sense); /* Try to pick a video mode out of NVRAM if we have one. */ -#ifndef CONFIG_MAC +#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM) if (default_vmode == VMODE_NVRAM) { default_vmode = nvram_read_byte(NV_VMODE); if (default_vmode <= 0 @@ -297,7 +297,7 @@ static void __init valkyrie_choose_mode(struct fb_info_valkyrie *p) default_vmode = mac_map_monitor_sense(p->sense); if (!valkyrie_reg_init[default_vmode - 1]) default_vmode = VMODE_640_480_67; -#ifndef CONFIG_MAC +#if !defined(CONFIG_MAC) && defined(CONFIG_NVRAM) if (default_cmode == CMODE_NVRAM) default_cmode = nvram_read_byte(NV_CMODE); #endif -- cgit v1.2.3 From 8b42f5c20251060cb1ab875459fe66ad7bb92cbd Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 18 Oct 2006 18:30:43 +0200 Subject: [S390] cio: invalid device operational notification Reset device operational notification flag when channel paths become unavailable during path verification. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_fsm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index fcaf28d7b4eb..de3d0857db9f 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -578,9 +578,13 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) } break; case -ETIME: + /* Reset oper notify indication after verify error. */ + cdev->private->flags.donotify = 0; ccw_device_done(cdev, DEV_STATE_BOXED); break; default: + /* Reset oper notify indication after verify error. */ + cdev->private->flags.donotify = 0; PREPARE_WORK(&cdev->private->kick_work, ccw_device_nopath_notify, cdev); queue_work(ccw_device_notify_work, &cdev->private->kick_work); -- cgit v1.2.3 From 85a4aa64a85a8bd19b86887f70b13a27a363030d Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 18 Oct 2006 18:30:47 +0200 Subject: [S390] cio: sch_no -> schid.sch_no conversion. Overlooked one sch_no -> schid.sch_no conversion. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index 0648ce5bb684..476aa1da5cbc 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -3529,7 +3529,7 @@ do_QDIO(struct ccw_device *cdev,unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text,"doQD%04x",cdev->private->sch_no); + sprintf(dbf_text,"doQD%04x",cdev->private->schid.sch_no); QDIO_DBF_TEXT3(0,trace,dbf_text); #endif /* CONFIG_QDIO_DEBUG */ -- cgit v1.2.3 From 2c91971f84be168a35f937dd6c61e56e492b2185 Mon Sep 17 00:00:00 2001 From: Melissa Howland Date: Wed, 18 Oct 2006 18:30:49 +0200 Subject: [S390] monwriter find header logic. Fix logic for finding matching buffers. Signed-off-by: Melissa Howland Signed-off-by: Martin Schwidefsky --- drivers/s390/char/monwriter.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/char/monwriter.c b/drivers/s390/char/monwriter.c index abd02ed501cb..b9b0fc3f812b 100644 --- a/drivers/s390/char/monwriter.c +++ b/drivers/s390/char/monwriter.c @@ -73,12 +73,15 @@ static inline struct mon_buf *monwrite_find_hdr(struct mon_private *monpriv, struct mon_buf *entry, *next; list_for_each_entry_safe(entry, next, &monpriv->list, list) - if (entry->hdr.applid == monhdr->applid && + if ((entry->hdr.mon_function == monhdr->mon_function || + monhdr->mon_function == MONWRITE_STOP_INTERVAL) && + entry->hdr.applid == monhdr->applid && entry->hdr.record_num == monhdr->record_num && entry->hdr.version == monhdr->version && entry->hdr.release == monhdr->release && entry->hdr.mod_level == monhdr->mod_level) return entry; + return NULL; } @@ -92,7 +95,9 @@ static int monwrite_new_hdr(struct mon_private *monpriv) monhdr->mon_function > MONWRITE_START_CONFIG || monhdr->hdrlen != sizeof(struct monwrite_hdr)) return -EINVAL; - monbuf = monwrite_find_hdr(monpriv, monhdr); + monbuf = NULL; + if (monhdr->mon_function != MONWRITE_GEN_EVENT) + monbuf = monwrite_find_hdr(monpriv, monhdr); if (monbuf) { if (monhdr->mon_function == MONWRITE_STOP_INTERVAL) { monhdr->datalen = monbuf->hdr.datalen; @@ -104,7 +109,7 @@ static int monwrite_new_hdr(struct mon_private *monpriv) kfree(monbuf); monbuf = NULL; } - } else { + } else if (monhdr->mon_function != MONWRITE_STOP_INTERVAL) { if (mon_buf_count >= mon_max_bufs) return -ENOSPC; monbuf = kzalloc(sizeof(struct mon_buf), GFP_KERNEL); @@ -118,7 +123,8 @@ static int monwrite_new_hdr(struct mon_private *monpriv) } monbuf->hdr = *monhdr; list_add_tail(&monbuf->list, &monpriv->list); - mon_buf_count++; + if (monhdr->mon_function != MONWRITE_GEN_EVENT) + mon_buf_count++; } monpriv->current_buf = monbuf; return 0; -- cgit v1.2.3 From 867dcd0f32b125f45a663f9374a36fb21193ab21 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Wed, 18 Oct 2006 18:30:53 +0200 Subject: [S390] dasd: clean up timer. Clean up dasd timer when when a dasd device is set offline. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d0647d116eaa..79ffef6bfaf8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -203,6 +203,7 @@ dasd_state_basic_to_known(struct dasd_device * device) rc = dasd_flush_ccw_queue(device, 1); if (rc) return rc; + dasd_clear_timer(device); DBF_DEV_EVENT(DBF_EMERG, device, "%p debug area deleted", device); if (device->debug_area != NULL) { -- cgit v1.2.3 From b4a1efffcf8070dbc7734f27da10ce49fb9f2a34 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 22 Sep 2006 12:52:37 -0700 Subject: shpchp: fix shpchp_wait_cmd in poll This patch fixes the problem that issuing SHPC command in poll mode always fails with the following message. shpchp: Command not completed in 2000 msec Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 54 ++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4d8aee119134..446e9beff046 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -302,16 +302,43 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) add_timer(&php_ctlr->int_poll_timer); } +/* + * Returns 1 if SHPC finishes executing a command within 1 sec, + * otherwise returns 0. + */ +static inline int shpc_poll_ctrl_busy(struct controller *ctrl) +{ + int i; + u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); + + if (!(cmd_status & 0x1)) + return 1; + + /* Check every 0.1 sec for a total of 1 sec */ + for (i = 0; i < 10; i++) { + msleep(100); + cmd_status = shpc_readw(ctrl, CMD_STATUS); + if (!(cmd_status & 0x1)) + return 1; + } + + return 0; +} + static inline int shpc_wait_cmd(struct controller *ctrl) { int retval = 0; - unsigned int timeout_msec = shpchp_poll_mode ? 2000 : 1000; - unsigned long timeout = msecs_to_jiffies(timeout_msec); - int rc = wait_event_interruptible_timeout(ctrl->queue, - !ctrl->cmd_busy, timeout); + unsigned long timeout = msecs_to_jiffies(1000); + int rc; + + if (shpchp_poll_mode) + rc = shpc_poll_ctrl_busy(ctrl); + else + rc = wait_event_interruptible_timeout(ctrl->queue, + !ctrl->cmd_busy, timeout); if (!rc) { retval = -EIO; - err("Command not completed in %d msec\n", timeout_msec); + err("Command not completed in 1000 msec\n"); } else if (rc < 0) { retval = -EINTR; info("Command was interrupted by a signal\n"); @@ -327,26 +354,15 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) u16 cmd_status; int retval = 0; u16 temp_word; - int i; DBG_ENTER_ROUTINE mutex_lock(&slot->ctrl->cmd_lock); - for (i = 0; i < 10; i++) { - cmd_status = shpc_readw(ctrl, CMD_STATUS); - - if (!(cmd_status & 0x1)) - break; - /* Check every 0.1 sec for a total of 1 sec*/ - msleep(100); - } - - cmd_status = shpc_readw(ctrl, CMD_STATUS); - - if (cmd_status & 0x1) { + if (!shpc_poll_ctrl_busy(ctrl)) { /* After 1 sec and and the controller is still busy */ - err("%s : Controller is still busy after 1 sec.\n", __FUNCTION__); + err("%s : Controller is still busy after 1 sec.\n", + __FUNCTION__); retval = -EBUSY; goto out; } -- cgit v1.2.3 From 49ed2b4963cd00993eab518b820a6700f94f222d Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 22 Sep 2006 10:17:10 -0700 Subject: pciehp: fix improper info messages The slot number displayed in info messages would cause a confusion because those are displayed in several ways (decimal and hex). Furthermore, those slot number is not same as slot name (directory name). This patch fixes those improper info messages. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 8 +++---- drivers/pci/hotplug/pciehp_ctrl.c | 47 ++++++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index eaea9d36a1bb..b71f774aca16 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -166,10 +166,10 @@ struct controller { * error Messages */ #define msg_initialization_err "Initialization failure, error=%d\n" -#define msg_button_on "PCI slot #%d - powering on due to button press.\n" -#define msg_button_off "PCI slot #%d - powering off due to button press.\n" -#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n" -#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n" +#define msg_button_on "PCI slot #%s - powering on due to button press.\n" +#define msg_button_off "PCI slot #%s - powering off due to button press.\n" +#define msg_button_cancel "PCI slot #%s - action canceled due to button press.\n" +#define msg_button_ignore "PCI slot #%s - button press ignored. (action in progress...)\n" /* controller functions */ extern int pciehp_event_start_thread (void); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 41290a106bd8..f602b042adcf 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -43,6 +43,11 @@ static int event_finished; static unsigned long pushbutton_pending; /* = 0 */ static unsigned long surprise_rm_pending; /* = 0 */ +static inline char *slot_name(struct slot *p_slot) +{ + return p_slot->hotplug_slot->name; +} + u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) { struct controller *ctrl = (struct controller *) inst_id; @@ -68,7 +73,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) /* * Button pressed - See if need to TAKE ACTION!!! */ - info("Button pressed on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Button pressed on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_BUTTON_PRESS; if ((p_slot->state == BLINKINGON_STATE) @@ -78,7 +83,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) * or hot-remove */ taskInfo->event_type = INT_BUTTON_CANCEL; - info("Button cancel on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Button cancel on Slot(%s)\n", slot_name(p_slot)); } else if ((p_slot->state == POWERON_STATE) || (p_slot->state == POWEROFF_STATE)) { /* Ignore if the slot is on power-on or power-off state; this @@ -86,7 +91,7 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) * hot-remove is undergoing */ taskInfo->event_type = INT_BUTTON_IGNORE; - info("Button ignore on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Button ignore on Slot(%s)\n", slot_name(p_slot)); } if (rc) @@ -122,13 +127,13 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id) /* * Switch opened */ - info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch open on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_SWITCH_OPEN; } else { /* * Switch closed */ - info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Latch close on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_SWITCH_CLOSE; } @@ -166,13 +171,13 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id) /* * Card Present */ - info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card present on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_PRESENCE_ON; } else { /* * Not Present */ - info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Card not present on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_PRESENCE_OFF; } @@ -206,13 +211,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) /* * power fault Cleared */ - info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault cleared on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_POWER_FAULT_CLEAR; } else { /* * power fault */ - info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot); + info("Power fault on Slot(%s)\n", slot_name(p_slot)); taskInfo->event_type = INT_POWER_FAULT; info("power fault bit %x set\n", hp_slot); } @@ -654,7 +659,7 @@ static void interrupt_event_handler(struct controller *ctrl) warn("Not a valid state\n"); return; } - info(msg_button_cancel, p_slot->number); + info(msg_button_cancel, slot_name(p_slot)); p_slot->state = STATIC_STATE; } /* ***********Button Pressed (No action on 1st press...) */ @@ -667,12 +672,12 @@ static void interrupt_event_handler(struct controller *ctrl) /* slot is on */ dbg("slot is on\n"); p_slot->state = BLINKINGOFF_STATE; - info(msg_button_off, p_slot->number); + info(msg_button_off, slot_name(p_slot)); } else { /* slot is off */ dbg("slot is off\n"); p_slot->state = BLINKINGON_STATE; - info(msg_button_on, p_slot->number); + info(msg_button_on, slot_name(p_slot)); } /* Wait for exclusive access to hardware */ @@ -760,14 +765,16 @@ int pciehp_enable_slot(struct slot *p_slot) rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (rc || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: no adapter on slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } if (MRL_SENS(p_slot->ctrl->ctrlcap)) { rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: latch open on slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -776,7 +783,8 @@ int pciehp_enable_slot(struct slot *p_slot) if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (rc || getstatus) { - info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: already enabled on slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } @@ -811,7 +819,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (ret || !getstatus) { - info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: no adapter on slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -820,7 +829,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (MRL_SENS(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (ret || getstatus) { - info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: latch open on slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -ENODEV; } @@ -829,7 +839,8 @@ int pciehp_disable_slot(struct slot *p_slot) if (POWER_CTRL(p_slot->ctrl->ctrlcap)) { ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (ret || !getstatus) { - info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); + info("%s: already disabled slot(%s)\n", __FUNCTION__, + slot_name(p_slot)); mutex_unlock(&p_slot->ctrl->crit_sect); return -EINVAL; } -- cgit v1.2.3 From dd5619cb4407e830a8921a93c949be37c81105b5 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Fri, 22 Sep 2006 10:17:29 -0700 Subject: pciehp - add missing locking This patch fixes the problem that system will panic if multiple power on/off operations are issued to the same slot in parallel. This problem can be easily reproduced by commands below. # while true; do echo 1 > power; echo 0 > power; done & # while true; do echo 1 > power; echo 0 > power; done & The cause is lack of locking for enable/disable operations. This patch fixes this problem. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp.h | 1 + drivers/pci/hotplug/pciehp_core.c | 6 ++--- drivers/pci/hotplug/pciehp_ctrl.c | 54 +++++++++++++++++++-------------------- drivers/pci/hotplug/pciehp_hpc.c | 2 ++ 4 files changed, 33 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index b71f774aca16..30f021c55fe5 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -92,6 +92,7 @@ struct php_ctlr_state_s { struct controller { struct controller *next; struct mutex crit_sect; /* critical section mutex */ + struct mutex ctrl_lock; /* controller lock */ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */ int num_slots; /* Number of slots on ctlr */ int slot_num_inc; /* 1 or -1 */ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index c67b7c3f1ddf..f93e81e2d2c7 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -448,7 +448,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ @@ -456,7 +456,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ if (rc) { /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); goto err_out_free_ctrl_slot; } else /* Wait for the command to complete */ @@ -464,7 +464,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return 0; diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index f602b042adcf..c206a3d63b63 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -234,13 +234,13 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id) static void set_slot_off(struct controller *ctrl, struct slot * pslot) { /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); /* turn off slot, turn on Amber LED, turn off Green LED if supported*/ if (POWER_CTRL(ctrl->ctrlcap)) { if (pslot->hpc_ops->power_off_slot(pslot)) { err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return; } wait_for_ctrl_irq (ctrl); @@ -254,14 +254,14 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) if (ATTN_LED(ctrl->ctrlcap)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) { err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return; } wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); } /** @@ -284,13 +284,13 @@ static int board_added(struct slot *p_slot) ctrl->slot_device_offset, hp_slot); /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); if (POWER_CTRL(ctrl->ctrlcap)) { /* Power on slot */ rc = p_slot->hpc_ops->power_on_slot(p_slot); if (rc) { - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return -1; } @@ -306,7 +306,7 @@ static int board_added(struct slot *p_slot) } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); /* Wait for ~1 second */ wait_for_ctrl_irq (ctrl); @@ -340,7 +340,7 @@ static int board_added(struct slot *p_slot) pci_fixup_device(pci_fixup_final, ctrl->pci_dev); if (PWR_LED(ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); p_slot->hpc_ops->green_led_on(p_slot); @@ -348,7 +348,7 @@ static int board_added(struct slot *p_slot) wait_for_ctrl_irq (ctrl); /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); } return 0; @@ -380,14 +380,14 @@ static int remove_board(struct slot *p_slot) dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot); /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); if (POWER_CTRL(ctrl->ctrlcap)) { /* power off slot */ rc = p_slot->hpc_ops->power_off_slot(p_slot); if (rc) { err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return rc; } /* Wait for the command to complete */ @@ -403,7 +403,7 @@ static int remove_board(struct slot *p_slot) } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); return 0; } @@ -450,7 +450,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - mutex_lock(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->ctrl_lock); p_slot->hpc_ops->green_led_off(p_slot); @@ -458,7 +458,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - mutex_unlock(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->ctrl_lock); } p_slot->state = STATIC_STATE; } @@ -500,7 +500,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) { /* Wait for exclusive access to hardware */ - mutex_lock(&p_slot->ctrl->crit_sect); + mutex_lock(&p_slot->ctrl->ctrl_lock); p_slot->hpc_ops->green_led_off(p_slot); @@ -508,7 +508,7 @@ static void pciehp_surprise_rm_thread(unsigned long slot) wait_for_ctrl_irq (p_slot->ctrl); /* Done with exclusive hardware access */ - mutex_unlock(&p_slot->ctrl->crit_sect); + mutex_unlock(&p_slot->ctrl->ctrl_lock); } p_slot->state = STATIC_STATE; } @@ -621,7 +621,7 @@ static void interrupt_event_handler(struct controller *ctrl) switch (p_slot->state) { case BLINKINGOFF_STATE: /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_on(p_slot); @@ -635,11 +635,11 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); break; case BLINKINGON_STATE: /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); if (PWR_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->green_led_off(p_slot); @@ -652,7 +652,7 @@ static void interrupt_event_handler(struct controller *ctrl) wait_for_ctrl_irq (ctrl); } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); break; default: @@ -681,7 +681,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); /* blink green LED and turn off amber */ if (PWR_LED(ctrl->ctrlcap)) { @@ -698,7 +698,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); init_timer(&p_slot->task_event); p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ @@ -713,7 +713,7 @@ static void interrupt_event_handler(struct controller *ctrl) if (POWER_CTRL(ctrl->ctrlcap)) { dbg("power fault\n"); /* Wait for exclusive access to hardware */ - mutex_lock(&ctrl->crit_sect); + mutex_lock(&ctrl->ctrl_lock); if (ATTN_LED(ctrl->ctrlcap)) { p_slot->hpc_ops->set_attention_status(p_slot, 1); @@ -726,7 +726,7 @@ static void interrupt_event_handler(struct controller *ctrl) } /* Done with exclusive hardware access */ - mutex_unlock(&ctrl->crit_sect); + mutex_unlock(&ctrl->ctrl_lock); } } /***********SURPRISE REMOVAL********************/ @@ -789,7 +789,6 @@ int pciehp_enable_slot(struct slot *p_slot) return -EINVAL; } } - mutex_unlock(&p_slot->ctrl->crit_sect); p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); @@ -801,6 +800,7 @@ int pciehp_enable_slot(struct slot *p_slot) if (p_slot) update_slot_info(p_slot); + mutex_unlock(&p_slot->ctrl->crit_sect); return rc; } @@ -846,10 +846,10 @@ int pciehp_disable_slot(struct slot *p_slot) } } - mutex_unlock(&p_slot->ctrl->crit_sect); - ret = remove_board(p_slot); update_slot_info(p_slot); + + mutex_unlock(&p_slot->ctrl->crit_sect); return ret; } diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 703a64a39fe8..1c551c697c35 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1402,6 +1402,8 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev) pdev->subsystem_vendor, pdev->subsystem_device); mutex_init(&ctrl->crit_sect); + mutex_init(&ctrl->ctrl_lock); + /* setup wait queue */ init_waitqueue_head(&ctrl->queue); -- cgit v1.2.3 From 9ef9977cabc1b2c1718ef6eb883caec8dcb80b4c Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 25 Sep 2006 00:56:53 +0200 Subject: pciehp: Remove unnecessary check in pciehp_ctrl.c this was spotted by coverity (cid #819). We dereference p_slot earlier in the function, and i found no way it could become NULL anywhere. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_ctrl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index c206a3d63b63..372c63e35aa9 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -797,8 +797,7 @@ int pciehp_enable_slot(struct slot *p_slot) p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); } - if (p_slot) - update_slot_info(p_slot); + update_slot_info(p_slot); mutex_unlock(&p_slot->ctrl->crit_sect); return rc; -- cgit v1.2.3 From 09d6029f43ebbe7307854abdae204c25d711ff94 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Mon, 25 Sep 2006 16:52:19 -0700 Subject: PCI: VIA IRQ quirk behaviour change The most recent VIA IRQ quirk changes have broken various VIA devices for some users. We are not able to add these devices to the blacklist as they are also available in PCI-card form, and running the quirk on these devices brings us back to square one (running the VIA quirk on non-VIA boards where the quirk is not needed). This patch, based on suggestions from Sergey Vlasov, implements a scheme similar to but more restrictive than the scheme we had in 2.6.16 and earlier. It runs the quirk on all VIA hardware, but *only* if a VIA southbridge was detected on the system. To further reduce the amount of quirked devices, this patch includes a change suggested by Linus at http://lkml.org/lkml/2005/9/27/113 This ensures that devices bound to non-legacy IO-APIC interrupt lines are not quirked. We have made one change to Linus' suggestion: we do a comparison of ">15" rather than ">=15", as 15 is still in the legacy interrupt range. There is still a downside to this patch: if the user inserts a VIA PCI card into a VIA-based motherboard, in some circumstances the quirk will also run on the VIA PCI card. This corner case is hard to avoid. Signed-off-by: Daniel Drake Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 23b599d6a9d5..e5425079cecd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -648,11 +648,43 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vi * Some of the on-chip devices are actually '586 devices' so they are * listed here. */ + +static int via_irq_fixup_needed = -1; + +/* + * As some VIA hardware is available in PCI-card form, we need to restrict + * this quirk to VIA PCI hardware built onto VIA-based motherboards only. + * We try to locate a VIA southbridge before deciding whether the quirk + * should be applied. + */ +static const struct pci_device_id via_irq_fixup_tbl[] = { + { + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .class = PCI_CLASS_BRIDGE_ISA << 8, + .class_mask = 0xffff00, + }, + { 0, }, +}; + static void quirk_via_irq(struct pci_dev *dev) { u8 irq, new_irq; - new_irq = dev->irq & 0xf; + if (via_irq_fixup_needed == -1) + via_irq_fixup_needed = pci_dev_present(via_irq_fixup_tbl); + + if (!via_irq_fixup_needed) + return; + + new_irq = dev->irq; + + /* Don't quirk interrupts outside the legacy IRQ range */ + if (!new_irq || new_irq > 15) + return; + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); if (new_irq != irq) { printk(KERN_INFO "PCI: VIA IRQ fixup for %s, from %d to %d\n", @@ -661,14 +693,7 @@ static void quirk_via_irq(struct pci_dev *dev) pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq); } } -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235_USB_2, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_irq); -DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irq); +DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq); /* * VIA VT82C598 has its device ID settable and many BIOSes -- cgit v1.2.3 From 3ec6a8d02efd54a66640bd85afa8c162647b56c3 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 25 Sep 2006 16:52:20 -0700 Subject: PCI: pcie-check-and-return-bus_register-errors fix __must_check goes on the declaration, not the definition. Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv.h | 4 +++- drivers/pci/pcie/portdrv_core.c | 3 +-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index 67fcd176babd..3656e0349dd1 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -9,6 +9,8 @@ #ifndef _PORTDRV_H_ #define _PORTDRV_H_ +#include + #if !defined(PCI_CAP_ID_PME) #define PCI_CAP_ID_PME 1 #endif @@ -39,7 +41,7 @@ extern int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state); extern int pcie_port_device_resume(struct pci_dev *dev); #endif extern void pcie_port_device_remove(struct pci_dev *dev); -extern int pcie_port_bus_register(void); +extern int __must_check pcie_port_bus_register(void); extern void pcie_port_bus_unregister(void); #endif /* _PORTDRV_H_ */ diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index bd6615b4d40e..b20a9b81dae2 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -6,7 +6,6 @@ * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) */ -#include #include #include #include @@ -401,7 +400,7 @@ void pcie_port_device_remove(struct pci_dev *dev) pci_disable_msi(dev); } -int __must_check pcie_port_bus_register(void) +int pcie_port_bus_register(void) { return bus_register(&pcie_port_bus_type); } -- cgit v1.2.3 From bacedce32b171cd461a7da3160ad794e2240c67a Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Mon, 25 Sep 2006 16:52:21 -0700 Subject: PCI: add ICH7/8 ACPI/GPIO io resource quirks Signed-off-by: Daniel Ritz Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e5425079cecd..1d2ccda946fd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -453,6 +453,12 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi ); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi ); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi ); /* * VIA ACPI: One IO region pointed to by longword at -- cgit v1.2.3 From b5e4efe7e061ff52ac97b9fa45acca529d8daeea Mon Sep 17 00:00:00 2001 From: "eiichiro.oiwa.nm@hitachi.com" Date: Thu, 28 Sep 2006 13:55:47 +0900 Subject: PCI: Turn pci_fixup_video into generic for embedded VGA pci_fixup_video turns into generic code because there are many platforms need this fixup for embedded VGA as well as x86. The Video BIOS integrates into System BIOS on a machine has embedded VGA although embedded VGA generally don't have PCI ROM. As a result, embedded VGA need the way that the sysfs rom points to the Video BIOS of System RAM (0xC0000). PCI-to-PCI Bridge Architecture specification describes the condition whether or not PCI ROM forwards VGA compatible memory address. fixup_video suits this specification. Although the Video ROM generally implements in x86 code regardless of platform, some application such as X Window System can run this code by dosemu86. Therefore, pci_fixup_video should turn into generic code. Signed-off-by: Eiichiro Oiwa Acked-by: Alan Cox Acked-by: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/fixup.c | 45 --------------------------------------------- drivers/pci/quirks.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/rom.c | 5 ++++- 3 files changed, 49 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index b60d7e8689ed..908b410f4c93 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -342,51 +342,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_r DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); -/* - * Fixup to mark boot BIOS video selected by BIOS before it changes - * - * From information provided by "Jon Smirl" - * - * The standard boot ROM sequence for an x86 machine uses the BIOS - * to select an initial video card for boot display. This boot video - * card will have it's BIOS copied to C0000 in system RAM. - * IORESOURCE_ROM_SHADOW is used to associate the boot video - * card with this copy. On laptops this copy has to be used since - * the main ROM may be compressed or combined with another image. - * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW - * is marked here since the boot video device will be the only enabled - * video device at this point. - */ - -static void __devinit pci_fixup_video(struct pci_dev *pdev) -{ - struct pci_dev *bridge; - struct pci_bus *bus; - u16 config; - - if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return; - - /* Is VGA routed to us? */ - bus = pdev->bus; - while (bus) { - bridge = bus->self; - if (bridge) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, - &config); - if (!(config & PCI_BRIDGE_CTL_VGA)) - return; - } - bus = bus->parent; - } - pci_read_config_word(pdev, PCI_COMMAND, &config); - if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; - printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); - /* * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. * diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1d2ccda946fd..371ab8821f10 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1619,6 +1619,51 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + */ + +static void __devinit fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 config; + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + if (bridge) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, + &config); + if (!(config & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pci_read_config_word(pdev, PCI_COMMAND, &config); + if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index f5ee7ce16fa6..43e4a49f2cc4 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -71,7 +71,10 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) void __iomem *image; int last_image; - /* IORESOURCE_ROM_SHADOW only set on x86 */ + /* + * IORESOURCE_ROM_SHADOW set if the VGA enable bit of the Bridge Control + * register is set for embedded VGA. + */ if (res->flags & IORESOURCE_ROM_SHADOW) { /* primary video rom always starts here */ start = (loff_t)0xC0000; -- cgit v1.2.3 From ccc4c7bbd6a2d47bf5899c2c8cf2e0d176a4dc0f Mon Sep 17 00:00:00 2001 From: Vojtech Pavlik Date: Fri, 7 Apr 2006 20:00:27 +0200 Subject: Fix DMA resource allocation in ACPIPnP The ACPIPnP implementation had the understanding of Linux resource flags very wrong, resulting in a nonfunctional implementation of DMA resource allocation. This was usually not a problem, since almost no on-board PnP devices use ISA DMA, with the exception of ECP parallel ports. Even with that, parallel port DMA is preconfigured by the BIOS, so this routine isn't normally called. Except in the case where somebody does 'rmmod parport_pc; modprobe parport_pc', where the rmmod case disables the ECP parallel port resources, and they need to be enabled again to initialize the module. This didn't work, resulting in a non-printing printer. The application doing exactly the above to force reprobing of printers is the YaST printer module. Thus without this fix YaST wedged the printer when configuring it, and was not able to print a test page. Reported-by: Ralf Flaxa Reproduced-by: Jiri Dluhos Signed-off-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman --- drivers/pnp/pnpacpi/rsparser.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index dc79b0a0059f..379048fdf05d 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c @@ -776,21 +776,32 @@ static void pnpacpi_encode_dma(struct acpi_resource *resource, struct resource *p) { /* Note: pnp_assign_dma will copy pnp_dma->flags into p->flags */ - if (p->flags & IORESOURCE_DMA_COMPATIBLE) - resource->data.dma.type = ACPI_COMPATIBILITY; - else if (p->flags & IORESOURCE_DMA_TYPEA) - resource->data.dma.type = ACPI_TYPE_A; - else if (p->flags & IORESOURCE_DMA_TYPEB) - resource->data.dma.type = ACPI_TYPE_B; - else if (p->flags & IORESOURCE_DMA_TYPEF) - resource->data.dma.type = ACPI_TYPE_F; - if (p->flags & IORESOURCE_DMA_8BIT) - resource->data.dma.transfer = ACPI_TRANSFER_8; - else if (p->flags & IORESOURCE_DMA_8AND16BIT) - resource->data.dma.transfer = ACPI_TRANSFER_8_16; - else if (p->flags & IORESOURCE_DMA_16BIT) - resource->data.dma.transfer = ACPI_TRANSFER_16; - resource->data.dma.bus_master = p->flags & IORESOURCE_DMA_MASTER; + switch (p->flags & IORESOURCE_DMA_SPEED_MASK) { + case IORESOURCE_DMA_TYPEA: + resource->data.dma.type = ACPI_TYPE_A; + break; + case IORESOURCE_DMA_TYPEB: + resource->data.dma.type = ACPI_TYPE_B; + break; + case IORESOURCE_DMA_TYPEF: + resource->data.dma.type = ACPI_TYPE_F; + break; + default: + resource->data.dma.type = ACPI_COMPATIBILITY; + } + + switch (p->flags & IORESOURCE_DMA_TYPE_MASK) { + case IORESOURCE_DMA_8BIT: + resource->data.dma.transfer = ACPI_TRANSFER_8; + break; + case IORESOURCE_DMA_8AND16BIT: + resource->data.dma.transfer = ACPI_TRANSFER_8_16; + break; + default: + resource->data.dma.transfer = ACPI_TRANSFER_16; + } + + resource->data.dma.bus_master = !!(p->flags & IORESOURCE_DMA_MASTER); resource->data.dma.channel_count = 1; resource->data.dma.channels[0] = p->start; } -- cgit v1.2.3 From 0bed208efcb25bed4dc2026488a4417aa68e7c92 Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 28 Sep 2006 14:35:59 +0800 Subject: PCI: fix pcie_portdrv_restore_config undefined without CONFIG_PM error On Thu, 2006-09-28 at 03:42, Olaf Hering wrote: > PCI-Express AER implemetation: pcie_portdrv error handler > > This patch breaks if CONFIG_PM is not enabled, > pcie_portdrv_restore_config() will be undefined. I move the definition of pcie_portdrv_restore_config out of CONFIG_PM. Below patch is against 2.6.18-mm1. Could you try it? Signed-off-by: Zhang Yanmin Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pcie/portdrv_pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 037690e08f5f..b4da7954611e 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -37,7 +37,6 @@ static int pcie_portdrv_save_config(struct pci_dev *dev) return pci_save_state(dev); } -#ifdef CONFIG_PM static int pcie_portdrv_restore_config(struct pci_dev *dev) { int retval; @@ -50,6 +49,7 @@ static int pcie_portdrv_restore_config(struct pci_dev *dev) return 0; } +#ifdef CONFIG_PM static int pcie_portdrv_suspend(struct pci_dev *dev, pm_message_t state) { int ret = pcie_port_device_suspend(dev, state); -- cgit v1.2.3 From 094ed76e8988d46158b036ab150e0c22aff6db3a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 29 Sep 2006 18:36:15 +0100 Subject: pci: Stamp out pci_find_* usage in fakephp pci_find is not hotplug safe, so it really doesn't want to be in an actual hotplug driver either. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/fakephp.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index 05a4f0f90186..aaeb1129132e 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -181,7 +181,9 @@ static void pci_rescan_slot(struct pci_dev *temp) if (!pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) { temp->hdr_type = hdr_type & 0x7f; - if (!pci_find_slot(bus->number, temp->devfn)) { + if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) + pci_dev_put(dev); + else { dev = pci_scan_single_device(bus, temp->devfn); if (dev) { dbg("New device on %s function %x:%x\n", @@ -205,7 +207,9 @@ static void pci_rescan_slot(struct pci_dev *temp) continue; temp->hdr_type = hdr_type & 0x7f; - if (!pci_find_slot(bus->number, temp->devfn)) { + if ((dev = pci_get_slot(bus, temp->devfn)) != NULL) + pci_dev_put(dev); + else { dev = pci_scan_single_device(bus, temp->devfn); if (dev) { dbg("New device on %s function %x:%x\n", @@ -305,7 +309,7 @@ static int disable_slot(struct hotplug_slot *slot) /* search for subfunctions and disable them first */ if (!(dslot->dev->devfn & 7)) { for (func = 1; func < 8; func++) { - dev = pci_find_slot(dslot->dev->bus->number, + dev = pci_get_slot(dslot->dev->bus, dslot->dev->devfn + func); if (dev) { hslot = get_slot_from_dev(dev); @@ -315,6 +319,7 @@ static int disable_slot(struct hotplug_slot *slot) err("Hotplug slot not found for subfunction of PCI device\n"); return -ENODEV; } + pci_dev_put(dev); } else dbg("No device in slot found\n"); } -- cgit v1.2.3 From d1729ccecd7ba9ceb6dca1c973dbfd87041d0637 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 28 Sep 2006 15:51:21 -0700 Subject: shpchp: fix command completion check This patch fixes the problem that shpchp driver could mis-detect command failures if the system was under heavy load. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 446e9beff046..4826dd158deb 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -302,6 +302,12 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) add_timer(&php_ctlr->int_poll_timer); } +static inline int is_ctrl_busy(struct controller *ctrl) +{ + u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); + return cmd_status & 0x1; +} + /* * Returns 1 if SHPC finishes executing a command within 1 sec, * otherwise returns 0. @@ -309,16 +315,14 @@ static void start_int_poll_timer(struct php_ctlr_state_s *php_ctlr, int sec) static inline int shpc_poll_ctrl_busy(struct controller *ctrl) { int i; - u16 cmd_status = shpc_readw(ctrl, CMD_STATUS); - if (!(cmd_status & 0x1)) + if (!is_ctrl_busy(ctrl)) return 1; /* Check every 0.1 sec for a total of 1 sec */ for (i = 0; i < 10; i++) { msleep(100); - cmd_status = shpc_readw(ctrl, CMD_STATUS); - if (!(cmd_status & 0x1)) + if (!is_ctrl_busy(ctrl)) return 1; } @@ -336,7 +340,7 @@ static inline int shpc_wait_cmd(struct controller *ctrl) else rc = wait_event_interruptible_timeout(ctrl->queue, !ctrl->cmd_busy, timeout); - if (!rc) { + if (!rc && is_ctrl_busy(ctrl)) { retval = -EIO; err("Command not completed in 1000 msec\n"); } else if (rc < 0) { -- cgit v1.2.3 From 6aa562c248e05db993e4a5f405f899c0cfabb7f2 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 28 Sep 2006 15:51:36 -0700 Subject: shpchp: remove unnecessary cmd_busy member from struct controller This patch removes unnecessary cmd_busy member from struct controller. Read command status register instead of using cmd_busy. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp.h | 1 - drivers/pci/hotplug/shpchp_hpc.c | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index c7103ac5cd06..7e7d490622e1 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -103,7 +103,6 @@ struct controller { u32 cap_offset; unsigned long mmio_base; unsigned long mmio_size; - volatile int cmd_busy; }; diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 4826dd158deb..bbe450f098e6 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -339,7 +339,7 @@ static inline int shpc_wait_cmd(struct controller *ctrl) rc = shpc_poll_ctrl_busy(ctrl); else rc = wait_event_interruptible_timeout(ctrl->queue, - !ctrl->cmd_busy, timeout); + !is_ctrl_busy(ctrl), timeout); if (!rc && is_ctrl_busy(ctrl)) { retval = -EIO; err("Command not completed in 1000 msec\n"); @@ -347,7 +347,6 @@ static inline int shpc_wait_cmd(struct controller *ctrl) retval = -EINTR; info("Command was interrupted by a signal\n"); } - ctrl->cmd_busy = 0; return retval; } @@ -378,7 +377,6 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd) /* To make sure the Controller Busy bit is 0 before we send out the * command. */ - slot->ctrl->cmd_busy = 1; shpc_writew(ctrl, CMD, temp_word); /* @@ -928,7 +926,6 @@ static irqreturn_t shpc_isr(int irq, void *dev_id) serr_int &= ~SERR_INTR_RSVDZ_MASK; shpc_writel(ctrl, SERR_INTR_ENABLE, serr_int); - ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } -- cgit v1.2.3 From 662a98fb8de5af4adb56e58f78753cdaa27b6459 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Thu, 5 Oct 2006 12:07:32 +0530 Subject: PCI hotplug: ioremap balanced with iounmap 1. ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. 2. Handle return value correctly Tested (compilation only) with: - allmodconfig Signed-off-by: Amol Lad Cc: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/shpchp_hpc.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index bbe450f098e6..83a5226ba9ed 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -1118,7 +1118,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) { struct php_ctlr_state_s *php_ctlr, *p; void *instance_id = ctrl; - int rc, num_slots = 0; + int rc = -1, num_slots = 0; u8 hp_slot; u32 shpc_base_offset; u32 tempdword, slot_reg, slot_config; @@ -1184,11 +1184,15 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", pdev->vendor, pdev->device, pdev->subsystem_vendor, pdev->subsystem_device); - if (pci_enable_device(pdev)) + rc = pci_enable_device(pdev); + if (rc) { + err("%s: pci_enable_device failed\n", __FUNCTION__); goto abort_free_ctlr; + } if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) { err("%s: cannot reserve MMIO region\n", __FUNCTION__); + rc = -1; goto abort_free_ctlr; } @@ -1197,6 +1201,7 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, ctrl->mmio_size, ctrl->mmio_base); release_mem_region(ctrl->mmio_base, ctrl->mmio_size); + rc = -1; goto abort_free_ctlr; } dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg); @@ -1299,8 +1304,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) */ if (atomic_add_return(1, &shpchp_num_controllers) == 1) { shpchp_wq = create_singlethread_workqueue("shpchpd"); - if (!shpchp_wq) - return -ENOMEM; + if (!shpchp_wq) { + rc = -ENOMEM; + goto abort_free_ctlr; + } } /* @@ -1330,8 +1337,10 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev) /* We end up here for the many possible ways to fail this API. */ abort_free_ctlr: + if (php_ctlr->creg) + iounmap(php_ctlr->creg); kfree(php_ctlr); abort: DBG_LEAVE_ROUTINE - return -1; + return rc; } -- cgit v1.2.3 From 0306ebfa3b45386401f80aa87cb4f7570bf3aadb Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 5 Oct 2006 10:24:31 +0200 Subject: PCI: Improve pci_msi_supported() comments Improve pci_msi_supported() comments. Signed-off-by: Brice Goglin Signed-off-by: Grant Grundler Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index f9fdc54473c4..9fc9a34ef24a 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -627,22 +627,24 @@ static int msix_capability_init(struct pci_dev *dev, * pci_msi_supported - check whether MSI may be enabled on device * @dev: pointer to the pci_dev data structure of MSI device function * - * MSI must be globally enabled and supported by the device and its root - * bus. But, the root bus is not easy to find since some architectures - * have virtual busses on top of the PCI hierarchy (for instance the - * hypertransport bus), while the actual bus where MSI must be supported - * is below. So we test the MSI flag on all parent busses and assume - * that no quirk will ever set the NO_MSI flag on a non-root bus. + * Look at global flags, the device itself, and its parent busses + * to return 0 if MSI are supported for the device. **/ static int pci_msi_supported(struct pci_dev * dev) { struct pci_bus *bus; + /* MSI must be globally enabled and supported by the device */ if (!pci_msi_enable || !dev || dev->no_msi) return -EINVAL; - /* check MSI flags of all parent busses */ + /* Any bridge which does NOT route MSI transactions from it's + * secondary bus to it's primary bus must set NO_MSI flag on + * the secondary pci_bus. + * We expect only arch-specific PCI host bus controller driver + * or quirks for specific PCI bridges to be setting NO_MSI. + */ for (bus = dev->bus; bus; bus = bus->parent) if (bus->bus_flags & PCI_BUS_FLAGS_NO_MSI) return -EINVAL; -- cgit v1.2.3 From 11f242f04c6d886494cc83097cb6def044eabebb Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 10 Oct 2006 14:39:00 -0700 Subject: PCI: quirks: switch quirks code offender to use pci_get API Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 371ab8821f10..e8a7f1b1b2bc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1840,7 +1840,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) /* check HT MSI cap on this chipset and the root one. * a single one having MSI is enough to be sure that MSI are supported. */ - pdev = pci_find_slot(dev->bus->number, 0); + pdev = pci_get_slot(dev->bus, 0); if (dev->subordinate && !msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { printk(KERN_WARNING "PCI: MSI quirk detected. " @@ -1848,6 +1848,7 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev) pci_name(dev)); dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI; } + pci_dev_put(pdev); } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE, quirk_nvidia_ck804_msi_ht_cap); -- cgit v1.2.3 From 29f3eb64634cf96903a3cdb56b1f9a80bebad17d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:20:21 -0700 Subject: pci: Additional search functions In order to finish converting to pci_get_* interfaces we need to add a couple of bits of missing functionaility pci_get_bus_and_slot() provides the equivalent to pci_find_slot() (pci_get_slot is already taken as a name for something similar but not the same) pci_get_device_reverse() is the equivalent of pci_find_device_reverse but refcounting Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/search.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/pci.h | 3 ++- 2 files changed, 72 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d529462d1b53..2f13eba5d5ae 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -139,6 +139,31 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn) return dev; } +/** + * pci_get_bus_and_slot - locate PCI device from a given PCI slot + * @bus: number of PCI bus on which desired PCI device resides + * @devfn: encodes number of PCI slot in which the desired PCI + * device resides and the logical device number within that slot + * in case of multi-function devices. + * + * Given a PCI bus and slot/function number, the desired PCI device + * is located in system global list of PCI devices. If the device + * is found, a pointer to its data structure is returned. If no + * device is found, %NULL is returned. The returned device has its + * reference count bumped by one. + */ + +struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->bus->number == bus && dev->devfn == devfn) + return dev; + } + return NULL; +} + /** * pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids @@ -274,6 +299,45 @@ pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from); } +/** + * pci_get_device_reverse - begin or continue searching for a PCI device by vendor/device id + * @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids + * @device: PCI device id to match, or %PCI_ANY_ID to match all device ids + * @from: Previous PCI device found in search, or %NULL for new search. + * + * Iterates through the list of known PCI devices in the reverse order of + * pci_get_device. + * If a PCI device is found with a matching @vendor and @device, the reference + * count to the device is incremented and a pointer to its device structure + * is returned Otherwise, %NULL is returned. A new search is initiated by + * passing %NULL as the @from argument. Otherwise if @from is not %NULL, + * searches continue from next device on the global list. The reference + * count for @from is always decremented if it is not %NULL. + */ +struct pci_dev * +pci_get_device_reverse(unsigned int vendor, unsigned int device, struct pci_dev *from) +{ + struct list_head *n; + struct pci_dev *dev; + + WARN_ON(in_interrupt()); + down_read(&pci_bus_sem); + n = from ? from->global_list.prev : pci_devices.prev; + + while (n && (n != &pci_devices)) { + dev = pci_dev_g(n); + if ((vendor == PCI_ANY_ID || dev->vendor == vendor) && + (device == PCI_ANY_ID || dev->device == device)) + goto exit; + n = n->prev; + } + dev = NULL; +exit: + dev = pci_dev_get(dev); + up_read(&pci_bus_sem); + pci_dev_put(from); + return dev; +} /** * pci_find_device_reverse - begin or continue searching for a PCI device by vendor/device id @@ -382,12 +446,16 @@ exit: } EXPORT_SYMBOL(pci_dev_present); -EXPORT_SYMBOL(pci_find_bus); -EXPORT_SYMBOL(pci_find_next_bus); EXPORT_SYMBOL(pci_find_device); EXPORT_SYMBOL(pci_find_device_reverse); EXPORT_SYMBOL(pci_find_slot); +/* For boot time work */ +EXPORT_SYMBOL(pci_find_bus); +EXPORT_SYMBOL(pci_find_next_bus); +/* For everyone */ EXPORT_SYMBOL(pci_get_device); +EXPORT_SYMBOL(pci_get_device_reverse); EXPORT_SYMBOL(pci_get_subsys); EXPORT_SYMBOL(pci_get_slot); +EXPORT_SYMBOL(pci_get_bus_and_slot); EXPORT_SYMBOL(pci_get_class); diff --git a/include/linux/pci.h b/include/linux/pci.h index 5c604f5fad67..09bf88fc80c5 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -452,13 +452,14 @@ struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn); int pci_find_capability (struct pci_dev *dev, int cap); int pci_find_next_capability (struct pci_dev *dev, u8 pos, int cap); int pci_find_ext_capability (struct pci_dev *dev, int cap); -struct pci_bus * pci_find_next_bus(const struct pci_bus *from); +struct pci_bus *pci_find_next_bus(const struct pci_bus *from); struct pci_dev *pci_get_device (unsigned int vendor, unsigned int device, struct pci_dev *from); struct pci_dev *pci_get_subsys (unsigned int vendor, unsigned int device, unsigned int ss_vendor, unsigned int ss_device, struct pci_dev *from); struct pci_dev *pci_get_slot (struct pci_bus *bus, unsigned int devfn); +struct pci_dev *pci_get_bus_and_slot (unsigned int bus, unsigned int devfn); struct pci_dev *pci_get_class (unsigned int class, struct pci_dev *from); int pci_dev_present(const struct pci_device_id *ids); -- cgit v1.2.3 From 49c61cca2b6591a28ffa4abb73c718091f569746 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 14 Oct 2006 03:07:30 +0900 Subject: cpcihp_generic: prevent loading without "bridge" parameter cpcihp_generic module requires configured "bridge" module parameter. But it can be loaded successfully without that parameter. Because module init call ends up returning positive value. This patch prevents from loading without setting "bridge" module parameter. Signed-off-by: Akinbou Mita Signed-off-by: Scott Murray Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/cpcihp_generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index e847f0d6c7fe..f3852a6b74ea 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c @@ -84,7 +84,7 @@ static int __init validate_parameters(void) if(!bridge) { info("not configured, disabling."); - return 1; + return -EINVAL; } str = bridge; if(!*str) @@ -147,7 +147,7 @@ static int __init cpcihp_generic_init(void) info(DRIVER_DESC " version: " DRIVER_VERSION); status = validate_parameters(); - if(status != 0) + if (status) return status; r = request_region(port, 1, "#ENUM hotswap signal register"); -- cgit v1.2.3 From 6b4b78fed47e7380dfe9280b154e8b9bfcd4c86c Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Fri, 29 Sep 2006 15:23:23 -0500 Subject: PCI: optionally sort device lists breadth-first Problem: New Dell PowerEdge servers have 2 embedded ethernet ports, which are labeled NIC1 and NIC2 on the chassis, in the BIOS setup screens, and in the printed documentation. Assuming no other add-in ethernet ports in the system, Linux 2.4 kernels name these eth0 and eth1 respectively. Many people have come to expect this naming. Linux 2.6 kernels name these eth1 and eth0 respectively (backwards from expectations). I also have reports that various Sun and HP servers have similar behavior. Root cause: Linux 2.4 kernels walk the pci_devices list, which happens to be sorted in breadth-first order (or pcbios_find_device order on i386, which most often is breadth-first also). 2.6 kernels have both the pci_devices list and the pci_bus_type.klist_devices list, the latter is what is walked at driver load time to match the pci_id tables; this klist happens to be in depth-first order. On systems where, for physical routing reasons, NIC1 appears on a lower bus number than NIC2, but NIC2's bridge is discovered first in the depth-first ordering, NIC2 will be discovered before NIC1. If the list were sorted breadth-first, NIC1 would be discovered before NIC2. A PowerEdge 1955 system has the following topology which easily exhibits the difference between depth-first and breadth-first device lists. -[0000:00]-+-00.0 Intel Corporation 5000P Chipset Memory Controller Hub +-02.0-[0000:03-08]--+-00.0-[0000:04-07]--+-00.0-[0000:05-06]----00.0-[0000:06]----00.0 Broadcom Corporation NetXtreme II BCM5708S Gigabit Ethernet (labeled NIC2, 2.4 kernel name eth1, 2.6 kernel name eth0) +-1c.0-[0000:01-02]----00.0-[0000:02]----00.0 Broadcom Corporation NetXtreme II BCM5708S Gigabit Ethernet (labeled NIC1, 2.4 kernel name eth0, 2.6 kernel name eth1) Other factors, such as device driver load order and the presence of PCI slots at various points in the bus hierarchy further complicate this problem; I'm not trying to solve those here, just restore the device order, and thus basic behavior, that 2.4 kernels had. Solution: The solution can come in multiple steps. Suggested fix #1: kernel Patch below optionally sorts the two device lists into breadth-first ordering to maintain compatibility with 2.4 kernels. It adds two new command line options: pci=bfsort pci=nobfsort to force the sort order, or not, as you wish. It also adds DMI checks for the specific Dell systems which exhibit "backwards" ordering, to make them "right". Suggested fix #2: udev rules from userland Many people also have the expectation that embedded NICs are always discovered before add-in NICs (which this patch does not try to do). Using the PCI IRQ Routing Table provided by system BIOS, it's easy to determine which PCI devices are embedded, or if add-in, which PCI slot they're in. I'm working on a tool that would allow udev to name ethernet devices in ascending embedded, slot 1 .. slot N order, subsort by PCI bus/dev/fn breadth-first. It'll be possible to use it independent of udev as well for those distributions that don't use udev in their installers. Suggested fix #3: system board routing rules One can constrain the system board layout to put NIC1 ahead of NIC2 regardless of breadth-first or depth-first discovery order. This adds a significant level of complexity to board routing, and may not be possible in all instances (witness the above systems from several major manufacturers). I don't want to encourage this particular train of thought too far, at the expense of not doing #1 or #2 above. Feedback appreciated. Patch tested on a Dell PowerEdge 1955 blade with 2.6.18. You'll also note I took some liberty and temporarily break the klist abstraction to simplify and speed up the sort algorithm. I think that's both safe and appropriate in this instance. Signed-off-by: Matt Domsch Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 5 ++ arch/i386/pci/common.c | 59 +++++++++++++++++++++++- arch/i386/pci/pci.h | 7 +++ drivers/pci/probe.c | 92 +++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 1 + 5 files changed, 162 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ff571f9298e0..dd00fd556a60 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1231,6 +1231,11 @@ and is between 256 and 4096 characters. It is defined in the file machine check when some devices' config space is read. But various workarounds are disabled and some IOMMU drivers will not work. + bfsort Sort PCI devices into breadth-first order. + This sorting is done to get a device + order compatible with older (<= 2.4) kernels. + nobfsort Don't sort PCI devices into breadth-first order. + pcmv= [HW,PCMCIA] BadgePAD 4 pd. [PARIDE] diff --git a/arch/i386/pci/common.c b/arch/i386/pci/common.c index 68bce194e688..6d5ace845e44 100644 --- a/arch/i386/pci/common.c +++ b/arch/i386/pci/common.c @@ -20,6 +20,7 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | PCI_PROBE_MMCONF; +int pci_bf_sort; int pci_routeirq; int pcibios_last_bus = -1; unsigned long pirq_table_addr; @@ -117,6 +118,20 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b) pci_read_bridge_bases(b); } +/* + * Only use DMI information to set this if nothing was passed + * on the kernel command line (which was parsed earlier). + */ + +static int __devinit set_bf_sort(struct dmi_system_id *d) +{ + if (pci_bf_sort == pci_bf_sort_default) { + pci_bf_sort = pci_dmi_bf; + printk(KERN_INFO "PCI: %s detected, enabling pci=bfsort.\n", d->ident); + } + return 0; +} + /* * Enable renumbering of PCI bus# ranges to reach all PCI busses (Cardbus) */ @@ -130,11 +145,11 @@ static int __devinit assign_all_busses(struct dmi_system_id *d) } #endif +static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { +#ifdef __i386__ /* * Laptops which need pci=assign-busses to see Cardbus cards */ -static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { -#ifdef __i386__ { .callback = assign_all_busses, .ident = "Samsung X20 Laptop", @@ -144,6 +159,38 @@ static struct dmi_system_id __devinitdata pciprobe_dmi_table[] = { }, }, #endif /* __i386__ */ + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 1950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1950"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 1955", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1955"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 2900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2900"), + }, + }, + { + .callback = set_bf_sort, + .ident = "Dell PowerEdge 2950", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2950"), + }, + }, {} }; @@ -189,6 +236,8 @@ static int __init pcibios_init(void) pcibios_resource_survey(); + if (pci_bf_sort >= pci_force_bf) + pci_sort_breadthfirst(); #ifdef CONFIG_PCI_BIOS if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) pcibios_sort(); @@ -203,6 +252,12 @@ char * __devinit pcibios_setup(char *str) if (!strcmp(str, "off")) { pci_probe = 0; return NULL; + } else if (!strcmp(str, "bfsort")) { + pci_bf_sort = pci_force_bf; + return NULL; + } else if (!strcmp(str, "nobfsort")) { + pci_bf_sort = pci_force_nobf; + return NULL; } #ifdef CONFIG_PCI_BIOS else if (!strcmp(str, "bios")) { diff --git a/arch/i386/pci/pci.h b/arch/i386/pci/pci.h index 1814f74569c6..ad065cebd7b9 100644 --- a/arch/i386/pci/pci.h +++ b/arch/i386/pci/pci.h @@ -30,6 +30,13 @@ extern unsigned int pci_probe; extern unsigned long pirq_table_addr; +enum pci_bf_sort_state { + pci_bf_sort_default, + pci_force_nobf, + pci_force_bf, + pci_dmi_bf, +}; + /* pci-i386.c */ extern unsigned int pcibios_max_latency; diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index a3b0a5eb5054..e159d6604494 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1067,3 +1067,95 @@ EXPORT_SYMBOL(pci_scan_bridge); EXPORT_SYMBOL(pci_scan_single_device); EXPORT_SYMBOL_GPL(pci_scan_child_bus); #endif + +static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b) +{ + if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1; + else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1; + + if (a->bus->number < b->bus->number) return -1; + else if (a->bus->number > b->bus->number) return 1; + + if (a->devfn < b->devfn) return -1; + else if (a->devfn > b->devfn) return 1; + + return 0; +} + +/* + * Yes, this forcably breaks the klist abstraction temporarily. It + * just wants to sort the klist, not change reference counts and + * take/drop locks rapidly in the process. It does all this while + * holding the lock for the list, so objects can't otherwise be + * added/removed while we're swizzling. + */ +static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list) +{ + struct list_head *pos; + struct klist_node *n; + struct device *dev; + struct pci_dev *b; + + list_for_each(pos, list) { + n = container_of(pos, struct klist_node, n_node); + dev = container_of(n, struct device, knode_bus); + b = to_pci_dev(dev); + if (pci_sort_bf_cmp(a, b) <= 0) { + list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node); + return; + } + } + list_move_tail(&a->dev.knode_bus.n_node, list); +} + +static void __init pci_sort_breadthfirst_klist(void) +{ + LIST_HEAD(sorted_devices); + struct list_head *pos, *tmp; + struct klist_node *n; + struct device *dev; + struct pci_dev *pdev; + + spin_lock(&pci_bus_type.klist_devices.k_lock); + list_for_each_safe(pos, tmp, &pci_bus_type.klist_devices.k_list) { + n = container_of(pos, struct klist_node, n_node); + dev = container_of(n, struct device, knode_bus); + pdev = to_pci_dev(dev); + pci_insertion_sort_klist(pdev, &sorted_devices); + } + list_splice(&sorted_devices, &pci_bus_type.klist_devices.k_list); + spin_unlock(&pci_bus_type.klist_devices.k_lock); +} + +static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list) +{ + struct pci_dev *b; + + list_for_each_entry(b, list, global_list) { + if (pci_sort_bf_cmp(a, b) <= 0) { + list_move_tail(&a->global_list, &b->global_list); + return; + } + } + list_move_tail(&a->global_list, list); +} + +static void __init pci_sort_breadthfirst_devices(void) +{ + LIST_HEAD(sorted_devices); + struct pci_dev *dev, *tmp; + + down_write(&pci_bus_sem); + list_for_each_entry_safe(dev, tmp, &pci_devices, global_list) { + pci_insertion_sort_devices(dev, &sorted_devices); + } + list_splice(&sorted_devices, &pci_devices); + up_write(&pci_bus_sem); +} + +void __init pci_sort_breadthfirst(void) +{ + pci_sort_breadthfirst_devices(); + pci_sort_breadthfirst_klist(); +} + diff --git a/include/linux/pci.h b/include/linux/pci.h index 09bf88fc80c5..4689e2a699c0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -443,6 +443,7 @@ extern void pci_remove_bus(struct pci_bus *b); extern void pci_remove_bus_device(struct pci_dev *dev); extern void pci_stop_bus_device(struct pci_dev *dev); void pci_setup_cardbus(struct pci_bus *bus); +extern void pci_sort_breadthfirst(void); /* Generic PCI functions exported to card drivers */ -- cgit v1.2.3 From fb5f4d7a74a140f8e033d1e6854989e88c36c6b8 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Fri, 29 Sep 2006 10:30:27 -0700 Subject: change pci hotplug subsystem maintainer to Kristen Here's a patch adding me to the maintainers file for the pci hotplug subsystem, as we discussed. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 4 ++-- drivers/pci/hotplug/pci_hotplug.h | 2 +- drivers/pci/hotplug/pci_hotplug_core.c | 4 +--- 3 files changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 5305dd69095b..9b6b88268d3f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2309,8 +2309,8 @@ T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ S: Supported PCI HOTPLUG CORE -P: Greg Kroah-Hartman -M: gregkh@suse.de +P: Kristen Carlson Accardi +M: kristen.c.accardi@intel.com S: Supported PCI HOTPLUG COMPAQ DRIVER diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h index 772523dc3860..a675a05c4091 100644 --- a/drivers/pci/hotplug/pci_hotplug.h +++ b/drivers/pci/hotplug/pci_hotplug.h @@ -22,7 +22,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to + * Send feedback to * */ #ifndef _PCI_HOTPLUG_H diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index e2823ea9c4ed..fa666d0cc489 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -21,9 +21,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Send feedback to - * - * Filesystem portion based on work done by Pat Mochel on ddfs/driverfs + * Send feedback to * */ -- cgit v1.2.3 From 7a54f25cef6c763f16c9fd49ae382de162147873 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Oct 2006 20:05:19 -0700 Subject: PCI Hotplug: move pci_hotplug.h to include/linux/ This makes it possible to build pci hotplug drivers outside of the main kernel tree, and Sam keeps telling me to move local header files to their proper places... Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpi_pcihp.c | 2 +- drivers/pci/hotplug/acpiphp.h | 2 +- drivers/pci/hotplug/acpiphp_core.c | 2 +- drivers/pci/hotplug/acpiphp_glue.c | 2 +- drivers/pci/hotplug/acpiphp_ibm.c | 1 - drivers/pci/hotplug/cpci_hotplug_core.c | 2 +- drivers/pci/hotplug/cpci_hotplug_pci.c | 2 +- drivers/pci/hotplug/cpqphp.h | 1 - drivers/pci/hotplug/cpqphp_core.c | 1 + drivers/pci/hotplug/cpqphp_ctrl.c | 1 + drivers/pci/hotplug/cpqphp_nvram.c | 1 + drivers/pci/hotplug/cpqphp_pci.c | 1 + drivers/pci/hotplug/cpqphp_sysfs.c | 1 + drivers/pci/hotplug/fakephp.c | 2 +- drivers/pci/hotplug/ibmphp.h | 2 +- drivers/pci/hotplug/pci_hotplug.h | 236 -------------------------------- drivers/pci/hotplug/pci_hotplug_core.c | 7 +- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/pcihp_skeleton.c | 2 +- drivers/pci/hotplug/rpadlpar_sysfs.c | 2 +- drivers/pci/hotplug/rpaphp_core.c | 2 +- drivers/pci/hotplug/sgi_hotplug.c | 2 +- drivers/pci/hotplug/shpchp.h | 3 +- include/linux/pci_hotplug.h | 236 ++++++++++++++++++++++++++++++++ 24 files changed, 258 insertions(+), 257 deletions(-) delete mode 100644 drivers/pci/hotplug/pci_hotplug.h create mode 100644 include/linux/pci_hotplug.h (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 51cb9f817c22..270a33cc08f6 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -29,10 +29,10 @@ #include #include #include +#include #include #include #include -#include "pci_hotplug.h" #define MY_NAME "acpi_pcihp" diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7fff07e877c7..59c5b242d86d 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -38,7 +38,7 @@ #include #include /* for KOBJ_NAME_LEN */ #include -#include "pci_hotplug.h" +#include #define dbg(format, arg...) \ do { \ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index e2fef60c2d06..c57d9d5ce84e 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -37,10 +37,10 @@ #include #include +#include #include #include #include -#include "pci_hotplug.h" #include "acpiphp.h" #define MY_NAME "acpiphp" diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 83e8e4412de5..c44311ac2fd3 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -45,11 +45,11 @@ #include #include +#include #include #include #include "../pci.h" -#include "pci_hotplug.h" #include "acpiphp.h" static LIST_HEAD(bridge_list); diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index d0a07d9ab30c..bd40aee10e16 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -35,7 +35,6 @@ #include #include "acpiphp.h" -#include "pci_hotplug.h" #define DRIVER_VERSION "1.0.1" #define DRIVER_AUTHOR "Irene Zubarev , Vernon Mauery " diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index d06ab4045134..684551559d44 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -29,12 +29,12 @@ #include #include #include +#include #include #include #include #include #include -#include "pci_hotplug.h" #include "cpci_hotplug.h" #define DRIVER_AUTHOR "Scott Murray " diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index 4afcaffd031c..7b1beaad2752 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -26,9 +26,9 @@ #include #include #include +#include #include #include "../pci.h" -#include "pci_hotplug.h" #include "cpci_hotplug.h" #define MY_NAME "cpci_hotplug" diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index ea040c32f47d..298ad7f3f4f4 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -28,7 +28,6 @@ #ifndef _CPQPHP_H #define _CPQPHP_H -#include "pci_hotplug.h" #include #include /* for read? and write? functions */ #include /* for delays */ diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 1fc259913b68..5617cfdadc5c 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 3ec2ad7db49a..79ff6b4de3a6 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "cpqphp.h" static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index cf0878917537..298a6cfd8406 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include "cpqphp.h" diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 0d9688952f4a..fc7c74d72595 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "../pci.h" #include "cpqphp.h" #include "cpqphp_nvram.h" diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 5bab666cd67e..634f74d919d3 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "cpqphp.h" diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c index aaeb1129132e..e27907c91d92 100644 --- a/drivers/pci/hotplug/fakephp.c +++ b/drivers/pci/hotplug/fakephp.c @@ -35,10 +35,10 @@ #include #include #include +#include #include #include #include -#include "pci_hotplug.h" #include "../pci.h" #if !defined(MODULE) diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index dba6d8ca9bda..612d96301509 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -30,7 +30,7 @@ * */ -#include "pci_hotplug.h" +#include extern int ibmphp_debug; diff --git a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h deleted file mode 100644 index a675a05c4091..000000000000 --- a/drivers/pci/hotplug/pci_hotplug.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * PCI HotPlug Core Functions - * - * Copyright (C) 1995,2001 Compaq Computer Corporation - * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (C) 2001 IBM Corp. - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License 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, GOOD TITLE or - * NON INFRINGEMENT. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Send feedback to - * - */ -#ifndef _PCI_HOTPLUG_H -#define _PCI_HOTPLUG_H - - -/* These values come from the PCI Hotplug Spec */ -enum pci_bus_speed { - PCI_SPEED_33MHz = 0x00, - PCI_SPEED_66MHz = 0x01, - PCI_SPEED_66MHz_PCIX = 0x02, - PCI_SPEED_100MHz_PCIX = 0x03, - PCI_SPEED_133MHz_PCIX = 0x04, - PCI_SPEED_66MHz_PCIX_ECC = 0x05, - PCI_SPEED_100MHz_PCIX_ECC = 0x06, - PCI_SPEED_133MHz_PCIX_ECC = 0x07, - PCI_SPEED_66MHz_PCIX_266 = 0x09, - PCI_SPEED_100MHz_PCIX_266 = 0x0a, - PCI_SPEED_133MHz_PCIX_266 = 0x0b, - PCI_SPEED_66MHz_PCIX_533 = 0x11, - PCI_SPEED_100MHz_PCIX_533 = 0x12, - PCI_SPEED_133MHz_PCIX_533 = 0x13, - PCI_SPEED_UNKNOWN = 0xff, -}; - -/* These values come from the PCI Express Spec */ -enum pcie_link_width { - PCIE_LNK_WIDTH_RESRV = 0x00, - PCIE_LNK_X1 = 0x01, - PCIE_LNK_X2 = 0x02, - PCIE_LNK_X4 = 0x04, - PCIE_LNK_X8 = 0x08, - PCIE_LNK_X12 = 0x0C, - PCIE_LNK_X16 = 0x10, - PCIE_LNK_X32 = 0x20, - PCIE_LNK_WIDTH_UNKNOWN = 0xFF, -}; - -enum pcie_link_speed { - PCIE_2PT5GB = 0x14, - PCIE_LNK_SPEED_UNKNOWN = 0xFF, -}; - -struct hotplug_slot; -struct hotplug_slot_attribute { - struct attribute attr; - ssize_t (*show)(struct hotplug_slot *, char *); - ssize_t (*store)(struct hotplug_slot *, const char *, size_t); -}; -#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr); - -/** - * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use - * @owner: The module owner of this structure - * @enable_slot: Called when the user wants to enable a specific pci slot - * @disable_slot: Called when the user wants to disable a specific pci slot - * @set_attention_status: Called to set the specific slot's attention LED to - * the specified value - * @hardware_test: Called to run a specified hardware test on the specified - * slot. - * @get_power_status: Called to get the current power status of a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_attention_status: Called to get the current attention status of a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_latch_status: Called to get the current latch status of a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_adapter_status: Called to get see if an adapter is present in the slot or not. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_address: Called to get pci address of a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_max_bus_speed: Called to get the max bus speed for a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * @get_cur_bus_speed: Called to get the current bus speed for a slot. - * If this field is NULL, the value passed in the struct hotplug_slot_info - * will be used when this value is requested by a user. - * - * The table of function pointers that is passed to the hotplug pci core by a - * hotplug pci driver. These functions are called by the hotplug pci core when - * the user wants to do something to a specific slot (query it for information, - * set an LED, enable / disable power, etc.) - */ -struct hotplug_slot_ops { - struct module *owner; - int (*enable_slot) (struct hotplug_slot *slot); - int (*disable_slot) (struct hotplug_slot *slot); - int (*set_attention_status) (struct hotplug_slot *slot, u8 value); - int (*hardware_test) (struct hotplug_slot *slot, u32 value); - int (*get_power_status) (struct hotplug_slot *slot, u8 *value); - int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); - int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); - int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); - int (*get_address) (struct hotplug_slot *slot, u32 *value); - int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); - int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); -}; - -/** - * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot - * @power: if power is enabled or not (1/0) - * @attention_status: if the attention light is enabled or not (1/0) - * @latch_status: if the latch (if any) is open or closed (1/0) - * @adapter_present: if there is a pci board present in the slot or not (1/0) - * @address: (domain << 16 | bus << 8 | dev) - * - * Used to notify the hotplug pci core of the status of a specific slot. - */ -struct hotplug_slot_info { - u8 power_status; - u8 attention_status; - u8 latch_status; - u8 adapter_status; - u32 address; - enum pci_bus_speed max_bus_speed; - enum pci_bus_speed cur_bus_speed; -}; - -/** - * struct hotplug_slot - used to register a physical slot with the hotplug pci core - * @name: the name of the slot being registered. This string must - * be unique amoung slots registered on this system. - * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot - * @info: pointer to the &struct hotplug_slot_info for the initial values for - * this slot. - * @release: called during pci_hp_deregister to free memory allocated in a - * hotplug_slot structure. - * @private: used by the hotplug pci controller driver to store whatever it - * needs. - */ -struct hotplug_slot { - char *name; - struct hotplug_slot_ops *ops; - struct hotplug_slot_info *info; - void (*release) (struct hotplug_slot *slot); - void *private; - - /* Variables below this are for use only by the hotplug pci core. */ - struct list_head slot_list; - struct kobject kobj; -}; -#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) - -extern int pci_hp_register (struct hotplug_slot *slot); -extern int pci_hp_deregister (struct hotplug_slot *slot); -extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, - struct hotplug_slot_info *info); -extern struct subsystem pci_hotplug_slots_subsys; - -/* PCI Setting Record (Type 0) */ -struct hpp_type0 { - u32 revision; - u8 cache_line_size; - u8 latency_timer; - u8 enable_serr; - u8 enable_perr; -}; - -/* PCI-X Setting Record (Type 1) */ -struct hpp_type1 { - u32 revision; - u8 max_mem_read; - u8 avg_max_split; - u16 tot_max_split; -}; - -/* PCI Express Setting Record (Type 2) */ -struct hpp_type2 { - u32 revision; - u32 unc_err_mask_and; - u32 unc_err_mask_or; - u32 unc_err_sever_and; - u32 unc_err_sever_or; - u32 cor_err_mask_and; - u32 cor_err_mask_or; - u32 adv_err_cap_and; - u32 adv_err_cap_or; - u16 pci_exp_devctl_and; - u16 pci_exp_devctl_or; - u16 pci_exp_lnkctl_and; - u16 pci_exp_lnkctl_or; - u32 sec_unc_err_sever_and; - u32 sec_unc_err_sever_or; - u32 sec_unc_err_mask_and; - u32 sec_unc_err_mask_or; -}; - -struct hotplug_params { - struct hpp_type0 *t0; /* Type0: NULL if not available */ - struct hpp_type1 *t1; /* Type1: NULL if not available */ - struct hpp_type2 *t2; /* Type2: NULL if not available */ - struct hpp_type0 type0_data; - struct hpp_type1 type1_data; - struct hpp_type2 type2_data; -}; - -#ifdef CONFIG_ACPI -#include -#include -#include -extern acpi_status acpi_run_oshp(acpi_handle handle); -extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, - struct hotplug_params *hpp); -int acpi_root_bridge(acpi_handle handle); -#endif -#endif - diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index fa666d0cc489..f5d632e72323 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include #include @@ -37,11 +39,8 @@ #include #include #include +#include #include -#include -#include -#include "pci_hotplug.h" - #define MY_NAME "pci_hotplug" diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 30f021c55fe5..4fb12fcda563 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -31,11 +31,11 @@ #include #include +#include #include #include /* signal_pending() */ #include #include -#include "pci_hotplug.h" #define MY_NAME "pciehp" diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 2b9e10e38613..50bcd3fe61da 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -33,8 +33,8 @@ #include #include #include +#include #include -#include "pci_hotplug.h" #define SLOT_NAME_SIZE 10 struct slot { diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c index db69be85b458..6c5be3ff578c 100644 --- a/drivers/pci/hotplug/rpadlpar_sysfs.c +++ b/drivers/pci/hotplug/rpadlpar_sysfs.c @@ -14,7 +14,7 @@ */ #include #include -#include "pci_hotplug.h" +#include #include "rpadlpar.h" #define DLPAR_KOBJ_NAME "control" diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 7288a3eccfb3..141486df235b 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +37,6 @@ #include "../pci.h" /* for pci_add_new_bus */ /* and pci_do_scan_bus */ #include "rpaphp.h" -#include "pci_hotplug.h" int debug; static struct semaphore rpaphp_sem; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index f31d83c2c633..b62ad31a9739 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include "../pci.h" -#include "pci_hotplug.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)"); diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index 7e7d490622e1..ea2087c34149 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -31,12 +31,11 @@ #include #include +#include #include #include /* signal_pending(), struct timer_list */ #include -#include "pci_hotplug.h" - #if !defined(MODULE) #define MY_NAME "shpchp" #else diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h new file mode 100644 index 000000000000..a675a05c4091 --- /dev/null +++ b/include/linux/pci_hotplug.h @@ -0,0 +1,236 @@ +/* + * PCI HotPlug Core Functions + * + * Copyright (C) 1995,2001 Compaq Computer Corporation + * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2001 IBM Corp. + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Send feedback to + * + */ +#ifndef _PCI_HOTPLUG_H +#define _PCI_HOTPLUG_H + + +/* These values come from the PCI Hotplug Spec */ +enum pci_bus_speed { + PCI_SPEED_33MHz = 0x00, + PCI_SPEED_66MHz = 0x01, + PCI_SPEED_66MHz_PCIX = 0x02, + PCI_SPEED_100MHz_PCIX = 0x03, + PCI_SPEED_133MHz_PCIX = 0x04, + PCI_SPEED_66MHz_PCIX_ECC = 0x05, + PCI_SPEED_100MHz_PCIX_ECC = 0x06, + PCI_SPEED_133MHz_PCIX_ECC = 0x07, + PCI_SPEED_66MHz_PCIX_266 = 0x09, + PCI_SPEED_100MHz_PCIX_266 = 0x0a, + PCI_SPEED_133MHz_PCIX_266 = 0x0b, + PCI_SPEED_66MHz_PCIX_533 = 0x11, + PCI_SPEED_100MHz_PCIX_533 = 0x12, + PCI_SPEED_133MHz_PCIX_533 = 0x13, + PCI_SPEED_UNKNOWN = 0xff, +}; + +/* These values come from the PCI Express Spec */ +enum pcie_link_width { + PCIE_LNK_WIDTH_RESRV = 0x00, + PCIE_LNK_X1 = 0x01, + PCIE_LNK_X2 = 0x02, + PCIE_LNK_X4 = 0x04, + PCIE_LNK_X8 = 0x08, + PCIE_LNK_X12 = 0x0C, + PCIE_LNK_X16 = 0x10, + PCIE_LNK_X32 = 0x20, + PCIE_LNK_WIDTH_UNKNOWN = 0xFF, +}; + +enum pcie_link_speed { + PCIE_2PT5GB = 0x14, + PCIE_LNK_SPEED_UNKNOWN = 0xFF, +}; + +struct hotplug_slot; +struct hotplug_slot_attribute { + struct attribute attr; + ssize_t (*show)(struct hotplug_slot *, char *); + ssize_t (*store)(struct hotplug_slot *, const char *, size_t); +}; +#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr); + +/** + * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use + * @owner: The module owner of this structure + * @enable_slot: Called when the user wants to enable a specific pci slot + * @disable_slot: Called when the user wants to disable a specific pci slot + * @set_attention_status: Called to set the specific slot's attention LED to + * the specified value + * @hardware_test: Called to run a specified hardware test on the specified + * slot. + * @get_power_status: Called to get the current power status of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_attention_status: Called to get the current attention status of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_latch_status: Called to get the current latch status of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_adapter_status: Called to get see if an adapter is present in the slot or not. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_address: Called to get pci address of a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_max_bus_speed: Called to get the max bus speed for a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * @get_cur_bus_speed: Called to get the current bus speed for a slot. + * If this field is NULL, the value passed in the struct hotplug_slot_info + * will be used when this value is requested by a user. + * + * The table of function pointers that is passed to the hotplug pci core by a + * hotplug pci driver. These functions are called by the hotplug pci core when + * the user wants to do something to a specific slot (query it for information, + * set an LED, enable / disable power, etc.) + */ +struct hotplug_slot_ops { + struct module *owner; + int (*enable_slot) (struct hotplug_slot *slot); + int (*disable_slot) (struct hotplug_slot *slot); + int (*set_attention_status) (struct hotplug_slot *slot, u8 value); + int (*hardware_test) (struct hotplug_slot *slot, u32 value); + int (*get_power_status) (struct hotplug_slot *slot, u8 *value); + int (*get_attention_status) (struct hotplug_slot *slot, u8 *value); + int (*get_latch_status) (struct hotplug_slot *slot, u8 *value); + int (*get_adapter_status) (struct hotplug_slot *slot, u8 *value); + int (*get_address) (struct hotplug_slot *slot, u32 *value); + int (*get_max_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); + int (*get_cur_bus_speed) (struct hotplug_slot *slot, enum pci_bus_speed *value); +}; + +/** + * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot + * @power: if power is enabled or not (1/0) + * @attention_status: if the attention light is enabled or not (1/0) + * @latch_status: if the latch (if any) is open or closed (1/0) + * @adapter_present: if there is a pci board present in the slot or not (1/0) + * @address: (domain << 16 | bus << 8 | dev) + * + * Used to notify the hotplug pci core of the status of a specific slot. + */ +struct hotplug_slot_info { + u8 power_status; + u8 attention_status; + u8 latch_status; + u8 adapter_status; + u32 address; + enum pci_bus_speed max_bus_speed; + enum pci_bus_speed cur_bus_speed; +}; + +/** + * struct hotplug_slot - used to register a physical slot with the hotplug pci core + * @name: the name of the slot being registered. This string must + * be unique amoung slots registered on this system. + * @ops: pointer to the &struct hotplug_slot_ops to be used for this slot + * @info: pointer to the &struct hotplug_slot_info for the initial values for + * this slot. + * @release: called during pci_hp_deregister to free memory allocated in a + * hotplug_slot structure. + * @private: used by the hotplug pci controller driver to store whatever it + * needs. + */ +struct hotplug_slot { + char *name; + struct hotplug_slot_ops *ops; + struct hotplug_slot_info *info; + void (*release) (struct hotplug_slot *slot); + void *private; + + /* Variables below this are for use only by the hotplug pci core. */ + struct list_head slot_list; + struct kobject kobj; +}; +#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) + +extern int pci_hp_register (struct hotplug_slot *slot); +extern int pci_hp_deregister (struct hotplug_slot *slot); +extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, + struct hotplug_slot_info *info); +extern struct subsystem pci_hotplug_slots_subsys; + +/* PCI Setting Record (Type 0) */ +struct hpp_type0 { + u32 revision; + u8 cache_line_size; + u8 latency_timer; + u8 enable_serr; + u8 enable_perr; +}; + +/* PCI-X Setting Record (Type 1) */ +struct hpp_type1 { + u32 revision; + u8 max_mem_read; + u8 avg_max_split; + u16 tot_max_split; +}; + +/* PCI Express Setting Record (Type 2) */ +struct hpp_type2 { + u32 revision; + u32 unc_err_mask_and; + u32 unc_err_mask_or; + u32 unc_err_sever_and; + u32 unc_err_sever_or; + u32 cor_err_mask_and; + u32 cor_err_mask_or; + u32 adv_err_cap_and; + u32 adv_err_cap_or; + u16 pci_exp_devctl_and; + u16 pci_exp_devctl_or; + u16 pci_exp_lnkctl_and; + u16 pci_exp_lnkctl_or; + u32 sec_unc_err_sever_and; + u32 sec_unc_err_sever_or; + u32 sec_unc_err_mask_and; + u32 sec_unc_err_mask_or; +}; + +struct hotplug_params { + struct hpp_type0 *t0; /* Type0: NULL if not available */ + struct hpp_type1 *t1; /* Type1: NULL if not available */ + struct hpp_type2 *t2; /* Type2: NULL if not available */ + struct hpp_type0 type0_data; + struct hpp_type1 type1_data; + struct hpp_type2 type2_data; +}; + +#ifdef CONFIG_ACPI +#include +#include +#include +extern acpi_status acpi_run_oshp(acpi_handle handle); +extern acpi_status acpi_get_hp_params_from_firmware(struct pci_bus *bus, + struct hotplug_params *hpp); +int acpi_root_bridge(acpi_handle handle); +#endif +#endif + -- cgit v1.2.3 From 0fbf116d120a2dc5d808204c7d86ad35f7d7846f Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Wed, 27 Sep 2006 23:38:08 +0200 Subject: Driver core: plug device probe memory leak Make sure data is freed if the kthread fails to start. Signed-off-by: Duncan Sands Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index b5f43c3e44fa..ef7db6939cbf 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -178,7 +178,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) probe_task = kthread_run(really_probe, data, "probe-%s", dev->bus_id); if (IS_ERR(probe_task)) - ret = PTR_ERR(probe_task); + ret = really_probe(data); } else ret = really_probe(data); -- cgit v1.2.3 From 310a922d4307ed38b37982a6f93b11fdf3b8dcb1 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 23 Sep 2006 23:35:04 -0600 Subject: Fix dev_printk() is now GPL-only Make dev_printk usable from non-GPL modules again dev_printk now calls dev_driver_string. We want even proprietary modules to be calling dev_printk, so the export of dev_driver_string needs to be non-GPL-only. Signed-off-by: Matthew Wilcox Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index b224bb43ff63..aee3743bd4a3 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -44,7 +44,7 @@ const char *dev_driver_string(struct device *dev) return dev->driver ? dev->driver->name : (dev->bus ? dev->bus->name : ""); } -EXPORT_SYMBOL_GPL(dev_driver_string); +EXPORT_SYMBOL(dev_driver_string); #define to_dev(obj) container_of(obj, struct device, kobj) #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) -- cgit v1.2.3 From f0e1761ac528e9d28f3ba06bd268ec41fe872ac8 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:00 +0200 Subject: driver core fixes: sysfs_create_link() retval check in class.c Check for return value of sysfs_create_link() in class_device_add(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/class.c b/drivers/base/class.c index b32b77ff2dcd..0ff267a248db 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -562,7 +562,10 @@ int class_device_add(struct class_device *class_dev) goto out2; /* add the needed attributes to this device */ - sysfs_create_link(&class_dev->kobj, &parent_class->subsys.kset.kobj, "subsystem"); + error = sysfs_create_link(&class_dev->kobj, + &parent_class->subsys.kset.kobj, "subsystem"); + if (error) + goto out3; class_dev->uevent_attr.attr.name = "uevent"; class_dev->uevent_attr.attr.mode = S_IWUSR; class_dev->uevent_attr.attr.owner = parent_class->owner; -- cgit v1.2.3 From 1bb6881acae1c4f11a6e86f04df32ba45e95031d Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:04 +0200 Subject: driver core fixes: bus_add_attrs() retval check Check return value of bus_add_attrs() in bus_register(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 12173d16bea7..b90f6e6f6442 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -732,11 +732,15 @@ int bus_register(struct bus_type * bus) klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put); klist_init(&bus->klist_drivers, NULL, NULL); - bus_add_attrs(bus); + retval = bus_add_attrs(bus); + if (retval) + goto bus_attrs_fail; pr_debug("bus type '%s' registered\n", bus->name); return 0; +bus_attrs_fail: + kset_unregister(&bus->drivers); bus_drivers_fail: kset_unregister(&bus->devices); bus_devices_fail: -- cgit v1.2.3 From 513e7337adc32cdfbffecb99953e45a44e812c2d Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:08 +0200 Subject: driver core fixes: bus_add_device() cleanup on error Correct cleanup in the error path of bus_add_device(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index b90f6e6f6442..d516f7d5f168 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -372,19 +372,30 @@ int bus_add_device(struct device * dev) pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); error = device_add_attrs(bus, dev); if (error) - goto out; + goto out_put; error = sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); if (error) - goto out; + goto out_id; error = sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "subsystem"); if (error) - goto out; + goto out_subsys; error = sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); + if (error) + goto out_deprecated; } -out: + return 0; + +out_deprecated: + sysfs_remove_link(&dev->kobj, "subsystem"); +out_subsys: + sysfs_remove_link(&bus->devices.kobj, dev->bus_id); +out_id: + device_remove_attrs(bus, dev); +out_put: + put_bus(dev->bus); return error; } -- cgit v1.2.3 From a306eea40952e6365301e8a2f7d5ffa9c6a1921b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:13 +0200 Subject: driver core fixes: device_add() cleanup on error Check for return code of device_create_file() and correct cleanup in the error case in device_add(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index aee3743bd4a3..365f709715ef 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -433,14 +433,16 @@ int device_add(struct device *dev) if (dev->driver) dev->uevent_attr.attr.owner = dev->driver->owner; dev->uevent_attr.store = store_uevent; - device_create_file(dev, &dev->uevent_attr); + error = device_create_file(dev, &dev->uevent_attr); + if (error) + goto attrError; if (MAJOR(dev->devt)) { struct device_attribute *attr; attr = kzalloc(sizeof(*attr), GFP_KERNEL); if (!attr) { error = -ENOMEM; - goto PMError; + goto ueventattrError; } attr->attr.name = "dev"; attr->attr.mode = S_IRUGO; @@ -450,7 +452,7 @@ int device_add(struct device *dev) error = device_create_file(dev, attr); if (error) { kfree(attr); - goto attrError; + goto ueventattrError; } dev->devt_attr = attr; @@ -507,6 +509,8 @@ int device_add(struct device *dev) device_remove_file(dev, dev->devt_attr); kfree(dev->devt_attr); } + ueventattrError: + device_remove_file(dev, &dev->uevent_attr); attrError: kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); -- cgit v1.2.3 From 141ecc5320147d363d060cfc8042d197a3cdd496 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:27 +0200 Subject: driver core fixes: device_create_file() retval check in dmapool.c Check for device_create_file() return value in dma_pool_create(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/dmapool.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index 33c5cce1560b..b2efbd4cf710 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c @@ -141,11 +141,20 @@ dma_pool_create (const char *name, struct device *dev, init_waitqueue_head (&retval->waitq); if (dev) { + int ret; + down (&pools_lock); if (list_empty (&dev->dma_pools)) - device_create_file (dev, &dev_attr_pools); + ret = device_create_file (dev, &dev_attr_pools); + else + ret = 0; /* note: not currently insisting "name" be unique */ - list_add (&retval->pools, &dev->dma_pools); + if (!ret) + list_add (&retval->pools, &dev->dma_pools); + else { + kfree(retval); + retval = NULL; + } up (&pools_lock); } else INIT_LIST_HEAD (&retval->pools); -- cgit v1.2.3 From 221c324a336770a911b16bda02b9f4adad506a35 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 22 Sep 2006 11:37:32 +0200 Subject: driver core fixes: sysfs_create_group() retval in topology.c Return the return value of sysfs_create_group() in topology_add_dev(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/topology.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3ef9d514b916..28dccb730af9 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -97,8 +97,7 @@ static struct attribute_group topology_attr_group = { /* Add/Remove cpu_topology interface for CPU device */ static int __cpuinit topology_add_dev(struct sys_device * sys_dev) { - sysfs_create_group(&sys_dev->kobj, &topology_attr_group); - return 0; + return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); } static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) -- cgit v1.2.3 From 952ab431cd36c7ab573f685af8679c3677cbdc29 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Thu, 28 Sep 2006 23:56:01 +0200 Subject: Driver core: Don't leak 'old_class_name' in drivers/base/core.c::device_rename() If kmalloc() fails to allocate space for 'old_symlink_name' in drivers/base/core.c::device_rename(), then we'll leak 'old_class_name'. Spotted by the Coverity checker. Signed-off-by: Jesper Juhl Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 365f709715ef..41f3dca55cd0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -809,8 +809,10 @@ int device_rename(struct device *dev, char *new_name) if (dev->class) { old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); - if (!old_symlink_name) - return -ENOMEM; + if (!old_symlink_name) { + error = -ENOMEM; + goto out_free_old_class; + } strlcpy(old_symlink_name, dev->bus_id, BUS_ID_SIZE); } @@ -834,9 +836,10 @@ int device_rename(struct device *dev, char *new_name) } put_device(dev); - kfree(old_class_name); kfree(new_class_name); kfree(old_symlink_name); + out_free_old_class: + kfree(old_class_name); return error; } -- cgit v1.2.3 From f70fa6296c2ec8f541f0a9b406ccc2d9d127d639 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Oct 2006 17:03:24 -0400 Subject: Driver core: Don't ignore error returns from probing This patch (as797) fixes device_add() in the driver core. It needs to pay attention when the driver for a new device reports an error. At the same time, since bus_remove_device() undoes the effects of both bus_add_device() and bus_attach_device(), it needs to check whether the bus_attach_device step failed. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 6 ++++-- drivers/base/core.c | 5 ++++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d516f7d5f168..d7c5ea246a0b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -439,8 +439,10 @@ void bus_remove_device(struct device * dev) sysfs_remove_link(&dev->kobj, "bus"); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); device_remove_attrs(dev->bus, dev); - dev->is_registered = 0; - klist_del(&dev->knode_bus); + if (dev->is_registered) { + dev->is_registered = 0; + klist_del(&dev->knode_bus); + } pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); device_release_driver(dev); put_bus(dev->bus); diff --git a/drivers/base/core.c b/drivers/base/core.c index 41f3dca55cd0..68ad11af22b4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -479,7 +479,8 @@ int device_add(struct device *dev) if ((error = bus_add_device(dev))) goto BusError; kobject_uevent(&dev->kobj, KOBJ_ADD); - bus_attach_device(dev); + if ((error = bus_attach_device(dev))) + goto AttachError; if (parent) klist_add_tail(&dev->knode_parent, &parent->klist_children); @@ -498,6 +499,8 @@ int device_add(struct device *dev) kfree(class_name); put_device(dev); return error; + AttachError: + bus_remove_device(dev); BusError: device_pm_remove(dev); PMError: -- cgit v1.2.3 From d9fd4d3b317a231e47f31d64d66c8cc7765d458f Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 4 Oct 2006 07:48:03 -0400 Subject: Driver core: bus: remove indentation level Before potentially fixing up these functions, this cosmetic change reduces the indentation level to make the code easier to read and maintain. No functional changes at all. Signed-off-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 77 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d7c5ea246a0b..7d8a7ce73fb3 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -518,34 +518,36 @@ int bus_add_driver(struct device_driver *drv) struct bus_type * bus = get_bus(drv->bus); int error = 0; - if (bus) { - pr_debug("bus %s: add driver %s\n", bus->name, drv->name); - error = kobject_set_name(&drv->kobj, "%s", drv->name); - if (error) - goto out_put_bus; - drv->kobj.kset = &bus->drivers; - if ((error = kobject_register(&drv->kobj))) - goto out_put_bus; - - error = driver_attach(drv); - if (error) - goto out_unregister; - klist_add_tail(&drv->knode_bus, &bus->klist_drivers); - module_add_driver(drv->owner, drv); - - error = driver_add_attrs(bus, drv); - if (error) { - /* How the hell do we get out of this pickle? Give up */ - printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", - __FUNCTION__, drv->name); - } - error = add_bind_files(drv); - if (error) { - /* Ditto */ - printk(KERN_ERR "%s: add_bind_files(%s) failed\n", - __FUNCTION__, drv->name); - } + if (!bus) + return 0; + + pr_debug("bus %s: add driver %s\n", bus->name, drv->name); + error = kobject_set_name(&drv->kobj, "%s", drv->name); + if (error) + goto out_put_bus; + drv->kobj.kset = &bus->drivers; + if ((error = kobject_register(&drv->kobj))) + goto out_put_bus; + + error = driver_attach(drv); + if (error) + goto out_unregister; + klist_add_tail(&drv->knode_bus, &bus->klist_drivers); + module_add_driver(drv->owner, drv); + + error = driver_add_attrs(bus, drv); + if (error) { + /* How the hell do we get out of this pickle? Give up */ + printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", + __FUNCTION__, drv->name); + } + error = add_bind_files(drv); + if (error) { + /* Ditto */ + printk(KERN_ERR "%s: add_bind_files(%s) failed\n", + __FUNCTION__, drv->name); } + return error; out_unregister: kobject_unregister(&drv->kobj); @@ -565,16 +567,17 @@ out_put_bus: void bus_remove_driver(struct device_driver * drv) { - if (drv->bus) { - remove_bind_files(drv); - driver_remove_attrs(drv->bus, drv); - klist_remove(&drv->knode_bus); - pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); - driver_detach(drv); - module_remove_driver(drv); - kobject_unregister(&drv->kobj); - put_bus(drv->bus); - } + if (!drv->bus) + return; + + remove_bind_files(drv); + driver_remove_attrs(drv->bus, drv); + klist_remove(&drv->knode_bus); + pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); + driver_detach(drv); + module_remove_driver(drv); + kobject_unregister(&drv->kobj); + put_bus(drv->bus); } -- cgit v1.2.3 From 4d664238207a82c4018757e2d87cf2a780462dcd Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 9 Oct 2006 18:04:30 +0900 Subject: driver core: kmalloc() failure check in driver_probe_device driver_probe_device() is missing kmalloc() failure check. Signed-off-by: Akinobu Mita Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index ef7db6939cbf..db01b95a47a5 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -171,6 +171,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) drv->bus->name, dev->bus_id, drv->name); data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; data->drv = drv; data->dev = dev; -- cgit v1.2.3 From 463c2c12dce78dd0cb77b65beba93f029a164ba3 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:34:41 -0400 Subject: aoe: eliminate isbusy message This message doesn't help users because the circumstance isn't problematic. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoedev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index ed4258a62df5..c2bc3edb32c7 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -20,11 +20,8 @@ aoedev_isbusy(struct aoedev *d) f = d->frames; e = f + d->nframes; do { - if (f->tag != FREETAG) { - printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n", - d->aoemajor, d->aoeminor); + if (f->tag != FREETAG) return 1; - } } while (++f < e); return 0; -- cgit v1.2.3 From 2611464d7f36685fb1990275d3de1e72e6aff9d9 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:48 -0400 Subject: aoe: update copyright date Update the copyright year to 2006. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoeblk.c | 2 +- drivers/block/aoe/aoechr.c | 2 +- drivers/block/aoe/aoecmd.c | 2 +- drivers/block/aoe/aoedev.c | 2 +- drivers/block/aoe/aoemain.c | 2 +- drivers/block/aoe/aoenet.c | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 6eebcb7be97e..507c37799882 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ #define VERSION "22" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 393b86a3dbf8..fa0e8cae6100 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoeblk.c * block device routines diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 1bc1cf9603f1..8a7a08191411 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoechr.c * AoE character device driver diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 39da28d344fe..d1d8759eca85 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoecmd.c * Filesystem request handling methods diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index c2bc3edb32c7..c7e05ed82512 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoedev.c * AoE device utility functions; maintains device list. diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index de08491ebe66..727c34d8bc78 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoemain.c * Module initialization routines, discover timer diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index c1434ed11880..1bba140549c9 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ +/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ /* * aoenet.c * Ethernet portion of AoE driver -- cgit v1.2.3 From 2fdc0ea75b26e3009cfdf72e79901e4e16bb99bd Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:48 -0400 Subject: aoe: remove unused NARGS enum The NARGS enum is left over from older code versions. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoechr.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 8a7a08191411..0c543d3bfe58 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -15,7 +15,6 @@ enum { MINOR_INTERFACES, MINOR_REVALIDATE, MSGSZ = 2048, - NARGS = 10, NMSG = 100, /* message backlog to retain */ }; -- cgit v1.2.3 From e407a7f6cd143b3ab4eb3d7e1cf882e96b710eb5 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: zero copy write 1 of 2 Avoid memory copy on writes. (This patch depends on fixes in patch 9 to follow.) Although skb->len should not be set when working with linear skbuffs, the skb->tail pointer maintained by skb_put/skb_trim is not relevant to what happens when the skb_fill_page_desc function is called. This issue was raised without comment in linux-kernel and netdev earlier this month: http://thread.gmane.org/gmane.linux.kernel/446474/ http://thread.gmane.org/gmane.linux.network/45444/ So until there is something analogous to skb_put that works for zero-copy write skbuffs, we will do what the other callers of skb_fill_page_desc are doing. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 7 +--- drivers/block/aoe/aoecmd.c | 94 ++++++++++++++++++---------------------------- drivers/block/aoe/aoedev.c | 42 +++++++++++++++------ 3 files changed, 69 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 507c37799882..fa2d804b2665 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -107,11 +107,7 @@ struct frame { ulong waited; struct buf *buf; char *bufaddr; - int writedatalen; - int ndata; - - /* largest possible */ - unsigned char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)]; + struct sk_buff *skb; }; struct aoedev { @@ -157,6 +153,7 @@ void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); void aoecmd_ata_rsp(struct sk_buff *); void aoecmd_cfg_rsp(struct sk_buff *); void aoecmd_sleepwork(void *vp); +struct sk_buff *new_skb(ulong); int aoedev_init(void); void aoedev_exit(void); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index d1d8759eca85..1aeb2969987f 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -17,15 +17,14 @@ #define MAXTIMER (HZ << 1) #define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */ -static struct sk_buff * -new_skb(struct net_device *if_dev, ulong len) +struct sk_buff * +new_skb(ulong len) { struct sk_buff *skb; skb = alloc_skb(len, GFP_ATOMIC); if (skb) { skb->nh.raw = skb->mac.raw = skb->data; - skb->dev = if_dev; skb->protocol = __constant_htons(ETH_P_AOE); skb->priority = 0; skb_put(skb, len); @@ -40,29 +39,6 @@ new_skb(struct net_device *if_dev, ulong len) return skb; } -static struct sk_buff * -skb_prepare(struct aoedev *d, struct frame *f) -{ - struct sk_buff *skb; - char *p; - - skb = new_skb(d->ifp, f->ndata + f->writedatalen); - if (!skb) { - printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n"); - return NULL; - } - - p = skb->mac.raw; - memcpy(p, f->data, f->ndata); - - if (f->writedatalen) { - p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr); - memcpy(p, f->bufaddr, f->writedatalen); - } - - return skb; -} - static struct frame * getframe(struct aoedev *d, int tag) { @@ -129,10 +105,11 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) bcnt = MAXATADATA; /* initialize the headers & frame */ - h = (struct aoe_hdr *) f->data; + skb = f->skb; + h = (struct aoe_hdr *) skb->mac.raw; ah = (struct aoe_atahdr *) (h+1); - f->ndata = sizeof *h + sizeof *ah; - memset(h, 0, f->ndata); + skb->len = sizeof *h + sizeof *ah; + memset(h, 0, skb->len); f->tag = aoehdr_atainit(d, h); f->waited = 0; f->buf = buf; @@ -155,11 +132,13 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) } if (bio_data_dir(buf->bio) == WRITE) { + skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), + offset_in_page(f->bufaddr), bcnt); ah->aflags |= AOEAFL_WRITE; - f->writedatalen = bcnt; } else { + skb_shinfo(skb)->nr_frags = 0; + skb->len = ETH_ZLEN; writebit = 0; - f->writedatalen = 0; } ah->cmdstat = WIN_READ | writebit | extbit; @@ -179,15 +158,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; } - skb = skb_prepare(d, f); - if (skb) { - skb->next = NULL; - if (d->sendq_hd) - d->sendq_tl->next = skb; - else - d->sendq_hd = skb; - d->sendq_tl = skb; - } + skb->dev = d->ifp; + skb_get(skb); + skb->next = NULL; + if (d->sendq_hd) + d->sendq_tl->next = skb; + else + d->sendq_hd = skb; + d->sendq_tl = skb; } /* some callers cannot sleep, and they can call this function, @@ -209,11 +187,12 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) if (!is_aoe_netif(ifp)) continue; - skb = new_skb(ifp, sizeof *h + sizeof *ch); + skb = new_skb(sizeof *h + sizeof *ch); if (skb == NULL) { printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); continue; } + skb->dev = ifp; if (sl_tail == NULL) sl_tail = skb; h = (struct aoe_hdr *) skb->mac.raw; @@ -283,21 +262,21 @@ rexmit(struct aoedev *d, struct frame *f) d->aoemajor, d->aoeminor, f->tag, jiffies, n); aoechr_error(buf); - h = (struct aoe_hdr *) f->data; + skb = f->skb; + h = (struct aoe_hdr *) skb->mac.raw; f->tag = n; h->tag = cpu_to_be32(n); memcpy(h->dst, d->addr, sizeof h->dst); memcpy(h->src, d->ifp->dev_addr, sizeof h->src); - skb = skb_prepare(d, f); - if (skb) { - skb->next = NULL; - if (d->sendq_hd) - d->sendq_tl->next = skb; - else - d->sendq_hd = skb; - d->sendq_tl = skb; - } + skb->dev = d->ifp; + skb_get(skb); + skb->next = NULL; + if (d->sendq_hd) + d->sendq_tl->next = skb; + else + d->sendq_hd = skb; + d->sendq_tl = skb; } static int @@ -514,7 +493,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) calc_rttavg(d, tsince(f->tag)); ahin = (struct aoe_atahdr *) (hin+1); - ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr)); + ahout = (struct aoe_atahdr *) (f->skb->mac.raw + sizeof(struct aoe_hdr)); buf = f->buf; if (ahout->cmdstat == WIN_IDENTIFY) @@ -620,20 +599,21 @@ aoecmd_ata_id(struct aoedev *d) } /* initialize the headers & frame */ - h = (struct aoe_hdr *) f->data; + skb = f->skb; + h = (struct aoe_hdr *) skb->mac.raw; ah = (struct aoe_atahdr *) (h+1); - f->ndata = sizeof *h + sizeof *ah; - memset(h, 0, f->ndata); + skb->len = sizeof *h + sizeof *ah; + memset(h, 0, skb->len); f->tag = aoehdr_atainit(d, h); f->waited = 0; - f->writedatalen = 0; /* set up ata header */ ah->scnt = 1; ah->cmdstat = WIN_IDENTIFY; ah->lba3 = 0xa0; - skb = skb_prepare(d, f); + skb->dev = d->ifp; + skb_get(skb); d->rttavg = MAXTIMER; d->timer.function = rexmit_timer; diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index c7e05ed82512..abf1d3c073e3 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -63,22 +63,32 @@ aoedev_newdev(ulong nframes) struct frame *f, *e; d = kzalloc(sizeof *d, GFP_ATOMIC); - if (d == NULL) - return NULL; f = kcalloc(nframes, sizeof *f, GFP_ATOMIC); - if (f == NULL) { - kfree(d); + switch (!d || !f) { + case 0: + d->nframes = nframes; + d->frames = f; + e = f + nframes; + for (; ftag = FREETAG; + f->skb = new_skb(ETH_ZLEN); + if (!f->skb) + break; + } + if (f == e) + break; + while (f > d->frames) { + f--; + dev_kfree_skb(f->skb); + } + default: + if (f) + kfree(f); + if (d) + kfree(d); return NULL; } - INIT_WORK(&d->work, aoecmd_sleepwork, d); - - d->nframes = nframes; - d->frames = f; - e = f + nframes; - for (; ftag = FREETAG; - spin_lock_init(&d->lock); init_timer(&d->timer); d->timer.data = (ulong) d; @@ -160,11 +170,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) static void aoedev_freedev(struct aoedev *d) { + struct frame *f, *e; + if (d->gd) { aoedisk_rm_sysfs(d); del_gendisk(d->gd); put_disk(d->gd); } + f = d->frames; + e = f + d->nframes; + for (; fskb)->nr_frags = 0; + dev_kfree_skb(f->skb); + } kfree(d->frames); if (d->bufpool) mempool_destroy(d->bufpool); -- cgit v1.2.3 From 19bf26353c50bc2be375109ec73f2f0bbd616ed1 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: jumbo frame support 1 of 2 Add support for jumbo ethernet frames. (This patch depends on patch 7 to follow.) Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 11 +++++-- drivers/block/aoe/aoechr.c | 1 + drivers/block/aoe/aoecmd.c | 77 +++++++++++++++++++++++++++++++++++++--------- 3 files changed, 72 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index fa2d804b2665..1cec19986c40 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -65,7 +65,7 @@ struct aoe_atahdr { struct aoe_cfghdr { __be16 bufcnt; __be16 fwver; - unsigned char res; + unsigned char scnt; unsigned char aoeccmd; unsigned char cslen[2]; }; @@ -78,12 +78,13 @@ enum { DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */ DEVFL_PAUSE = (1<<5), DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ + DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */ BUFFL_FAIL = 1, }; enum { - MAXATADATA = 1024, + DEFAULTBCNT = 2 * 512, /* 2 sectors */ NPERSHELF = 16, /* number of slots per shelf address */ FREETAG = -1, MIN_BUFS = 8, @@ -107,6 +108,8 @@ struct frame { ulong waited; struct buf *buf; char *bufaddr; + ulong bcnt; + sector_t lba; struct sk_buff *skb; }; @@ -120,6 +123,7 @@ struct aoedev { ulong nopen; /* (bd_openers isn't available without sleeping) */ ulong rttavg; /* round trip average of requests/responses */ u16 fw_ver; /* version of blade's firmware */ + u16 maxbcnt; struct work_struct work;/* disk create work struct */ struct gendisk *gd; request_queue_t blkq; @@ -134,7 +138,8 @@ struct aoedev { struct list_head bufq; /* queue of bios to work on */ struct buf *inprocess; /* the one we're currently working on */ ulong lasttag; /* last tag sent */ - ulong nframes; /* number of frames below */ + ushort lostjumbo; + ushort nframes; /* number of frames below */ struct frame *frames; }; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 0c543d3bfe58..2b5256cc733d 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -89,6 +89,7 @@ revalidate(const char __user *str, size_t size) return -EINVAL; spin_lock_irqsave(&d->lock, flags); + d->flags &= ~DEVFL_MAXBCNT; d->flags |= DEVFL_PAUSE; spin_unlock_irqrestore(&d->lock, flags); aoecmd_cfg(major, minor); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 1aeb2969987f..666797d646d6 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -83,6 +83,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h) return host_tag; } +static inline void +put_lba(struct aoe_atahdr *ah, sector_t lba) +{ + ah->lba0 = lba; + ah->lba1 = lba >>= 8; + ah->lba2 = lba >>= 8; + ah->lba3 = lba >>= 8; + ah->lba4 = lba >>= 8; + ah->lba5 = lba >>= 8; +} + static void aoecmd_ata_rw(struct aoedev *d, struct frame *f) { @@ -101,8 +112,8 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) sector = buf->sector; bcnt = buf->bv_resid; - if (bcnt > MAXATADATA) - bcnt = MAXATADATA; + if (bcnt > d->maxbcnt) + bcnt = d->maxbcnt; /* initialize the headers & frame */ skb = f->skb; @@ -114,17 +125,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) f->waited = 0; f->buf = buf; f->bufaddr = buf->bufaddr; + f->bcnt = bcnt; + f->lba = sector; /* set up ata header */ ah->scnt = bcnt >> 9; - ah->lba0 = sector; - ah->lba1 = sector >>= 8; - ah->lba2 = sector >>= 8; - ah->lba3 = sector >>= 8; + put_lba(ah, sector); if (d->flags & DEVFL_EXT) { ah->aflags |= AOEAFL_EXT; - ah->lba4 = sector >>= 8; - ah->lba5 = sector >>= 8; } else { extbit = 0; ah->lba3 &= 0x0f; @@ -251,6 +259,7 @@ rexmit(struct aoedev *d, struct frame *f) { struct sk_buff *skb; struct aoe_hdr *h; + struct aoe_atahdr *ah; char buf[128]; u32 n; @@ -264,11 +273,27 @@ rexmit(struct aoedev *d, struct frame *f) skb = f->skb; h = (struct aoe_hdr *) skb->mac.raw; + ah = (struct aoe_atahdr *) (h+1); f->tag = n; h->tag = cpu_to_be32(n); memcpy(h->dst, d->addr, sizeof h->dst); memcpy(h->src, d->ifp->dev_addr, sizeof h->src); + n = DEFAULTBCNT / 512; + if (ah->scnt > n) { + ah->scnt = n; + if (ah->aflags & AOEAFL_WRITE) + skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), + offset_in_page(f->bufaddr), DEFAULTBCNT); + if (++d->lostjumbo > (d->nframes << 1)) + if (d->maxbcnt != DEFAULTBCNT) { + printk(KERN_INFO "aoe: rexmit: too many lost jumbo. " + "dropping back to 1KB frames.\n"); + d->maxbcnt = DEFAULTBCNT; + d->flags |= DEVFL_MAXBCNT; + } + } + skb->dev = d->ifp; skb_get(skb); skb->next = NULL; @@ -506,10 +531,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (buf) buf->flags |= BUFFL_FAIL; } else { + n = ahout->scnt << 9; switch (ahout->cmdstat) { case WIN_READ: case WIN_READ_EXT: - n = ahout->scnt << 9; if (skb->len - sizeof *hin - sizeof *ahin < n) { printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " "ata data size in read. skb->len=%d\n", @@ -521,6 +546,22 @@ aoecmd_ata_rsp(struct sk_buff *skb) memcpy(f->bufaddr, ahin+1, n); case WIN_WRITE: case WIN_WRITE_EXT: + if (f->bcnt -= n) { + f->bufaddr += n; + put_lba(ahout, f->lba += ahout->scnt); + n = f->bcnt > DEFAULTBCNT ? DEFAULTBCNT : f->bcnt; + ahout->scnt = n >> 9; + if (ahout->aflags & AOEAFL_WRITE) + skb_fill_page_desc(f->skb, 0, virt_to_page(f->bufaddr), + offset_in_page(f->bufaddr), n); + skb_get(f->skb); + f->skb->next = NULL; + spin_unlock_irqrestore(&d->lock, flags); + aoenet_xmit(f->skb); + return; + } + if (n > DEFAULTBCNT) + d->lostjumbo = 0; break; case WIN_IDENTIFY: if (skb->len - sizeof *hin - sizeof *ahin < 512) { @@ -628,9 +669,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb) struct aoe_hdr *h; struct aoe_cfghdr *ch; ulong flags, sysminor, aoemajor; - u16 bufcnt; struct sk_buff *sl; enum { MAXFRAMES = 16 }; + u16 n; h = (struct aoe_hdr *) skb->mac.raw; ch = (struct aoe_cfghdr *) (h+1); @@ -654,11 +695,11 @@ aoecmd_cfg_rsp(struct sk_buff *skb) return; } - bufcnt = be16_to_cpu(ch->bufcnt); - if (bufcnt > MAXFRAMES) /* keep it reasonable */ - bufcnt = MAXFRAMES; + n = be16_to_cpu(ch->bufcnt); + if (n > MAXFRAMES) /* keep it reasonable */ + n = MAXFRAMES; - d = aoedev_by_sysminor_m(sysminor, bufcnt); + d = aoedev_by_sysminor_m(sysminor, n); if (d == NULL) { printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); return; @@ -669,6 +710,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb) /* permit device to migrate mac and network interface */ d->ifp = skb->dev; memcpy(d->addr, h->src, sizeof d->addr); + if (!(d->flags & DEVFL_MAXBCNT)) { + n = d->ifp->mtu; + n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr); + n /= 512; + if (n > ch->scnt) + n = ch->scnt; + d->maxbcnt = n ? n * 512 : DEFAULTBCNT; + } /* don't change users' perspective */ if (d->nopen && !(d->flags & DEVFL_PAUSE)) { -- cgit v1.2.3 From 6bb6285fdb948cedee586c6bebc9ebc5e32a5c35 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: clean up printks via macros Use simple macros to clean up the printks. (This patch is reverted by the 14th patch to follow.) Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 5 ++++ drivers/block/aoe/aoeblk.c | 16 ++++++------- drivers/block/aoe/aoechr.c | 13 ++++------- drivers/block/aoe/aoecmd.c | 57 +++++++++++++++++++++------------------------ drivers/block/aoe/aoedev.c | 2 +- drivers/block/aoe/aoemain.c | 8 +++---- drivers/block/aoe/aoenet.c | 7 +++--- 7 files changed, 50 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 1cec19986c40..4d79f1eaf708 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -10,6 +10,11 @@ #define AOE_PARTITIONS (16) #endif +#define xprintk(L, fmt, arg...) printk(L "aoe: " "%s: " fmt, __func__, ## arg) +#define iprintk(fmt, arg...) xprintk(KERN_INFO, fmt, ## arg) +#define eprintk(fmt, arg...) xprintk(KERN_ERR, fmt, ## arg) +#define dprintk(fmt, arg...) xprintk(KERN_DEBUG, fmt, ## arg) + #define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor)) #define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF) #define AOEMINOR(sysminor) ((sysminor) % NPERSHELF) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index fa0e8cae6100..a7dbe6f53c14 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -132,8 +132,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) d = bio->bi_bdev->bd_disk->private_data; buf = mempool_alloc(d->bufpool, GFP_NOIO); if (buf == NULL) { - printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation " - "failure\n"); + iprintk("buf allocation failure\n"); bio_endio(bio, bio->bi_size, -ENOMEM); return 0; } @@ -150,8 +149,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) spin_lock_irqsave(&d->lock, flags); if ((d->flags & DEVFL_UP) == 0) { - printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n", - d->aoemajor, d->aoeminor); + iprintk("device %ld.%ld is not up\n", d->aoemajor, d->aoeminor); spin_unlock_irqrestore(&d->lock, flags); mempool_free(buf, d->bufpool); bio_endio(bio, bio->bi_size, -ENXIO); @@ -176,7 +174,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) struct aoedev *d = bdev->bd_disk->private_data; if ((d->flags & DEVFL_UP) == 0) { - printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n"); + eprintk("disk not up\n"); return -ENODEV; } @@ -203,8 +201,8 @@ aoeblk_gdalloc(void *vp) gd = alloc_disk(AOE_PARTITIONS); if (gd == NULL) { - printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk " - "structure for %ld.%ld\n", d->aoemajor, d->aoeminor); + eprintk("cannot allocate disk structure for %ld.%ld\n", + d->aoemajor, d->aoeminor); spin_lock_irqsave(&d->lock, flags); d->flags &= ~DEVFL_GDALLOC; spin_unlock_irqrestore(&d->lock, flags); @@ -213,8 +211,8 @@ aoeblk_gdalloc(void *vp) d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); if (d->bufpool == NULL) { - printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool " - "for %ld.%ld\n", d->aoemajor, d->aoeminor); + eprintk("cannot allocate bufpool for %ld.%ld\n", + d->aoemajor, d->aoeminor); put_disk(gd); spin_lock_irqsave(&d->lock, flags); d->flags &= ~DEVFL_GDALLOC; diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 2b5256cc733d..f5cab69fbc91 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -55,9 +55,7 @@ static int interfaces(const char __user *str, size_t size) { if (set_aoe_iflist(str, size)) { - printk(KERN_CRIT - "%s: could not set interface list: %s\n", - __FUNCTION__, "too many interfaces"); + eprintk("could not set interface list: too many interfaces\n"); return -EINVAL; } return 0; @@ -80,8 +78,7 @@ revalidate(const char __user *str, size_t size) /* should be e%d.%d format */ n = sscanf(buf, "e%d.%d", &major, &minor); if (n != 2) { - printk(KERN_ERR "aoe: %s: invalid device specification\n", - __FUNCTION__); + eprintk("invalid device specification\n"); return -EINVAL; } d = aoedev_by_aoeaddr(major, minor); @@ -116,7 +113,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags); mp = kmalloc(n, GFP_ATOMIC); if (mp == NULL) { - printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n); + eprintk("allocation failure, len=%ld\n", n); goto bail; } @@ -141,7 +138,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp switch ((unsigned long) filp->private_data) { default: - printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n"); + iprintk("can't write to that file.\n"); break; case MINOR_DISCOVER: ret = discover(); @@ -250,7 +247,7 @@ aoechr_init(void) n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); if (n < 0) { - printk(KERN_ERR "aoe: aoechr_init: can't register char device\n"); + eprintk("can't register char device\n"); return n; } sema_init(&emsgs_sema, 0); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 666797d646d6..63c456082d81 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -155,7 +155,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) buf->nframesout += 1; buf->bufaddr += bcnt; buf->bv_resid -= bcnt; -/* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */ +/* dprintk("bv_resid=%ld\n", buf->bv_resid); */ buf->resid -= bcnt; buf->sector += bcnt >> 9; if (buf->resid == 0) { @@ -197,7 +197,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) skb = new_skb(sizeof *h + sizeof *ch); if (skb == NULL) { - printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n"); + iprintk("skb alloc failure\n"); continue; } skb->dev = ifp; @@ -247,7 +247,7 @@ loop: return; buf = container_of(d->bufq.next, struct buf, bufs); list_del(d->bufq.next); -/*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */ +/*dprintk("bi_size=%ld\n", buf->bio->bi_size); */ d->inprocess = buf; } aoecmd_ata_rw(d, f); @@ -287,8 +287,7 @@ rexmit(struct aoedev *d, struct frame *f) offset_in_page(f->bufaddr), DEFAULTBCNT); if (++d->lostjumbo > (d->nframes << 1)) if (d->maxbcnt != DEFAULTBCNT) { - printk(KERN_INFO "aoe: rexmit: too many lost jumbo. " - "dropping back to 1KB frames.\n"); + iprintk("too many lost jumbo - using 1KB frames.\n"); d->maxbcnt = DEFAULTBCNT; d->flags |= DEVFL_MAXBCNT; } @@ -435,8 +434,8 @@ ataid_complete(struct aoedev *d, unsigned char *id) } if (d->ssize != ssize) - printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu " - "sectors\n", (unsigned long long)mac_addr(d->addr), + iprintk("%012llx e%lu.%lu v%04x has %llu sectors\n", + (unsigned long long)mac_addr(d->addr), d->aoemajor, d->aoeminor, d->fw_ver, (long long)ssize); d->ssize = ssize; @@ -446,11 +445,9 @@ ataid_complete(struct aoedev *d, unsigned char *id) d->flags |= DEVFL_NEWSIZE; } else { if (d->flags & DEVFL_GDALLOC) { - printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n", - __FUNCTION__, - "can't schedule work for", + eprintk("can't schedule work for e%lu.%lu, %s\n", d->aoemajor, d->aoeminor, - "it's already on! (This really shouldn't happen).\n"); + "it's already on! This shouldn't happen.\n"); return; } d->flags |= DEVFL_GDALLOC; @@ -524,8 +521,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (ahout->cmdstat == WIN_IDENTIFY) d->flags &= ~DEVFL_PAUSE; if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ - printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh " - "stat=%2.2Xh from e%ld.%ld\n", + eprintk("ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", ahout->cmdstat, ahin->cmdstat, d->aoemajor, d->aoeminor); if (buf) @@ -536,8 +532,7 @@ aoecmd_ata_rsp(struct sk_buff *skb) case WIN_READ: case WIN_READ_EXT: if (skb->len - sizeof *hin - sizeof *ahin < n) { - printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt " - "ata data size in read. skb->len=%d\n", + eprintk("runt data size in read. skb->len=%d\n", skb->len); /* fail frame f? just returning will rexmit. */ spin_unlock_irqrestore(&d->lock, flags); @@ -549,10 +544,13 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (f->bcnt -= n) { f->bufaddr += n; put_lba(ahout, f->lba += ahout->scnt); - n = f->bcnt > DEFAULTBCNT ? DEFAULTBCNT : f->bcnt; + n = f->bcnt; + if (n > DEFAULTBCNT) + n = DEFAULTBCNT; ahout->scnt = n >> 9; if (ahout->aflags & AOEAFL_WRITE) - skb_fill_page_desc(f->skb, 0, virt_to_page(f->bufaddr), + skb_fill_page_desc(f->skb, 0, + virt_to_page(f->bufaddr), offset_in_page(f->bufaddr), n); skb_get(f->skb); f->skb->next = NULL; @@ -565,19 +563,18 @@ aoecmd_ata_rsp(struct sk_buff *skb) break; case WIN_IDENTIFY: if (skb->len - sizeof *hin - sizeof *ahin < 512) { - printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size " - "in ataid. skb->len=%d\n", skb->len); + iprintk("runt data size in ataid. skb->len=%d\n", + skb->len); spin_unlock_irqrestore(&d->lock, flags); return; } ataid_complete(d, (char *) (ahin+1)); break; default: - printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized " - "outbound ata command %2.2Xh for %d.%d\n", - ahout->cmdstat, - be16_to_cpu(hin->major), - hin->minor); + iprintk("unrecognized ata command %2.2Xh for %d.%d\n", + ahout->cmdstat, + be16_to_cpu(hin->major), + hin->minor); } } @@ -634,8 +631,7 @@ aoecmd_ata_id(struct aoedev *d) f = getframe(d, FREETAG); if (f == NULL) { - printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. " - "This shouldn't happen.\n"); + eprintk("can't get a frame. This shouldn't happen.\n"); return NULL; } @@ -682,15 +678,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb) */ aoemajor = be16_to_cpu(h->major); if (aoemajor == 0xfff) { - printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf " - "address is all ones. Check shelf dip switches\n"); + eprintk("Warning: shelf address is all ones. " + "Check shelf dip switches.\n"); return; } sysminor = SYSMINOR(aoemajor, h->minor); if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { - printk(KERN_INFO - "aoe: e%ld.%d: minor number too large\n", + iprintk("e%ld.%d: minor number too large\n", aoemajor, (int) h->minor); return; } @@ -701,7 +696,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) d = aoedev_by_sysminor_m(sysminor, n); if (d == NULL) { - printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n"); + iprintk("device sysminor_m failure\n"); return; } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index abf1d3c073e3..f51d87bbb501 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -155,7 +155,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) d = aoedev_newdev(bufcnt); if (d == NULL) { spin_unlock_irqrestore(&devlist_lock, flags); - printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n"); + iprintk("aoedev_newdev failure.\n"); return NULL; } d->sysminor = sysminor; diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 727c34d8bc78..13e634db6fd4 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -84,13 +84,11 @@ aoe_init(void) goto net_fail; ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); if (ret < 0) { - printk(KERN_ERR "aoe: aoeblk_init: can't register major\n"); + eprintk("can't register major\n"); goto blkreg_fail; } - printk(KERN_INFO - "aoe: aoe_init: AoE v%s initialised.\n", - VERSION); + iprintk("AoE v%s initialised.\n", VERSION); discover_timer(TINIT); return 0; @@ -103,7 +101,7 @@ aoe_init(void) chr_fail: aoedev_exit(); - printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n"); + iprintk("initialisation failure.\n"); return ret; } diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index 1bba140549c9..f1cf2666fc7d 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -74,7 +74,7 @@ set_aoe_iflist(const char __user *user_str, size_t size) return -EINVAL; if (copy_from_user(aoe_iflist, user_str, size)) { - printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__); + iprintk("copy from user failed\n"); return -EFAULT; } aoe_iflist[size] = 0x00; @@ -132,8 +132,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, if (n > NECODES) n = 0; if (net_ratelimit()) - printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; " - "ecode=%d '%s'\n", + eprintk("error packet from %d.%d; ecode=%d '%s'\n", be16_to_cpu(h->major), h->minor, h->err, aoe_errlist[n]); goto exit; @@ -147,7 +146,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, aoecmd_cfg_rsp(skb); break; default: - printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd); + iprintk("unknown cmd %d\n", h->cmd); } exit: dev_kfree_skb(skb); -- cgit v1.2.3 From ddec63e86752b89776547e93aa68af01f1cbb10c Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: jumbo frame support 2 of 2 Add support for jumbo ethernet frames. (This patch follows patch 5.) Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 63c456082d81..621fdbbc4cd4 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -475,7 +475,7 @@ void aoecmd_ata_rsp(struct sk_buff *skb) { struct aoedev *d; - struct aoe_hdr *hin; + struct aoe_hdr *hin, *hout; struct aoe_atahdr *ahin, *ahout; struct frame *f; struct buf *buf; @@ -515,7 +515,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) calc_rttavg(d, tsince(f->tag)); ahin = (struct aoe_atahdr *) (hin+1); - ahout = (struct aoe_atahdr *) (f->skb->mac.raw + sizeof(struct aoe_hdr)); + hout = (struct aoe_hdr *) f->skb->mac.raw; + ahout = (struct aoe_atahdr *) (hout+1); buf = f->buf; if (ahout->cmdstat == WIN_IDENTIFY) @@ -552,6 +553,9 @@ aoecmd_ata_rsp(struct sk_buff *skb) skb_fill_page_desc(f->skb, 0, virt_to_page(f->bufaddr), offset_in_page(f->bufaddr), n); + f->tag = newtag(d); + hout->tag = cpu_to_be32(f->tag); + skb->dev = d->ifp; skb_get(f->skb); f->skb->next = NULL; spin_unlock_irqrestore(&d->lock, flags); -- cgit v1.2.3 From dced3a053dd5415a7321e1ae153c96dea644da4e Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: improve retransmission heuristics Add a dynamic minimum timer for better retransmission behavior. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 7 ++++--- drivers/block/aoe/aoecmd.c | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 4d79f1eaf708..7b1121748633 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -125,8 +125,10 @@ struct aoedev { ulong sysminor; ulong aoemajor; ulong aoeminor; - ulong nopen; /* (bd_openers isn't available without sleeping) */ - ulong rttavg; /* round trip average of requests/responses */ + u16 nopen; /* (bd_openers isn't available without sleeping) */ + u16 lasttag; /* last tag sent */ + u16 rttavg; /* round trip average of requests/responses */ + u16 mintimer; u16 fw_ver; /* version of blade's firmware */ u16 maxbcnt; struct work_struct work;/* disk create work struct */ @@ -142,7 +144,6 @@ struct aoedev { mempool_t *bufpool; /* for deadlock-free Buf allocation */ struct list_head bufq; /* queue of bios to work on */ struct buf *inprocess; /* the one we're currently working on */ - ulong lasttag; /* last tag sent */ ushort lostjumbo; ushort nframes; /* number of frames below */ struct frame *frames; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 621fdbbc4cd4..c0bdc1fe21f0 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -461,8 +461,15 @@ calc_rttavg(struct aoedev *d, int rtt) register long n; n = rtt; - if (n < MINTIMER) - n = MINTIMER; + if (n < 0) { + n = -rtt; + if (n < MINTIMER) + n = MINTIMER; + else if (n > MAXTIMER) + n = MAXTIMER; + d->mintimer += (n - d->mintimer) >> 1; + } else if (n < d->mintimer) + n = d->mintimer; else if (n > MAXTIMER) n = MAXTIMER; @@ -498,8 +505,10 @@ aoecmd_ata_rsp(struct sk_buff *skb) spin_lock_irqsave(&d->lock, flags); - f = getframe(d, be32_to_cpu(hin->tag)); + n = be32_to_cpu(hin->tag); + f = getframe(d, n); if (f == NULL) { + calc_rttavg(d, -tsince(n)); spin_unlock_irqrestore(&d->lock, flags); snprintf(ebuf, sizeof ebuf, "%15s e%d.%d tag=%08x@%08lx\n", @@ -724,6 +733,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) return; } d->flags |= DEVFL_PAUSE; /* force pause */ + d->mintimer = MINTIMER; d->fw_ver = be16_to_cpu(ch->fwver); /* check for already outstanding ataid */ -- cgit v1.2.3 From 4f51dc5e9ae195d2e8c22e5f574e004c2f6518a4 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:49 -0400 Subject: aoe: zero copy write 2 of 2 Avoid memory copy on writes. (This patch follows patch 4.) Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 1 + drivers/block/aoe/aoecmd.c | 82 +++++++++++++++++++++++++++++++++++----------- drivers/block/aoe/aoedev.c | 1 + 3 files changed, 64 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 7b1121748633..b41fdfe0f4b8 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -84,6 +84,7 @@ enum { DEVFL_PAUSE = (1<<5), DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */ + DEVFL_KICKME = (1<<8), BUFFL_FAIL = 1, }; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index c0bdc1fe21f0..9ebc98ade3c5 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -120,7 +120,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) h = (struct aoe_hdr *) skb->mac.raw; ah = (struct aoe_atahdr *) (h+1); skb->len = sizeof *h + sizeof *ah; - memset(h, 0, skb->len); + memset(h, 0, ETH_ZLEN); f->tag = aoehdr_atainit(d, h); f->waited = 0; f->buf = buf; @@ -143,8 +143,9 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), offset_in_page(f->bufaddr), bcnt); ah->aflags |= AOEAFL_WRITE; + skb->len += bcnt; + skb->data_len = bcnt; } else { - skb_shinfo(skb)->nr_frags = 0; skb->len = ETH_ZLEN; writebit = 0; } @@ -167,8 +168,9 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) } skb->dev = d->ifp; - skb_get(skb); - skb->next = NULL; + skb = skb_clone(skb, GFP_ATOMIC); + if (skb == NULL) + return; if (d->sendq_hd) d->sendq_tl->next = skb; else @@ -224,6 +226,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) return sl; } +static struct frame * +freeframe(struct aoedev *d) +{ + struct frame *f, *e; + int n = 0; + + f = d->frames; + e = f + d->nframes; + for (; ftag != FREETAG) + continue; + if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) { + skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; + return f; + } + n++; + } + if (n == d->nframes) /* wait for network layer */ + d->flags |= DEVFL_KICKME; + + return NULL; +} + /* enters with d->lock held */ void aoecmd_work(struct aoedev *d) @@ -239,7 +264,7 @@ aoecmd_work(struct aoedev *d) } loop: - f = getframe(d, FREETAG); + f = freeframe(d); if (f == NULL) return; if (d->inprocess == NULL) { @@ -282,20 +307,25 @@ rexmit(struct aoedev *d, struct frame *f) n = DEFAULTBCNT / 512; if (ah->scnt > n) { ah->scnt = n; - if (ah->aflags & AOEAFL_WRITE) + if (ah->aflags & AOEAFL_WRITE) { skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), offset_in_page(f->bufaddr), DEFAULTBCNT); + skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT; + skb->data_len = DEFAULTBCNT; + } if (++d->lostjumbo > (d->nframes << 1)) if (d->maxbcnt != DEFAULTBCNT) { - iprintk("too many lost jumbo - using 1KB frames.\n"); + iprintk("e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", + d->aoemajor, d->aoeminor, d->ifp->name); d->maxbcnt = DEFAULTBCNT; d->flags |= DEVFL_MAXBCNT; } } skb->dev = d->ifp; - skb_get(skb); - skb->next = NULL; + skb = skb_clone(skb, GFP_ATOMIC); + if (skb == NULL) + return; if (d->sendq_hd) d->sendq_tl->next = skb; else @@ -350,6 +380,10 @@ rexmit_timer(ulong vp) rexmit(d, f); } } + if (d->flags & DEVFL_KICKME) { + d->flags &= ~DEVFL_KICKME; + aoecmd_work(d); + } sl = d->sendq_hd; d->sendq_hd = d->sendq_tl = NULL; @@ -552,23 +586,27 @@ aoecmd_ata_rsp(struct sk_buff *skb) case WIN_WRITE: case WIN_WRITE_EXT: if (f->bcnt -= n) { + skb = f->skb; f->bufaddr += n; put_lba(ahout, f->lba += ahout->scnt); n = f->bcnt; if (n > DEFAULTBCNT) n = DEFAULTBCNT; ahout->scnt = n >> 9; - if (ahout->aflags & AOEAFL_WRITE) - skb_fill_page_desc(f->skb, 0, + if (ahout->aflags & AOEAFL_WRITE) { + skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr), offset_in_page(f->bufaddr), n); + skb->len = sizeof *hout + sizeof *ahout + n; + skb->data_len = n; + } f->tag = newtag(d); hout->tag = cpu_to_be32(f->tag); skb->dev = d->ifp; - skb_get(f->skb); - f->skb->next = NULL; + skb = skb_clone(skb, GFP_ATOMIC); spin_unlock_irqrestore(&d->lock, flags); - aoenet_xmit(f->skb); + if (skb) + aoenet_xmit(skb); return; } if (n > DEFAULTBCNT) @@ -642,7 +680,7 @@ aoecmd_ata_id(struct aoedev *d) struct frame *f; struct sk_buff *skb; - f = getframe(d, FREETAG); + f = freeframe(d); if (f == NULL) { eprintk("can't get a frame. This shouldn't happen.\n"); return NULL; @@ -652,8 +690,8 @@ aoecmd_ata_id(struct aoedev *d) skb = f->skb; h = (struct aoe_hdr *) skb->mac.raw; ah = (struct aoe_atahdr *) (h+1); - skb->len = sizeof *h + sizeof *ah; - memset(h, 0, skb->len); + skb->len = ETH_ZLEN; + memset(h, 0, ETH_ZLEN); f->tag = aoehdr_atainit(d, h); f->waited = 0; @@ -663,12 +701,11 @@ aoecmd_ata_id(struct aoedev *d) ah->lba3 = 0xa0; skb->dev = d->ifp; - skb_get(skb); d->rttavg = MAXTIMER; d->timer.function = rexmit_timer; - return skb; + return skb_clone(skb, GFP_ATOMIC); } void @@ -724,7 +761,12 @@ aoecmd_cfg_rsp(struct sk_buff *skb) n /= 512; if (n > ch->scnt) n = ch->scnt; - d->maxbcnt = n ? n * 512 : DEFAULTBCNT; + n = n ? n * 512 : DEFAULTBCNT; + if (n != d->maxbcnt) { + iprintk("e%ld.%ld: setting %d byte data frames on %s\n", + d->aoemajor, d->aoeminor, n, d->ifp->name); + d->maxbcnt = n; + } } /* don't change users' perspective */ diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index f51d87bbb501..7fd63d4daf51 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -121,6 +121,7 @@ aoedev_downdev(struct aoedev *d) mempool_free(buf, d->bufpool); bio_endio(bio, bio->bi_size, -EIO); } + skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0; } d->inprocess = NULL; -- cgit v1.2.3 From b751e8b6590efdb76e1682c85bfcd5f3531ccae4 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:50 -0400 Subject: aoe: module parameter for device timeout The aoe_deadsecs module parameter sets the number of seconds that elapse before a nonresponsive AoE device is marked as dead. This is runtime settable in sysfs or settable with a module load or kernel boot parameter. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoecmd.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 9ebc98ade3c5..f2b8f558e1bb 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -15,7 +15,10 @@ #define TIMERTICK (HZ / 10) #define MINTIMER (2 * TIMERTICK) #define MAXTIMER (HZ << 1) -#define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */ + +static int aoe_deadsecs = 60 * 3; +module_param(aoe_deadsecs, int, 0644); +MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev."); struct sk_buff * new_skb(ulong len) @@ -373,7 +376,7 @@ rexmit_timer(ulong vp) if (f->tag != FREETAG && tsince(f->tag) >= timeout) { n = f->waited += timeout; n /= HZ; - if (n > MAXWAIT) { /* waited too long. device failure. */ + if (n > aoe_deadsecs) { /* waited too long for response */ aoedev_downdev(d); break; } -- cgit v1.2.3 From 392e4845f9728114f7ffa8d7612683397fd4d441 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:50 -0400 Subject: aoe: use bio->bi_idx Instead of starting with bio->bi_io_vec, use the offset in bio->bi_idx. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoeblk.c | 3 ++- drivers/block/aoe/aoecmd.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index a7dbe6f53c14..196ae7a37643 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -142,7 +142,8 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) buf->bio = bio; buf->resid = bio->bi_size; buf->sector = bio->bi_sector; - buf->bv = buf->bio->bi_io_vec; + buf->bv = &bio->bi_io_vec[bio->bi_idx]; + WARN_ON(buf->bv->bv_len == 0); buf->bv_resid = buf->bv->bv_len; buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index f2b8f558e1bb..2d0bcdd96698 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -166,6 +166,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) d->inprocess = NULL; } else if (buf->bv_resid == 0) { buf->bv++; + WARN_ON(buf->bv->bv_len == 0); buf->bv_resid = buf->bv->bv_len; buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset; } -- cgit v1.2.3 From b849086d8f77f8a1269a01d5552fbf355311f7ac Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:51 -0400 Subject: aoe: remove sysfs comment Remove unecessary comment. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoeblk.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 196ae7a37643..088acf48ffa4 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -14,7 +14,6 @@ static kmem_cache_t *buf_pool_cache; -/* add attributes for our block devices in sysfs */ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page) { struct aoedev *d = disk->private_data; -- cgit v1.2.3 From 086216db1435f44a58c18454acfa59f013510c95 Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:51 -0400 Subject: aoe: update driver version Update aoe driver version number to 32. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index b41fdfe0f4b8..188bf09876d9 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "22" +#define VERSION "32" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" -- cgit v1.2.3 From a12c93f08b8fc83b7fcdabaf92b1adcea7489f5e Mon Sep 17 00:00:00 2001 From: "Ed L. Cashin" Date: Wed, 20 Sep 2006 14:36:51 -0400 Subject: aoe: revert printk macros This patch addresses the concern that the aoe driver should not introduce unecessary conventions that must be learned by the reader. It reverts patch 6. Signed-off-by: "Ed L. Cashin" Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoe.h | 5 ----- drivers/block/aoe/aoeblk.c | 11 ++++++----- drivers/block/aoe/aoechr.c | 11 ++++++----- drivers/block/aoe/aoecmd.c | 35 ++++++++++++++++++++--------------- drivers/block/aoe/aoedev.c | 2 +- drivers/block/aoe/aoemain.c | 6 +++--- drivers/block/aoe/aoenet.c | 6 +++--- 7 files changed, 39 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 188bf09876d9..6d111228cfac 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -10,11 +10,6 @@ #define AOE_PARTITIONS (16) #endif -#define xprintk(L, fmt, arg...) printk(L "aoe: " "%s: " fmt, __func__, ## arg) -#define iprintk(fmt, arg...) xprintk(KERN_INFO, fmt, ## arg) -#define eprintk(fmt, arg...) xprintk(KERN_ERR, fmt, ## arg) -#define dprintk(fmt, arg...) xprintk(KERN_DEBUG, fmt, ## arg) - #define SYSMINOR(aoemajor, aoeminor) ((aoemajor) * NPERSHELF + (aoeminor)) #define AOEMAJOR(sysminor) ((sysminor) / NPERSHELF) #define AOEMINOR(sysminor) ((sysminor) % NPERSHELF) diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 088acf48ffa4..4259b52b01e2 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -131,7 +131,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) d = bio->bi_bdev->bd_disk->private_data; buf = mempool_alloc(d->bufpool, GFP_NOIO); if (buf == NULL) { - iprintk("buf allocation failure\n"); + printk(KERN_INFO "aoe: buf allocation failure\n"); bio_endio(bio, bio->bi_size, -ENOMEM); return 0; } @@ -149,7 +149,8 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio) spin_lock_irqsave(&d->lock, flags); if ((d->flags & DEVFL_UP) == 0) { - iprintk("device %ld.%ld is not up\n", d->aoemajor, d->aoeminor); + printk(KERN_INFO "aoe: device %ld.%ld is not up\n", + d->aoemajor, d->aoeminor); spin_unlock_irqrestore(&d->lock, flags); mempool_free(buf, d->bufpool); bio_endio(bio, bio->bi_size, -ENXIO); @@ -174,7 +175,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo) struct aoedev *d = bdev->bd_disk->private_data; if ((d->flags & DEVFL_UP) == 0) { - eprintk("disk not up\n"); + printk(KERN_ERR "aoe: disk not up\n"); return -ENODEV; } @@ -201,7 +202,7 @@ aoeblk_gdalloc(void *vp) gd = alloc_disk(AOE_PARTITIONS); if (gd == NULL) { - eprintk("cannot allocate disk structure for %ld.%ld\n", + printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n", d->aoemajor, d->aoeminor); spin_lock_irqsave(&d->lock, flags); d->flags &= ~DEVFL_GDALLOC; @@ -211,7 +212,7 @@ aoeblk_gdalloc(void *vp) d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache); if (d->bufpool == NULL) { - eprintk("cannot allocate bufpool for %ld.%ld\n", + printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n", d->aoemajor, d->aoeminor); put_disk(gd); spin_lock_irqsave(&d->lock, flags); diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index f5cab69fbc91..e22b4c9520a9 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -55,7 +55,8 @@ static int interfaces(const char __user *str, size_t size) { if (set_aoe_iflist(str, size)) { - eprintk("could not set interface list: too many interfaces\n"); + printk(KERN_ERR + "aoe: could not set interface list: too many interfaces\n"); return -EINVAL; } return 0; @@ -78,7 +79,7 @@ revalidate(const char __user *str, size_t size) /* should be e%d.%d format */ n = sscanf(buf, "e%d.%d", &major, &minor); if (n != 2) { - eprintk("invalid device specification\n"); + printk(KERN_ERR "aoe: invalid device specification\n"); return -EINVAL; } d = aoedev_by_aoeaddr(major, minor); @@ -113,7 +114,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags); mp = kmalloc(n, GFP_ATOMIC); if (mp == NULL) { - eprintk("allocation failure, len=%ld\n", n); + printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n); goto bail; } @@ -138,7 +139,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp switch ((unsigned long) filp->private_data) { default: - iprintk("can't write to that file.\n"); + printk(KERN_INFO "aoe: can't write to that file.\n"); break; case MINOR_DISCOVER: ret = discover(); @@ -247,7 +248,7 @@ aoechr_init(void) n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops); if (n < 0) { - eprintk("can't register char device\n"); + printk(KERN_ERR "aoe: can't register char device\n"); return n; } sema_init(&emsgs_sema, 0); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 2d0bcdd96698..8a13b1af8bab 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -159,7 +159,7 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f) buf->nframesout += 1; buf->bufaddr += bcnt; buf->bv_resid -= bcnt; -/* dprintk("bv_resid=%ld\n", buf->bv_resid); */ +/* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */ buf->resid -= bcnt; buf->sector += bcnt >> 9; if (buf->resid == 0) { @@ -203,7 +203,7 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail) skb = new_skb(sizeof *h + sizeof *ch); if (skb == NULL) { - iprintk("skb alloc failure\n"); + printk(KERN_INFO "aoe: skb alloc failure\n"); continue; } skb->dev = ifp; @@ -276,7 +276,7 @@ loop: return; buf = container_of(d->bufq.next, struct buf, bufs); list_del(d->bufq.next); -/*dprintk("bi_size=%ld\n", buf->bio->bi_size); */ +/*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */ d->inprocess = buf; } aoecmd_ata_rw(d, f); @@ -319,7 +319,7 @@ rexmit(struct aoedev *d, struct frame *f) } if (++d->lostjumbo > (d->nframes << 1)) if (d->maxbcnt != DEFAULTBCNT) { - iprintk("e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", + printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n", d->aoemajor, d->aoeminor, d->ifp->name); d->maxbcnt = DEFAULTBCNT; d->flags |= DEVFL_MAXBCNT; @@ -472,7 +472,7 @@ ataid_complete(struct aoedev *d, unsigned char *id) } if (d->ssize != ssize) - iprintk("%012llx e%lu.%lu v%04x has %llu sectors\n", + printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n", (unsigned long long)mac_addr(d->addr), d->aoemajor, d->aoeminor, d->fw_ver, (long long)ssize); @@ -483,7 +483,7 @@ ataid_complete(struct aoedev *d, unsigned char *id) d->flags |= DEVFL_NEWSIZE; } else { if (d->flags & DEVFL_GDALLOC) { - eprintk("can't schedule work for e%lu.%lu, %s\n", + printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n", d->aoemajor, d->aoeminor, "it's already on! This shouldn't happen.\n"); return; @@ -569,7 +569,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) if (ahout->cmdstat == WIN_IDENTIFY) d->flags &= ~DEVFL_PAUSE; if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */ - eprintk("ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", + printk(KERN_ERR + "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n", ahout->cmdstat, ahin->cmdstat, d->aoemajor, d->aoeminor); if (buf) @@ -580,7 +581,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) case WIN_READ: case WIN_READ_EXT: if (skb->len - sizeof *hin - sizeof *ahin < n) { - eprintk("runt data size in read. skb->len=%d\n", + printk(KERN_ERR + "aoe: runt data size in read. skb->len=%d\n", skb->len); /* fail frame f? just returning will rexmit. */ spin_unlock_irqrestore(&d->lock, flags); @@ -618,7 +620,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) break; case WIN_IDENTIFY: if (skb->len - sizeof *hin - sizeof *ahin < 512) { - iprintk("runt data size in ataid. skb->len=%d\n", + printk(KERN_INFO + "aoe: runt data size in ataid. skb->len=%d\n", skb->len); spin_unlock_irqrestore(&d->lock, flags); return; @@ -626,7 +629,8 @@ aoecmd_ata_rsp(struct sk_buff *skb) ataid_complete(d, (char *) (ahin+1)); break; default: - iprintk("unrecognized ata command %2.2Xh for %d.%d\n", + printk(KERN_INFO + "aoe: unrecognized ata command %2.2Xh for %d.%d\n", ahout->cmdstat, be16_to_cpu(hin->major), hin->minor); @@ -686,7 +690,7 @@ aoecmd_ata_id(struct aoedev *d) f = freeframe(d); if (f == NULL) { - eprintk("can't get a frame. This shouldn't happen.\n"); + printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n"); return NULL; } @@ -732,14 +736,14 @@ aoecmd_cfg_rsp(struct sk_buff *skb) */ aoemajor = be16_to_cpu(h->major); if (aoemajor == 0xfff) { - eprintk("Warning: shelf address is all ones. " + printk(KERN_ERR "aoe: Warning: shelf address is all ones. " "Check shelf dip switches.\n"); return; } sysminor = SYSMINOR(aoemajor, h->minor); if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) { - iprintk("e%ld.%d: minor number too large\n", + printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n", aoemajor, (int) h->minor); return; } @@ -750,7 +754,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb) d = aoedev_by_sysminor_m(sysminor, n); if (d == NULL) { - iprintk("device sysminor_m failure\n"); + printk(KERN_INFO "aoe: device sysminor_m failure\n"); return; } @@ -767,7 +771,8 @@ aoecmd_cfg_rsp(struct sk_buff *skb) n = ch->scnt; n = n ? n * 512 : DEFAULTBCNT; if (n != d->maxbcnt) { - iprintk("e%ld.%ld: setting %d byte data frames on %s\n", + printk(KERN_INFO + "aoe: e%ld.%ld: setting %d byte data frames on %s\n", d->aoemajor, d->aoeminor, n, d->ifp->name); d->maxbcnt = n; } diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c index 7fd63d4daf51..6125921bbec4 100644 --- a/drivers/block/aoe/aoedev.c +++ b/drivers/block/aoe/aoedev.c @@ -156,7 +156,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt) d = aoedev_newdev(bufcnt); if (d == NULL) { spin_unlock_irqrestore(&devlist_lock, flags); - iprintk("aoedev_newdev failure.\n"); + printk(KERN_INFO "aoe: aoedev_newdev failure.\n"); return NULL; } d->sysminor = sysminor; diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c index 13e634db6fd4..a04b7d613299 100644 --- a/drivers/block/aoe/aoemain.c +++ b/drivers/block/aoe/aoemain.c @@ -84,11 +84,11 @@ aoe_init(void) goto net_fail; ret = register_blkdev(AOE_MAJOR, DEVICE_NAME); if (ret < 0) { - eprintk("can't register major\n"); + printk(KERN_ERR "aoe: can't register major\n"); goto blkreg_fail; } - iprintk("AoE v%s initialised.\n", VERSION); + printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION); discover_timer(TINIT); return 0; @@ -101,7 +101,7 @@ aoe_init(void) chr_fail: aoedev_exit(); - iprintk("initialisation failure.\n"); + printk(KERN_INFO "aoe: initialisation failure.\n"); return ret; } diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c index f1cf2666fc7d..9626e0f5da9d 100644 --- a/drivers/block/aoe/aoenet.c +++ b/drivers/block/aoe/aoenet.c @@ -74,7 +74,7 @@ set_aoe_iflist(const char __user *user_str, size_t size) return -EINVAL; if (copy_from_user(aoe_iflist, user_str, size)) { - iprintk("copy from user failed\n"); + printk(KERN_INFO "aoe: copy from user failed\n"); return -EFAULT; } aoe_iflist[size] = 0x00; @@ -132,7 +132,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, if (n > NECODES) n = 0; if (net_ratelimit()) - eprintk("error packet from %d.%d; ecode=%d '%s'\n", + printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n", be16_to_cpu(h->major), h->minor, h->err, aoe_errlist[n]); goto exit; @@ -146,7 +146,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt, aoecmd_cfg_rsp(skb); break; default: - iprintk("unknown cmd %d\n", h->cmd); + printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd); } exit: dev_kfree_skb(skb); -- cgit v1.2.3 From 4ca5224f3ea4779054d96e885ca9b3980801ce13 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Apr 2002 12:14:34 -0700 Subject: aoe: fix sysfs_create_file warnings Moved the attributes into a group, making the compiler be quiet about ignoring the return value of the file create calls. This also also fixed a bug when removing the files, which were not symlinks. Cc: "Ed L. Cashin" Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoeblk.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 4259b52b01e2..d433f27e0ce2 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -63,21 +63,26 @@ static struct disk_attribute disk_attr_fwver = { .show = aoedisk_show_fwver }; -static void +static struct attribute *aoe_attrs[] = { + &disk_attr_state.attr, + &disk_attr_mac.attr, + &disk_attr_netif.attr, + &disk_attr_fwver.attr, +}; + +static const struct attribute_group attr_group = { + .attrs = aoe_attrs, +}; + +static int aoedisk_add_sysfs(struct aoedev *d) { - sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr); - sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr); - sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr); - sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr); + return sysfs_create_group(&d->gd->kobj, &attr_group); } void aoedisk_rm_sysfs(struct aoedev *d) { - sysfs_remove_link(&d->gd->kobj, "state"); - sysfs_remove_link(&d->gd->kobj, "mac"); - sysfs_remove_link(&d->gd->kobj, "netif"); - sysfs_remove_link(&d->gd->kobj, "firmware-version"); + sysfs_remove_group(&d->gd->kobj, &attr_group); } static int -- cgit v1.2.3 From 34fc921a253f3ddfc4ad9de1dbc88683f84fbaaa Mon Sep 17 00:00:00 2001 From: Jim Cromie Date: Sun, 8 Oct 2006 21:56:29 +0200 Subject: w83791d: Fix unchecked return status Replace all unchecked calls to device_create_file with a single group declaration, and one call to sysfs_create_group, and check that one return status. Also remove the files on device detach. Signed-off-by: Jim Cromie Signed-off by: Charles Spirakis Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83791d.c | 85 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 371ed4f69a97..9e5f885368b4 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -746,6 +746,52 @@ static ssize_t store_vrm_reg(struct device *dev, static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); +#define IN_UNIT_ATTRS(X) \ + &sda_in_input[X].dev_attr.attr, \ + &sda_in_min[X].dev_attr.attr, \ + &sda_in_max[X].dev_attr.attr + +#define FAN_UNIT_ATTRS(X) \ + &sda_fan_input[X].dev_attr.attr, \ + &sda_fan_min[X].dev_attr.attr, \ + &sda_fan_div[X].dev_attr.attr + +#define TEMP_UNIT_ATTRS(X) \ + &sda_temp_input[X].dev_attr.attr, \ + &sda_temp_max[X].dev_attr.attr, \ + &sda_temp_max_hyst[X].dev_attr.attr + +static struct attribute *w83791d_attributes[] = { + IN_UNIT_ATTRS(0), + IN_UNIT_ATTRS(1), + IN_UNIT_ATTRS(2), + IN_UNIT_ATTRS(3), + IN_UNIT_ATTRS(4), + IN_UNIT_ATTRS(5), + IN_UNIT_ATTRS(6), + IN_UNIT_ATTRS(7), + IN_UNIT_ATTRS(8), + IN_UNIT_ATTRS(9), + FAN_UNIT_ATTRS(0), + FAN_UNIT_ATTRS(1), + FAN_UNIT_ATTRS(2), + FAN_UNIT_ATTRS(3), + FAN_UNIT_ATTRS(4), + TEMP_UNIT_ATTRS(0), + TEMP_UNIT_ATTRS(1), + TEMP_UNIT_ATTRS(2), + &dev_attr_alarms.attr, + &sda_beep_ctrl[0].dev_attr.attr, + &sda_beep_ctrl[1].dev_attr.attr, + &dev_attr_cpu0_vid.attr, + &dev_attr_vrm.attr, + NULL +}; + +static const struct attribute_group w83791d_group = { + .attrs = w83791d_attributes, +}; + /* This function is called when: * w83791d_driver is inserted (when this module is loaded), for each available adapter @@ -967,41 +1013,20 @@ static int w83791d_detect(struct i2c_adapter *adapter, int address, int kind) } /* Register sysfs hooks */ + if ((err = sysfs_create_group(&client->dev.kobj, &w83791d_group))) + goto error3; + + /* Everything is ready, now register the working device */ data->class_dev = hwmon_device_register(dev); if (IS_ERR(data->class_dev)) { err = PTR_ERR(data->class_dev); - goto error3; + goto error4; } - for (i = 0; i < NUMBER_OF_VIN; i++) { - device_create_file(dev, &sda_in_input[i].dev_attr); - device_create_file(dev, &sda_in_min[i].dev_attr); - device_create_file(dev, &sda_in_max[i].dev_attr); - } - - for (i = 0; i < NUMBER_OF_FANIN; i++) { - device_create_file(dev, &sda_fan_input[i].dev_attr); - device_create_file(dev, &sda_fan_div[i].dev_attr); - device_create_file(dev, &sda_fan_min[i].dev_attr); - } - - for (i = 0; i < NUMBER_OF_TEMPIN; i++) { - device_create_file(dev, &sda_temp_input[i].dev_attr); - device_create_file(dev, &sda_temp_max[i].dev_attr); - device_create_file(dev, &sda_temp_max_hyst[i].dev_attr); - } - - device_create_file(dev, &dev_attr_alarms); - - for (i = 0; i < ARRAY_SIZE(sda_beep_ctrl); i++) { - device_create_file(dev, &sda_beep_ctrl[i].dev_attr); - } - - device_create_file(dev, &dev_attr_cpu0_vid); - device_create_file(dev, &dev_attr_vrm); - return 0; +error4: + sysfs_remove_group(&client->dev.kobj, &w83791d_group); error3: if (data->lm75[0] != NULL) { i2c_detach_client(data->lm75[0]); @@ -1025,8 +1050,10 @@ static int w83791d_detach_client(struct i2c_client *client) int err; /* main client */ - if (data) + if (data) { hwmon_device_unregister(data->class_dev); + sysfs_remove_group(&client->dev.kobj, &w83791d_group); + } if ((err = i2c_detach_client(client))) return err; -- cgit v1.2.3 From 2ca7b961c3c9f072d307293aad0f9705522e916a Mon Sep 17 00:00:00 2001 From: Grant Coady Date: Sun, 8 Oct 2006 21:57:41 +0200 Subject: adm9240: Update Grant Coady's email address Replace a bouncing email that I cannot recover from Mr Google. Signed-off-by: Grant Coady Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/adm9240 | 2 +- drivers/hwmon/adm9240.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/adm9240 b/Documentation/hwmon/adm9240 index 35f618f32896..2c6f1fed4618 100644 --- a/Documentation/hwmon/adm9240 +++ b/Documentation/hwmon/adm9240 @@ -24,7 +24,7 @@ Authors: Frodo Looijaard , Philip Edelbrock , Michiel Rook , - Grant Coady with guidance + Grant Coady with guidance from Jean Delvare Interface diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 377961c4a41e..aad594adf0c7 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -5,7 +5,7 @@ * Copyright (C) 1999 Frodo Looijaard * Philip Edelbrock * Copyright (C) 2003 Michiel Rook - * Copyright (C) 2005 Grant Coady with valuable + * Copyright (C) 2005 Grant Coady with valuable * guidance from Jean Delvare * * Driver supports Analog Devices ADM9240 @@ -774,7 +774,7 @@ static void __exit sensors_adm9240_exit(void) } MODULE_AUTHOR("Michiel Rook , " - "Grant Coady and others"); + "Grant Coady and others"); MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6091780eba5d195213747b515a62211ac97641f1 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Sun, 8 Oct 2006 22:00:44 +0200 Subject: smsc47m1: List the SMSC LPC47M112 as supported The SMSC LPC47M112 Super-I/O chip appears to be compatible with the LPC47M10x and LPC47M13x as far as hardware monitoring is concerned. The device ID is even the same, so it's really only a documentation update. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/smsc47m1 | 4 +++- drivers/hwmon/Kconfig | 4 ++-- drivers/hwmon/smsc47m1.c | 11 ++++++----- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/smsc47m1 b/Documentation/hwmon/smsc47m1 index c15bbe68264e..04a11124f667 100644 --- a/Documentation/hwmon/smsc47m1 +++ b/Documentation/hwmon/smsc47m1 @@ -2,12 +2,14 @@ Kernel driver smsc47m1 ====================== Supported chips: - * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 + * SMSC LPC47B27x, LPC47M112, LPC47M10x, LPC47M13x, LPC47M14x, + LPC47M15x and LPC47M192 Addresses scanned: none, address read from Super I/O config space Prefix: 'smsc47m1' Datasheets: http://www.smsc.com/main/datasheets/47b27x.pdf http://www.smsc.com/main/datasheets/47m10x.pdf + http://www.smsc.com/main/datasheets/47m112.pdf http://www.smsc.com/main/tools/discontinued/47m13x.pdf http://www.smsc.com/main/datasheets/47m14x.pdf http://www.smsc.com/main/tools/discontinued/47m15x.pdf diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 9b88b25b6edb..e0dede7198c8 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -369,8 +369,8 @@ config SENSORS_SMSC47M1 help If you say yes here you get support for the integrated fan monitoring and control capabilities of the SMSC LPC47B27x, - LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x, LPC47M192 and - LPC47M997 chips. + LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, + LPC47M192 and LPC47M997 chips. The temperature and voltage sensor features of the LPC47M192 and LPC47M997 are supported by another driver, select also diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 47132fd26b1b..beb881c4b2e8 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -2,8 +2,8 @@ smsc47m1.c - Part of lm_sensors, Linux kernel modules for hardware monitoring - Supports the SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, - LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips. + Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, + LPC47M14x, LPC47M15x, LPC47M192 and LPC47M997 Super-I/O chips. Copyright (C) 2002 Mark D. Studebaker Copyright (C) 2004 Jean Delvare @@ -380,8 +380,8 @@ static int __init smsc47m1_find(unsigned short *addr) val = superio_inb(SUPERIO_REG_DEVID); /* - * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id - * 0x5F) and LPC47B27x (device id 0x51) have fan control. + * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x + * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control. * The LPC47M15x and LPC47M192 chips "with hardware monitoring block" * can do much more besides (device id 0x60). * The LPC47M997 is undocumented, but seems to be compatible with @@ -390,7 +390,8 @@ static int __init smsc47m1_find(unsigned short *addr) if (val == 0x51) printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n"); else if (val == 0x59) - printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n"); + printk(KERN_INFO "smsc47m1: Found SMSC " + "LPC47M10x/LPC47M112/LPC47M13x\n"); else if (val == 0x5F) printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n"); else if (val == 0x60) -- cgit v1.2.3 From 4660cb354a1dacbbc9c96f94eceedc38fe542fe2 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sun, 8 Oct 2006 22:01:26 +0200 Subject: k8temp: Documentation update Update the documentation for the k8temp driver. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- Documentation/hwmon/k8temp | 13 ++++++++----- MAINTAINERS | 6 ++++++ drivers/hwmon/Kconfig | 6 ++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/k8temp b/Documentation/hwmon/k8temp index bab445ab0f52..30d123b8d920 100644 --- a/Documentation/hwmon/k8temp +++ b/Documentation/hwmon/k8temp @@ -2,7 +2,7 @@ Kernel driver k8temp ==================== Supported chips: - * AMD K8 CPU + * AMD Athlon64/FX or Opteron CPUs Prefix: 'k8temp' Addresses scanned: PCI space Datasheet: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf @@ -13,10 +13,13 @@ Contact: Rudolf Marek Description ----------- -This driver permits reading temperature sensor(s) embedded inside AMD K8 CPUs. -Official documentation says that it works from revision F of K8 core, but -in fact it seems to be implemented for all revisions of K8 except the first -two revisions (SH-B0 and SH-B3). +This driver permits reading temperature sensor(s) embedded inside AMD K8 +family CPUs (Athlon64/FX, Opteron). Official documentation says that it works +from revision F of K8 core, but in fact it seems to be implemented for all +revisions of K8 except the first two revisions (SH-B0 and SH-B3). + +Please note that you will need at least lm-sensors 2.10.1 for proper userspace +support. There can be up to four temperature sensors inside single CPU. The driver will auto-detect the sensors and will display only temperatures from diff --git a/MAINTAINERS b/MAINTAINERS index 5305dd69095b..595b34c4f9d8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1668,6 +1668,12 @@ M: sct@redhat.com, akpm@osdl.org L: ext2-devel@lists.sourceforge.net S: Maintained +K8TEMP HARDWARE MONITORING DRIVER +P: Rudolf Marek +M: r.marek@assembler.cz +L: lm-sensors@lm-sensors.org +S: Maintained + KCONFIG P: Roman Zippel M: zippel@linux-m68k.org diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index e0dede7198c8..e76d91906c99 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -95,11 +95,13 @@ config SENSORS_ADM9240 will be called adm9240. config SENSORS_K8TEMP - tristate "AMD K8 processor sensor" + tristate "AMD Athlon64/FX or Opteron temperature sensor" depends on HWMON && X86 && PCI && EXPERIMENTAL help If you say yes here you get support for the temperature - sensor(s) inside your AMD K8 CPU. + sensor(s) inside your CPU. Supported is whole AMD K8 + microarchitecture. Please note that you will need at least + lm-sensors 2.10.1 for proper userspace support. This driver can also be built as a module. If so, the module will be called k8temp. -- cgit v1.2.3 From 14992c7eff937bb12c8ebf2d91dbaa8c2f0cfc87 Mon Sep 17 00:00:00 2001 From: Rudolf Marek Date: Sun, 8 Oct 2006 22:02:09 +0200 Subject: w83627ehf: Fix the detection of fan5 Fix the detection of fan5 and preserve the bit between the register writes, because the bit is write only. Signed-off-by: Rudolf Marek Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83627ehf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 833faa275ffa..2257806d0102 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -354,6 +354,8 @@ static void w83627ehf_write_fan_div(struct i2c_client *client, int nr) case 0: reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf) | ((data->fan_div[0] & 0x03) << 4); + /* fan5 input control bit is write only, compute the value */ + reg |= (data->has_fan & (1 << 4)) ? 1 : 0; w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf) | ((data->fan_div[0] & 0x04) << 3); @@ -362,6 +364,8 @@ static void w83627ehf_write_fan_div(struct i2c_client *client, int nr) case 1: reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f) | ((data->fan_div[1] & 0x03) << 6); + /* fan5 input control bit is write only, compute the value */ + reg |= (data->has_fan & (1 << 4)) ? 1 : 0; w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg); reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf) | ((data->fan_div[1] & 0x04) << 4); @@ -1216,13 +1220,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter) superio_exit(); /* It looks like fan4 and fan5 pins can be alternatively used - as fan on/off switches */ + as fan on/off switches, but fan5 control is write only :/ + We assume that if the serial interface is disabled, designers + connected fan5 as input unless they are emitting log 1, which + is not the default. */ data->has_fan = 0x07; /* fan1, fan2 and fan3 */ i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1); if ((i & (1 << 2)) && (!fan4pin)) data->has_fan |= (1 << 3); - if ((i & (1 << 0)) && (!fan5pin)) + if (!(i & (1 << 1)) && (!fan5pin)) data->has_fan |= (1 << 4); /* Register sysfs hooks */ -- cgit v1.2.3 From e693810ce8495ce3e227dacaa83f501b3b8ab204 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 13 Oct 2006 16:56:28 +0200 Subject: hwmon: Let w83781d and lm78 load again Let the w83781d and lm78 hardware monitoring drivers load even when no chip was detected at the ISA address. There can still be supported chips connected to an I2C bus or SMBus. This fixes bug #7293. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/lm78.c | 12 ++++++------ drivers/hwmon/w83781d.c | 12 ++++++------ drivers/i2c/busses/i2c-isa.c | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index ac1b746df6d0..73bc2ffc598d 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -815,18 +815,18 @@ static int __init sm_lm78_init(void) if (res) return res; - res = i2c_isa_add_driver(&lm78_isa_driver); - if (res) { - i2c_del_driver(&lm78_driver); - return res; - } + /* Don't exit if this one fails, we still want the I2C variants + to work! */ + if (i2c_isa_add_driver(&lm78_isa_driver)) + isa_address = 0; return 0; } static void __exit sm_lm78_exit(void) { - i2c_isa_del_driver(&lm78_isa_driver); + if (isa_address) + i2c_isa_del_driver(&lm78_isa_driver); i2c_del_driver(&lm78_driver); } diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a4584ec69842..fea92061f863 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1685,11 +1685,10 @@ sensors_w83781d_init(void) if (res) return res; - res = i2c_isa_add_driver(&w83781d_isa_driver); - if (res) { - i2c_del_driver(&w83781d_driver); - return res; - } + /* Don't exit if this one fails, we still want the I2C variants + to work! */ + if (i2c_isa_add_driver(&w83781d_isa_driver)) + isa_address = 0; return 0; } @@ -1697,7 +1696,8 @@ sensors_w83781d_init(void) static void __exit sensors_w83781d_exit(void) { - i2c_isa_del_driver(&w83781d_isa_driver); + if (isa_address) + i2c_isa_del_driver(&w83781d_isa_driver); i2c_del_driver(&w83781d_driver); } diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c index 4380653748a4..8ed59a2dff53 100644 --- a/drivers/i2c/busses/i2c-isa.c +++ b/drivers/i2c/busses/i2c-isa.c @@ -91,7 +91,7 @@ int i2c_isa_add_driver(struct i2c_driver *driver) /* Now look for clients */ res = driver->attach_adapter(&isa_adapter); if (res) { - dev_err(&isa_adapter.dev, + dev_dbg(&isa_adapter.dev, "Driver %s failed to attach adapter, unregistering\n", driver->driver.name); driver_unregister(&driver->driver); -- cgit v1.2.3 From bd452e6f178a559408c54c2b4ca29191b812d47f Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Fri, 13 Oct 2006 17:03:42 +0200 Subject: hwmon: Fix debug messages in w83781d Fix debug messages in w83781d at detection time. We can't use dev_dbg() on an i2c client's device before calling i2c_attach_client() on that client. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/hwmon/w83781d.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index fea92061f863..1232171c3aad 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1099,7 +1099,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) bank. */ if (kind < 0) { if (w83781d_read_value(client, W83781D_REG_CONFIG) & 0x80) { - dev_dbg(dev, "Detection failed at step 3\n"); + dev_dbg(&adapter->dev, "Detection of w83781d chip " + "failed at step 3\n"); err = -ENODEV; goto ERROR2; } @@ -1109,7 +1110,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) if ((!(val1 & 0x07)) && (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)) || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) { - dev_dbg(dev, "Detection failed at step 4\n"); + dev_dbg(&adapter->dev, "Detection of w83781d chip " + "failed at step 4\n"); err = -ENODEV; goto ERROR2; } @@ -1119,7 +1121,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ((val1 & 0x80) && (val2 == 0x5c)))) { if (w83781d_read_value (client, W83781D_REG_I2C_ADDR) != address) { - dev_dbg(dev, "Detection failed at step 5\n"); + dev_dbg(&adapter->dev, "Detection of w83781d " + "chip failed at step 5\n"); err = -ENODEV; goto ERROR2; } @@ -1141,8 +1144,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) else if (val2 == 0x12) vendid = asus; else { - dev_dbg(dev, "Chip was made by neither " - "Winbond nor Asus?\n"); + dev_dbg(&adapter->dev, "w83781d chip vendor is " + "neither Winbond nor Asus\n"); err = -ENODEV; goto ERROR2; } @@ -1161,10 +1164,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) kind = as99127f; else { if (kind == 0) - dev_warn(dev, "Ignoring 'force' " + dev_warn(&adapter->dev, "Ignoring 'force' " "parameter for unknown chip at " - "adapter %d, address 0x%02x\n", - i2c_adapter_id(adapter), address); + "address 0x%02x\n", address); err = -EINVAL; goto ERROR2; } -- cgit v1.2.3 From 5175c3786c244f8b689854db24c9e79b1c6a084f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 18 Oct 2006 20:51:57 -0700 Subject: [NET]: reduce per cpu ram used for loopback stats We dont need a full struct net_device_stats (currently 23 long : 184 bytes on x86_64) per possible CPU, but only two counters : bytes and packets We save few CPU cycles too in loopback_xmit() not updating 4 fields, but 2. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/loopback.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 4178b4b1d2df..93fbea1c9271 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -58,7 +58,11 @@ #include #include -static DEFINE_PER_CPU(struct net_device_stats, loopback_stats); +struct pcpu_lstats { + unsigned long packets; + unsigned long bytes; +}; +static DEFINE_PER_CPU(struct pcpu_lstats, pcpu_lstats); #define LOOPBACK_OVERHEAD (128 + MAX_HEADER + 16 + 16) @@ -128,7 +132,7 @@ static void emulate_large_send_offload(struct sk_buff *skb) */ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) { - struct net_device_stats *lb_stats; + struct pcpu_lstats *lb_stats; skb_orphan(skb); @@ -149,11 +153,9 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) #endif dev->last_rx = jiffies; - lb_stats = &per_cpu(loopback_stats, get_cpu()); - lb_stats->rx_bytes += skb->len; - lb_stats->tx_bytes = lb_stats->rx_bytes; - lb_stats->rx_packets++; - lb_stats->tx_packets = lb_stats->rx_packets; + lb_stats = &per_cpu(pcpu_lstats, get_cpu()); + lb_stats->bytes += skb->len; + lb_stats->packets++; put_cpu(); netif_rx(skb); @@ -166,20 +168,21 @@ static struct net_device_stats loopback_stats; static struct net_device_stats *get_stats(struct net_device *dev) { struct net_device_stats *stats = &loopback_stats; + unsigned long bytes = 0; + unsigned long packets = 0; int i; - memset(stats, 0, sizeof(struct net_device_stats)); - for_each_possible_cpu(i) { - struct net_device_stats *lb_stats; + const struct pcpu_lstats *lb_stats; - lb_stats = &per_cpu(loopback_stats, i); - stats->rx_bytes += lb_stats->rx_bytes; - stats->tx_bytes += lb_stats->tx_bytes; - stats->rx_packets += lb_stats->rx_packets; - stats->tx_packets += lb_stats->tx_packets; + lb_stats = &per_cpu(pcpu_lstats, i); + bytes += lb_stats->bytes; + packets += lb_stats->packets; } - + stats->rx_packets = packets; + stats->tx_packets = packets; + stats->rx_bytes = bytes; + stats->tx_bytes = bytes; return stats; } -- cgit v1.2.3 From 42952231c6a8623117ee3cc89c82d382dc69ca30 Mon Sep 17 00:00:00 2001 From: Ranjit Manomohan Date: Wed, 18 Oct 2006 20:54:26 -0700 Subject: [TG3]: Fix set ring params tx ring size implementation Fixes the implementation of the ethtool set ring parameters for the tg3 transmit ring. The size of tx_pending is taken into account before doing a netif_wake_queue. This prevents the interface from locking up when smaller transmit ring sizes are used. Signed-off-by: Ranjit Manomohan Acked-by: Michael Chan Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/tg3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 327836b1014e..39e483308a44 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -129,7 +129,7 @@ #define RX_JUMBO_PKT_BUF_SZ (9046 + tp->rx_offset + 64) /* minimum number of free TX descriptors required to wake up TX process */ -#define TG3_TX_WAKEUP_THRESH (TG3_TX_RING_SIZE / 4) +#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4) /* number of ETHTOOL_GSTATS u64's */ #define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64)) @@ -3075,10 +3075,10 @@ static void tg3_tx(struct tg3 *tp) smp_mb(); if (unlikely(netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH))) { + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)))) { netif_tx_lock(tp->dev); if (netif_queue_stopped(tp->dev) && - (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH)) + (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp))) netif_wake_queue(tp->dev); netif_tx_unlock(tp->dev); } @@ -3928,7 +3928,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) tp->tx_prod = entry; if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) netif_wake_queue(tp->dev); } @@ -4143,7 +4143,7 @@ static int tg3_start_xmit_dma_bug(struct sk_buff *skb, struct net_device *dev) tp->tx_prod = entry; if (unlikely(tg3_tx_avail(tp) <= (MAX_SKB_FRAGS + 1))) { netif_stop_queue(dev); - if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH) + if (tg3_tx_avail(tp) > TG3_TX_WAKEUP_THRESH(tp)) netif_wake_queue(tp->dev); } -- cgit v1.2.3 From bc3a9254a7925b6278f6d882746fe6a0bdf6f610 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 18 Oct 2006 20:55:18 -0700 Subject: [TG3]: Add lower bound checks for tx ring size. The minimum tx ring size must be greater than MAX_SKB_FRAGS or 3 times that on some chips with TSO bugs. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 39e483308a44..7ba9dd2b1f80 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8106,7 +8106,10 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) || (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) || - (ering->tx_pending > TG3_TX_RING_SIZE - 1)) + (ering->tx_pending > TG3_TX_RING_SIZE - 1) || + (ering->tx_pending <= MAX_SKB_FRAGS) || + ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_1_BUG) && + (ering->tx_pending <= (MAX_SKB_FRAGS * 3)))) return -EINVAL; if (netif_running(dev)) { -- cgit v1.2.3 From 6ba7511b7c8b71d5148f7516584d0b677acc384a Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 18 Oct 2006 20:56:06 -0700 Subject: [TG3]: Bump driver version and release date. Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7ba9dd2b1f80..8e398499c045 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.66" -#define DRV_MODULE_RELDATE "September 23, 2006" +#define DRV_MODULE_VERSION "3.67" +#define DRV_MODULE_RELDATE "October 18, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.2.3 From 082c44d20eb4c6c4aa60ae7429ea184854cb0610 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 19 Oct 2006 16:16:18 +0900 Subject: sh: Cleanup board header directories. Now with the ide.h mess sorted out, most of these boards don't need their own directory. Move the headers out, and update the driver paths. Signed-off-by: Paul Mundt --- arch/sh/boards/hp6xx/hp6xx_apm.c | 2 +- arch/sh/boards/hp6xx/pm.c | 2 +- arch/sh/boards/hp6xx/setup.c | 2 +- arch/sh/boards/renesas/hs7751rvoip/io.c | 2 +- arch/sh/boards/renesas/hs7751rvoip/irq.c | 2 +- arch/sh/boards/renesas/hs7751rvoip/setup.c | 7 +- arch/sh/boards/renesas/r7780rp/io.c | 2 +- arch/sh/boards/renesas/r7780rp/irq.c | 3 +- arch/sh/boards/renesas/r7780rp/setup.c | 2 +- arch/sh/boards/renesas/rts7751r2d/io.c | 4 +- arch/sh/boards/renesas/rts7751r2d/irq.c | 6 +- arch/sh/boards/renesas/rts7751r2d/led.c | 15 +-- arch/sh/boards/renesas/rts7751r2d/setup.c | 2 +- arch/sh/boards/shmin/setup.c | 2 +- arch/sh/cchips/voyagergx/irq.c | 22 +--- arch/sh/drivers/pci/ops-r7780rp.c | 2 +- arch/sh/drivers/pci/ops-rts7751r2d.c | 24 ++-- drivers/input/touchscreen/hp680_ts_input.c | 2 +- drivers/video/hitfb.c | 1 - include/asm-sh/edosk7705/io.h | 30 ----- include/asm-sh/hp6xx/hp6xx.h | 80 ------------- include/asm-sh/hp6xx/io.h | 10 -- include/asm-sh/hs7751rvoip/hs7751rvoip.h | 54 --------- include/asm-sh/r7780rp/r7780rp.h | 177 ----------------------------- include/asm-sh/rts7751r2d/rts7751r2d.h | 74 ------------ include/asm-sh/shmin/shmin.h | 9 -- sound/oss/sh_dac_audio.c | 2 +- 27 files changed, 36 insertions(+), 504 deletions(-) delete mode 100644 include/asm-sh/edosk7705/io.h delete mode 100644 include/asm-sh/hp6xx/hp6xx.h delete mode 100644 include/asm-sh/hp6xx/io.h delete mode 100644 include/asm-sh/hs7751rvoip/hs7751rvoip.h delete mode 100644 include/asm-sh/r7780rp/r7780rp.h delete mode 100644 include/asm-sh/rts7751r2d/rts7751r2d.h delete mode 100644 include/asm-sh/shmin/shmin.h (limited to 'drivers') diff --git a/arch/sh/boards/hp6xx/hp6xx_apm.c b/arch/sh/boards/hp6xx/hp6xx_apm.c index 219179114f0f..d146cdaa0b8b 100644 --- a/arch/sh/boards/hp6xx/hp6xx_apm.c +++ b/arch/sh/boards/hp6xx/hp6xx_apm.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #define SH7709_PGDR 0xa400012c diff --git a/arch/sh/boards/hp6xx/pm.c b/arch/sh/boards/hp6xx/pm.c index 83d327212064..d1947732fb3e 100644 --- a/arch/sh/boards/hp6xx/pm.c +++ b/arch/sh/boards/hp6xx/pm.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/sh/boards/hp6xx/setup.c b/arch/sh/boards/hp6xx/setup.c index 2d3a5b4faf58..b5a96649ed26 100644 --- a/arch/sh/boards/hp6xx/setup.c +++ b/arch/sh/boards/hp6xx/setup.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #define SCPCR 0xa4000116 diff --git a/arch/sh/boards/renesas/hs7751rvoip/io.c b/arch/sh/boards/renesas/hs7751rvoip/io.c index 51f3f6574210..bb9aa0d62852 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/io.c +++ b/arch/sh/boards/renesas/hs7751rvoip/io.c @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include extern void *area6_io8_base; /* Area 6 8bit I/O Base address */ diff --git a/arch/sh/boards/renesas/hs7751rvoip/irq.c b/arch/sh/boards/renesas/hs7751rvoip/irq.c index c617b188258a..943f93aa6052 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/irq.c +++ b/arch/sh/boards/renesas/hs7751rvoip/irq.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include static int mask_pos[] = {8, 9, 10, 11, 12, 13, 0, 1, 2, 3, 4, 5, 6, 7}; diff --git a/arch/sh/boards/renesas/hs7751rvoip/setup.c b/arch/sh/boards/renesas/hs7751rvoip/setup.c index 0414c15c3458..1d997ffd7931 100644 --- a/arch/sh/boards/renesas/hs7751rvoip/setup.c +++ b/arch/sh/boards/renesas/hs7751rvoip/setup.c @@ -10,15 +10,10 @@ #include #include #include -#include -#include -#include #include +#include #include -#include #include -#include -#include static void __init hs7751rvoip_init_irq(void) { diff --git a/arch/sh/boards/renesas/r7780rp/io.c b/arch/sh/boards/renesas/r7780rp/io.c index db92d6e6ae99..311ccccba718 100644 --- a/arch/sh/boards/renesas/r7780rp/io.c +++ b/arch/sh/boards/renesas/r7780rp/io.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/sh/boards/renesas/r7780rp/irq.c b/arch/sh/boards/renesas/r7780rp/irq.c index b544772cbc72..cbb4ea28e9ad 100644 --- a/arch/sh/boards/renesas/r7780rp/irq.c +++ b/arch/sh/boards/renesas/r7780rp/irq.c @@ -10,7 +10,8 @@ */ #include #include -#include +#include +#include #ifdef CONFIG_SH_R7780MP static int mask_pos[] = {12, 11, 9, 14, 15, 8, 13, 6, 5, 4, 3, 2, 0, 0, 1, 0}; diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c index b941aa0aa34e..c331caeb694b 100644 --- a/arch/sh/boards/renesas/r7780rp/setup.c +++ b/arch/sh/boards/renesas/r7780rp/setup.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include diff --git a/arch/sh/boards/renesas/rts7751r2d/io.c b/arch/sh/boards/renesas/rts7751r2d/io.c index 135aa0b5e62d..f2507a804979 100644 --- a/arch/sh/boards/renesas/rts7751r2d/io.c +++ b/arch/sh/boards/renesas/rts7751r2d/io.c @@ -11,8 +11,8 @@ #include #include #include -#include -#include +#include +#include #include /* diff --git a/arch/sh/boards/renesas/rts7751r2d/irq.c b/arch/sh/boards/renesas/rts7751r2d/irq.c index c915e7a3693a..cb0eb20d1b43 100644 --- a/arch/sh/boards/renesas/rts7751r2d/irq.c +++ b/arch/sh/boards/renesas/rts7751r2d/irq.c @@ -8,12 +8,10 @@ * Modified for RTS7751R2D by * Atom Create Engineering Co., Ltd. 2002. */ - #include #include -#include -#include -#include +#include +#include #if defined(CONFIG_RTS7751R2D_REV11) static int mask_pos[] = {11, 9, 8, 12, 10, 6, 5, 4, 7, 14, 13, 0, 0, 0, 0}; diff --git a/arch/sh/boards/renesas/rts7751r2d/led.c b/arch/sh/boards/renesas/rts7751r2d/led.c index a7ce66c1e4f0..509f548bdce0 100644 --- a/arch/sh/boards/renesas/rts7751r2d/led.c +++ b/arch/sh/boards/renesas/rts7751r2d/led.c @@ -8,13 +8,9 @@ * * This file contains Renesas Technology Sales RTS7751R2D specific LED code. */ - -#include -#include - -#ifdef CONFIG_HEARTBEAT - +#include #include +#include /* Cycle the LED's in the clasic Knightriger/Sun pattern */ void heartbeat_rts7751r2d(void) @@ -46,10 +42,3 @@ void heartbeat_rts7751r2d(void) else bit--; } -#endif /* CONFIG_HEARTBEAT */ - -void rts7751r2d_led(unsigned short value) -{ - ctrl_outw(value, PA_OUTPORT); -} - diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c index 20597a6e6702..5c042d35ec91 100644 --- a/arch/sh/boards/renesas/rts7751r2d/setup.c +++ b/arch/sh/boards/renesas/rts7751r2d/setup.c @@ -12,9 +12,9 @@ #include #include #include -#include #include #include +#include #include extern void heartbeat_rts7751r2d(void); diff --git a/arch/sh/boards/shmin/setup.c b/arch/sh/boards/shmin/setup.c index 2f0c19706cf9..a31a1d1e2681 100644 --- a/arch/sh/boards/shmin/setup.c +++ b/arch/sh/boards/shmin/setup.c @@ -7,7 +7,7 @@ */ #include #include -#include +#include #include #include #include diff --git a/arch/sh/cchips/voyagergx/irq.c b/arch/sh/cchips/voyagergx/irq.c index bf1b28feca06..f7ea700d05ae 100644 --- a/arch/sh/cchips/voyagergx/irq.c +++ b/arch/sh/cchips/voyagergx/irq.c @@ -17,29 +17,18 @@ Copyright 2003 (c) Lineo uSolutions,Inc. */ -/* -------------------------------------------------------------------- */ - -#undef DEBUG - -#include -#include -#include -#include -#include #include #include -#include - -#include -#include +#include #include +#include static void disable_voyagergx_irq(unsigned int irq) { unsigned long val; unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); - pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); + pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); val = inl(VOYAGER_INT_MASK); val &= ~mask; outl(val, VOYAGER_INT_MASK); @@ -50,7 +39,7 @@ static void enable_voyagergx_irq(unsigned int irq) unsigned long val; unsigned long mask = 1 << (irq - VOYAGER_IRQ_BASE); - pr_debug("disable_voyagergx_irq(%d): mask=%x\n", irq, mask); + pr_debug("disable_voyagergx_irq(%d): mask=%lx\n", irq, mask); val = inl(VOYAGER_INT_MASK); val |= mask; outl(val, VOYAGER_INT_MASK); @@ -137,7 +126,7 @@ int voyagergx_irq_demux(int irq) } else { printk("Unexpected IRQ irq = %d status = 0x%08lx\n", irq, val); } - pr_debug("voyagergx_irq_demux %d \n", i); + pr_debug("voyagergx_irq_demux %ld\n", i); #else for (bit = 1, i = 0 ; i < VOYAGER_IRQ_NUM ; bit <<= 1, i++) if (val & bit) @@ -185,4 +174,3 @@ void __init setup_voyagergx_irq(void) setup_irq(IRQ_VOYAGER, &irq0); } - diff --git a/arch/sh/drivers/pci/ops-r7780rp.c b/arch/sh/drivers/pci/ops-r7780rp.c index 6e3ba9c65b40..eeea1577e112 100644 --- a/arch/sh/drivers/pci/ops-r7780rp.c +++ b/arch/sh/drivers/pci/ops-r7780rp.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include "pci-sh4.h" diff --git a/arch/sh/drivers/pci/ops-rts7751r2d.c b/arch/sh/drivers/pci/ops-rts7751r2d.c index b68824c8b81e..4a518d948049 100644 --- a/arch/sh/drivers/pci/ops-rts7751r2d.c +++ b/arch/sh/drivers/pci/ops-rts7751r2d.c @@ -10,28 +10,24 @@ * * PCI initialization for the Renesas SH7751R RTS7751R2D board */ - #include #include #include -#include #include -#include -#include -#include +#include +#include #include "pci-sh4.h" +static u8 rts7751r2d_irq_tab[] __initdata = { + IRQ_PCISLOT1, + IRQ_PCISLOT2, + IRQ_PCMCIA, + IRQ_PCIETH, +}; + int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) { - switch (slot) { - case 0: return IRQ_PCISLOT1; /* PCI Extend slot #1 */ - case 1: return IRQ_PCISLOT2; /* PCI Extend slot #2 */ - case 2: return IRQ_PCMCIA; /* PCI Cardbus Bridge */ - case 3: return IRQ_PCIETH; /* Realtek Ethernet controller */ - default: - printk("PCI: Bad IRQ mapping request for slot %d\n", slot); - return -1; - } + return rts7751r2d_irq_tab[slot]; } static struct resource sh7751_io_resource = { diff --git a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c index e31c6c55b2e2..58fca316786c 100644 --- a/drivers/input/touchscreen/hp680_ts_input.c +++ b/drivers/input/touchscreen/hp680_ts_input.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #define MODNAME "hp680_ts_input" diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 3afb472763c0..3dc49424dc75 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -29,7 +29,6 @@ #include #include #include -#include #define WIDTH 640 diff --git a/include/asm-sh/edosk7705/io.h b/include/asm-sh/edosk7705/io.h deleted file mode 100644 index a1089a65bc36..000000000000 --- a/include/asm-sh/edosk7705/io.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * include/asm-sh/edosk7705/io.h - * - * Modified version of io_se.h for the EDOSK7705 specific functions. - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * IO functions for an Hitachi EDOSK7705 development board - */ - -#ifndef __ASM_SH_EDOSK7705_IO_H -#define __ASM_SH_EDOSK7705_IO_H - -#include - -extern unsigned char sh_edosk7705_inb(unsigned long port); -extern unsigned int sh_edosk7705_inl(unsigned long port); - -extern void sh_edosk7705_outb(unsigned char value, unsigned long port); -extern void sh_edosk7705_outl(unsigned int value, unsigned long port); - -extern void sh_edosk7705_insb(unsigned long port, void *addr, unsigned long count); -extern void sh_edosk7705_insl(unsigned long port, void *addr, unsigned long count); -extern void sh_edosk7705_outsb(unsigned long port, const void *addr, unsigned long count); -extern void sh_edosk7705_outsl(unsigned long port, const void *addr, unsigned long count); - -extern unsigned long sh_edosk7705_isa_port2addr(unsigned long offset); - -#endif /* __ASM_SH_EDOSK7705_IO_H */ diff --git a/include/asm-sh/hp6xx/hp6xx.h b/include/asm-sh/hp6xx/hp6xx.h deleted file mode 100644 index f35134c159dd..000000000000 --- a/include/asm-sh/hp6xx/hp6xx.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef __ASM_SH_HP6XX_H -#define __ASM_SH_HP6XX_H - -/* - * Copyright (C) 2003, 2004, 2005 Andriy Skulysh - * - * 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. - * - */ - -#define HP680_BTN_IRQ IRQ0_IRQ -#define HP680_TS_IRQ IRQ3_IRQ -#define HP680_HD64461_IRQ IRQ4_IRQ - -#define DAC_LCD_BRIGHTNESS 0 -#define DAC_SPEAKER_VOLUME 1 - -#define PGDR_OPENED 0x01 -#define PGDR_MAIN_BATTERY_OUT 0x04 -#define PGDR_PLAY_BUTTON 0x08 -#define PGDR_REWIND_BUTTON 0x10 -#define PGDR_RECORD_BUTTON 0x20 - -#define PHDR_TS_PEN_DOWN 0x08 - -#define PJDR_LED_BLINK 0x02 - -#define PKDR_LED_GREEN 0x10 - -#define SCPDR_TS_SCAN_ENABLE 0x20 -#define SCPDR_TS_SCAN_Y 0x02 -#define SCPDR_TS_SCAN_X 0x01 - -#define SCPCR_TS_ENABLE 0x405 -#define SCPCR_TS_MASK 0xc0f - -#define ADC_CHANNEL_TS_Y 1 -#define ADC_CHANNEL_TS_X 2 -#define ADC_CHANNEL_BATTERY 3 -#define ADC_CHANNEL_BACKUP 4 -#define ADC_CHANNEL_CHARGE 5 - -#define HD64461_GPADR_SPEAKER 0x01 -#define HD64461_GPADR_PCMCIA0 (0x02|0x08) - -#define HD64461_GPBDR_LCDOFF 0x01 -#define HD64461_GPBDR_LCD_CONTRAST_MASK 0x78 -#define HD64461_GPBDR_LED_RED 0x80 - -#include -#include - -#define PJDR 0xa4000130 -#define PKDR 0xa4000132 - -static inline void hp6xx_led_red(int on) -{ - u16 v16; - v16 = ctrl_inw(CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); - if (on) - ctrl_outw(v16 & (~HD64461_GPBDR_LED_RED), CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); - else - ctrl_outw(v16 | HD64461_GPBDR_LED_RED, CONFIG_HD64461_IOBASE + HD64461_GPBDR - 0x10000); -} - -static inline void hp6xx_led_green(int on) -{ - u8 v8; - - v8 = ctrl_inb(PKDR); - if (on) - ctrl_outb(v8 & (~PKDR_LED_GREEN), PKDR); - else - ctrl_outb(v8 | PKDR_LED_GREEN, PKDR); -} - - -#endif /* __ASM_SH_HP6XX_H */ diff --git a/include/asm-sh/hp6xx/io.h b/include/asm-sh/hp6xx/io.h deleted file mode 100644 index 2044476ab199..000000000000 --- a/include/asm-sh/hp6xx/io.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __ASM_SH_HP6XX_IO_H -#define __ASM_SH_HP6XX_IO_H - -/* - * Nothing special here.. just use the generic cchip io routines. - */ -#include - -#endif /* __ASM_SH_HP6XX_IO_H */ - diff --git a/include/asm-sh/hs7751rvoip/hs7751rvoip.h b/include/asm-sh/hs7751rvoip/hs7751rvoip.h deleted file mode 100644 index c4cff9d33927..000000000000 --- a/include/asm-sh/hs7751rvoip/hs7751rvoip.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __ASM_SH_RENESAS_HS7751RVOIP_H -#define __ASM_SH_RENESAS_HS7751RVOIP_H - -/* - * linux/include/asm-sh/hs7751rvoip/hs7751rvoip.h - * - * Copyright (C) 2000 Atom Create Engineering Co., Ltd. - * - * Renesas Technology Sales HS7751RVoIP support - */ - -/* Box specific addresses. */ - -#define PA_BCR 0xa4000000 /* FPGA */ -#define PA_SLICCNTR1 0xa4000006 /* SLIC PIO Control 1 */ -#define PA_SLICCNTR2 0xa4000008 /* SLIC PIO Control 2 */ -#define PA_DMACNTR 0xa400000a /* USB DMA Control */ -#define PA_INPORTR 0xa400000c /* Input Port Register */ -#define PA_OUTPORTR 0xa400000e /* Output Port Reguster */ -#define PA_VERREG 0xa4000014 /* FPGA Version Register */ - -#define PA_IDE_OFFSET 0x1f0 /* CF IDE Offset */ - -#define IRLCNTR1 (PA_BCR + 0) /* Interrupt Control Register1 */ -#define IRLCNTR2 (PA_BCR + 2) /* Interrupt Control Register2 */ -#define IRLCNTR3 (PA_BCR + 4) /* Interrupt Control Register3 */ -#define IRLCNTR4 (PA_BCR + 16) /* Interrupt Control Register4 */ -#define IRLCNTR5 (PA_BCR + 18) /* Interrupt Control Register5 */ - -#define IRQ_PCIETH 6 /* PCI Ethernet IRQ */ -#define IRQ_PCIHUB 7 /* PCI Ethernet Hub IRQ */ -#define IRQ_USBCOM 8 /* USB Comunication IRQ */ -#define IRQ_USBCON 9 /* USB Connect IRQ */ -#define IRQ_USBDMA 10 /* USB DMA IRQ */ -#define IRQ_CFCARD 11 /* CF Card IRQ */ -#define IRQ_PCMCIA 12 /* PCMCIA IRQ */ -#define IRQ_PCISLOT 13 /* PCI Slot #1 IRQ */ -#define IRQ_ONHOOK1 0 /* ON HOOK1 IRQ */ -#define IRQ_OFFHOOK1 1 /* OFF HOOK1 IRQ */ -#define IRQ_ONHOOK2 2 /* ON HOOK2 IRQ */ -#define IRQ_OFFHOOK2 3 /* OFF HOOK2 IRQ */ -#define IRQ_RINGING 4 /* Ringing IRQ */ -#define IRQ_CODEC 5 /* CODEC IRQ */ - -#define __IO_PREFIX hs7751rvoip -#include - -/* arch/sh/boards/renesas/hs7751rvoip/irq.c */ -void init_hs7751rvoip_IRQ(void); - -/* arch/sh/boards/renesas/hs7751rvoip/io.c */ -void *hs7751rvoip_ioremap(unsigned long, unsigned long); - -#endif /* __ASM_SH_RENESAS_HS7751RVOIP */ diff --git a/include/asm-sh/r7780rp/r7780rp.h b/include/asm-sh/r7780rp/r7780rp.h deleted file mode 100644 index f95d9dba31a2..000000000000 --- a/include/asm-sh/r7780rp/r7780rp.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef __ASM_SH_RENESAS_R7780RP_H -#define __ASM_SH_RENESAS_R7780RP_H - -/* - * linux/include/asm-sh/r7780rp.h - * - * Copyright (C) 2000 Atom Create Engineering Co., Ltd. - * - * Renesas Solutions Highlander R7780RP support - */ - -/* Box specific addresses. */ -#if defined(CONFIG_SH_R7780MP) -#define PA_BCR 0xa4000000 /* FPGA */ -#define PA_IRLMSK (PA_BCR+0x0000) /* Interrupt Mask control */ -#define PA_IRLMON (PA_BCR+0x0002) /* Interrupt Status control */ -#define PA_IRLPRI1 (PA_BCR+0x0004) /* Interrupt Priorty 1 */ -#define PA_IRLPRI2 (PA_BCR+0x0006) /* Interrupt Priorty 2 */ -#define PA_IRLPRI3 (PA_BCR+0x0008) /* Interrupt Priorty 3 */ -#define PA_IRLPRI4 (PA_BCR+0x000a) /* Interrupt Priorty 4 */ -#define PA_RSTCTL (PA_BCR+0x000c) /* Reset Control */ -#define PA_PCIBD (PA_BCR+0x000e) /* PCI Board detect control */ -#define PA_PCICD (PA_BCR+0x0010) /* PCI Conector detect control */ -#define PA_EXTGIO (PA_BCR+0x0016) /* Extension GPIO Control */ -#define PA_IVDRMON (PA_BCR+0x0018) /* iVDR Moniter control */ -#define PA_IVDRCTL (PA_BCR+0x001a) /* iVDR control */ -#define PA_OBLED (PA_BCR+0x001c) /* On Board LED control */ -#define PA_OBSW (PA_BCR+0x001e) /* On Board Switch control */ -#define PA_AUDIOSEL (PA_BCR+0x0020) /* Sound Interface Select control */ -#define PA_EXTPLR (PA_BCR+0x001e) /* Extention Pin Polarity control */ -#define PA_TPCTL (PA_BCR+0x0100) /* Touch Panel Access control */ -#define PA_TPDCKCTL (PA_BCR+0x0102) /* Touch Panel Access data control */ -#define PA_TPCTLCLR (PA_BCR+0x0104) /* Touch Panel Access control */ -#define PA_TPXPOS (PA_BCR+0x0106) /* Touch Panel X position control */ -#define PA_TPYPOS (PA_BCR+0x0108) /* Touch Panel Y position control */ -#define PA_DBSW (PA_BCR+0x0200) /* Debug Board Switch control */ -#define PA_CFCTL (PA_BCR+0x0300) /* CF Timing control */ -#define PA_CFPOW (PA_BCR+0x0302) /* CF Power control */ -#define PA_CFCDINTCLR (PA_BCR+0x0304) /* CF Insert Interrupt clear */ -#define PA_SCSMR0 (PA_BCR+0x0400) /* SCIF0 Serial mode control */ -#define PA_SCBRR0 (PA_BCR+0x0404) /* SCIF0 Bit rate control */ -#define PA_SCSCR0 (PA_BCR+0x0408) /* SCIF0 Serial control */ -#define PA_SCFTDR0 (PA_BCR+0x040c) /* SCIF0 Send FIFO control */ -#define PA_SCFSR0 (PA_BCR+0x0410) /* SCIF0 Serial status control */ -#define PA_SCFRDR0 (PA_BCR+0x0414) /* SCIF0 Receive FIFO control */ -#define PA_SCFCR0 (PA_BCR+0x0418) /* SCIF0 FIFO control */ -#define PA_SCTFDR0 (PA_BCR+0x041c) /* SCIF0 Send FIFO data control */ -#define PA_SCRFDR0 (PA_BCR+0x0420) /* SCIF0 Receive FIFO data control */ -#define PA_SCSPTR0 (PA_BCR+0x0424) /* SCIF0 Serial Port control */ -#define PA_SCLSR0 (PA_BCR+0x0428) /* SCIF0 Line Status control */ -#define PA_SCRER0 (PA_BCR+0x042c) /* SCIF0 Serial Error control */ -#define PA_SCSMR1 (PA_BCR+0x0500) /* SCIF1 Serial mode control */ -#define PA_SCBRR1 (PA_BCR+0x0504) /* SCIF1 Bit rate control */ -#define PA_SCSCR1 (PA_BCR+0x0508) /* SCIF1 Serial control */ -#define PA_SCFTDR1 (PA_BCR+0x050c) /* SCIF1 Send FIFO control */ -#define PA_SCFSR1 (PA_BCR+0x0510) /* SCIF1 Serial status control */ -#define PA_SCFRDR1 (PA_BCR+0x0514) /* SCIF1 Receive FIFO control */ -#define PA_SCFCR1 (PA_BCR+0x0518) /* SCIF1 FIFO control */ -#define PA_SCTFDR1 (PA_BCR+0x051c) /* SCIF1 Send FIFO data control */ -#define PA_SCRFDR1 (PA_BCR+0x0520) /* SCIF1 Receive FIFO data control */ -#define PA_SCSPTR1 (PA_BCR+0x0524) /* SCIF1 Serial Port control */ -#define PA_SCLSR1 (PA_BCR+0x0528) /* SCIF1 Line Status control */ -#define PA_SCRER1 (PA_BCR+0x052c) /* SCIF1 Serial Error control */ -#define PA_ICCR (PA_BCR+0x0600) /* Serial control */ -#define PA_SAR (PA_BCR+0x0602) /* Serial Slave control */ -#define PA_MDR (PA_BCR+0x0604) /* Serial Mode control */ -#define PA_ADR1 (PA_BCR+0x0606) /* Serial Address1 control */ -#define PA_DAR1 (PA_BCR+0x0646) /* Serial Data1 control */ -#define PA_VERREG (PA_BCR+0x0700) /* FPGA Version Register */ -#define PA_POFF (PA_BCR+0x0800) /* System Power Off control */ -#define PA_PMR (PA_BCR+0x0900) /* */ - -#define PA_AX88796L 0xa4100400 /* AX88796L Area */ -#define PA_SC1602BSLB 0xa6000000 /* SC1602BSLB Area */ -#define PA_AREA5_IO 0xb4000000 /* Area 5 IO Memory */ -#define PA_AREA6_IO 0xb8000000 /* Area 6 IO Memory */ -#define PA_IDE_OFFSET 0x1f0 /* CF IDE Offset */ -#define AX88796L_IO_BASE 0x1000 /* AX88796L IO Base Address */ - -#define IRLCNTR1 (PA_BCR + 0) /* Interrupt Control Register1 */ - -#define IRQ_PCISLOT1 65 /* PCI Slot #1 IRQ */ -#define IRQ_PCISLOT2 66 /* PCI Slot #2 IRQ */ -#define IRQ_PCISLOT3 67 /* PCI Slot #3 IRQ */ -#define IRQ_PCISLOT4 68 /* PCI Slot #4 IRQ */ -#define IRQ_CFCARD 1 /* CF Card IRQ */ -// #define IRQ_CFINST 0 /* CF Card Insert IRQ */ -#define IRQ_TP 2 /* Touch Panel IRQ */ -#define IRQ_SCI1 3 /* SCI1 IRQ */ -#define IRQ_SCI0 4 /* SCI0 IRQ */ -#define IRQ_2SERIAL 5 /* Serial IRQ */ -#define IRQ_RTC 6 /* RTC A / B IRQ */ -#define IRQ_EXTENTION6 7 /* EXT6n IRQ */ -#define IRQ_EXTENTION5 8 /* EXT5n IRQ */ -#define IRQ_EXTENTION4 9 /* EXT4n IRQ */ -#define IRQ_EXTENTION2 10 /* EXT2n IRQ */ -#define IRQ_EXTENTION1 11 /* EXT1n IRQ */ -#define IRQ_ONETH 13 /* On board Ethernet IRQ */ -#define IRQ_PSW 14 /* Push Switch IRQ */ - -#else /* R7780RP */ - -#define PA_BCR 0xa5000000 /* FPGA */ -#define PA_IRLMSK (PA_BCR+0x0000) /* Interrupt Mask control */ -#define PA_IRLMON (PA_BCR+0x0002) /* Interrupt Status control */ -#define PA_SDPOW (PA_BCR+0x0004) /* SD Power control */ -#define PA_RSTCTL (PA_BCR+0x0006) /* Device Reset control */ -#define PA_PCIBD (PA_BCR+0x0008) /* PCI Board detect control */ -#define PA_PCICD (PA_BCR+0x000a) /* PCI Conector detect control */ -#define PA_ZIGIO1 (PA_BCR+0x000c) /* Zigbee IO control 1 */ -#define PA_ZIGIO2 (PA_BCR+0x000e) /* Zigbee IO control 2 */ -#define PA_ZIGIO3 (PA_BCR+0x0010) /* Zigbee IO control 3 */ -#define PA_ZIGIO4 (PA_BCR+0x0012) /* Zigbee IO control 4 */ -#define PA_IVDRMON (PA_BCR+0x0014) /* iVDR Moniter control */ -#define PA_IVDRCTL (PA_BCR+0x0016) /* iVDR control */ -#define PA_OBLED (PA_BCR+0x0018) /* On Board LED control */ -#define PA_OBSW (PA_BCR+0x001a) /* On Board Switch control */ -#define PA_AUDIOSEL (PA_BCR+0x001c) /* Sound Interface Select control */ -#define PA_EXTPLR (PA_BCR+0x001e) /* Extention Pin Polarity control */ -#define PA_TPCTL (PA_BCR+0x0100) /* Touch Panel Access control */ -#define PA_TPDCKCTL (PA_BCR+0x0102) /* Touch Panel Access data control */ -#define PA_TPCTLCLR (PA_BCR+0x0104) /* Touch Panel Access control */ -#define PA_TPXPOS (PA_BCR+0x0106) /* Touch Panel X position control */ -#define PA_TPYPOS (PA_BCR+0x0108) /* Touch Panel Y position control */ -#define PA_DBDET (PA_BCR+0x0200) /* Debug Board detect control */ -#define PA_DBDISPCTL (PA_BCR+0x0202) /* Debug Board Dot timing control */ -#define PA_DBSW (PA_BCR+0x0204) /* Debug Board Switch control */ -#define PA_CFCTL (PA_BCR+0x0300) /* CF Timing control */ -#define PA_CFPOW (PA_BCR+0x0302) /* CF Power control */ -#define PA_CFCDINTCLR (PA_BCR+0x0304) /* CF Insert Interrupt clear */ -#define PA_SCSMR (PA_BCR+0x0400) /* SCIF Serial mode control */ -#define PA_SCBRR (PA_BCR+0x0402) /* SCIF Bit rate control */ -#define PA_SCSCR (PA_BCR+0x0404) /* SCIF Serial control */ -#define PA_SCFDTR (PA_BCR+0x0406) /* SCIF Send FIFO control */ -#define PA_SCFSR (PA_BCR+0x0408) /* SCIF Serial status control */ -#define PA_SCFRDR (PA_BCR+0x040a) /* SCIF Receive FIFO control */ -#define PA_SCFCR (PA_BCR+0x040c) /* SCIF FIFO control */ -#define PA_SCFDR (PA_BCR+0x040e) /* SCIF FIFO data control */ -#define PA_SCLSR (PA_BCR+0x0412) /* SCIF Line Status control */ -#define PA_ICCR (PA_BCR+0x0500) /* Serial control */ -#define PA_SAR (PA_BCR+0x0502) /* Serial Slave control */ -#define PA_MDR (PA_BCR+0x0504) /* Serial Mode control */ -#define PA_ADR1 (PA_BCR+0x0506) /* Serial Address1 control */ -#define PA_DAR1 (PA_BCR+0x0546) /* Serial Data1 control */ -#define PA_VERREG (PA_BCR+0x0600) /* FPGA Version Register */ - -#define PA_AX88796L 0xa5800400 /* AX88796L Area */ -#define PA_SC1602BSLB 0xa6000000 /* SC1602BSLB Area */ -#define PA_AREA5_IO 0xb4000000 /* Area 5 IO Memory */ -#define PA_AREA6_IO 0xb8000000 /* Area 6 IO Memory */ -#define PA_IDE_OFFSET 0x1f0 /* CF IDE Offset */ -#define AX88796L_IO_BASE 0x1000 /* AX88796L IO Base Address */ - -#define IRLCNTR1 (PA_BCR + 0) /* Interrupt Control Register1 */ - -#define IRQ_PCISLOT1 0 /* PCI Slot #1 IRQ */ -#define IRQ_PCISLOT2 1 /* PCI Slot #2 IRQ */ -#define IRQ_PCISLOT3 2 /* PCI Slot #3 IRQ */ -#define IRQ_PCISLOT4 3 /* PCI Slot #4 IRQ */ -#define IRQ_CFCARD 4 /* CF Card IRQ */ -#define IRQ_CFINST 5 /* CF Card Insert IRQ */ -#define IRQ_M66596 6 /* M66596 IRQ */ -#define IRQ_SDCARD 7 /* SD Card IRQ */ -#define IRQ_TUCHPANEL 8 /* Touch Panel IRQ */ -#define IRQ_SCI 9 /* SCI IRQ */ -#define IRQ_2SERIAL 10 /* Serial IRQ */ -#define IRQ_EXTENTION 11 /* EXTn IRQ */ -#define IRQ_ONETH 12 /* On board Ethernet IRQ */ -#define IRQ_PSW 13 /* Push Switch IRQ */ -#define IRQ_ZIGBEE 14 /* Ziggbee IO IRQ */ - -#endif /* CONFIG_SH_R7780MP */ - -#define __IO_PREFIX r7780rp -#include - -#endif /* __ASM_SH_RENESAS_R7780RP */ diff --git a/include/asm-sh/rts7751r2d/rts7751r2d.h b/include/asm-sh/rts7751r2d/rts7751r2d.h deleted file mode 100644 index 796b8fcb81a8..000000000000 --- a/include/asm-sh/rts7751r2d/rts7751r2d.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef __ASM_SH_RENESAS_RTS7751R2D_H -#define __ASM_SH_RENESAS_RTS7751R2D_H - -/* - * linux/include/asm-sh/renesas_rts7751r2d.h - * - * Copyright (C) 2000 Atom Create Engineering Co., Ltd. - * - * Renesas Technology Sales RTS7751R2D support - */ - -/* Box specific addresses. */ - -#define PA_BCR 0xa4000000 /* FPGA */ -#define PA_IRLMON 0xa4000002 /* Interrupt Status control */ -#define PA_CFCTL 0xa4000004 /* CF Timing control */ -#define PA_CFPOW 0xa4000006 /* CF Power control */ -#define PA_DISPCTL 0xa4000008 /* Display Timing control */ -#define PA_SDMPOW 0xa400000a /* SD Power control */ -#define PA_RTCCE 0xa400000c /* RTC(9701) Enable control */ -#define PA_PCICD 0xa400000e /* PCI Extention detect control */ -#define PA_VOYAGERRTS 0xa4000020 /* VOYAGER Reset control */ -#if defined(CONFIG_RTS7751R2D_REV11) -#define PA_AXRST 0xa4000022 /* AX_LAN Reset control */ -#define PA_CFRST 0xa4000024 /* CF Reset control */ -#define PA_ADMRTS 0xa4000026 /* SD Reset control */ -#define PA_EXTRST 0xa4000028 /* Extention Reset control */ -#define PA_CFCDINTCLR 0xa400002a /* CF Insert Interrupt clear */ -#else -#define PA_CFRST 0xa4000022 /* CF Reset control */ -#define PA_ADMRTS 0xa4000024 /* SD Reset control */ -#define PA_EXTRST 0xa4000026 /* Extention Reset control */ -#define PA_CFCDINTCLR 0xa4000028 /* CF Insert Interrupt clear */ -#define PA_KEYCTLCLR 0xa400002a /* Key Interrupt clear */ -#endif -#define PA_POWOFF 0xa4000030 /* Board Power OFF control */ -#define PA_VERREG 0xa4000032 /* FPGA Version Register */ -#define PA_INPORT 0xa4000034 /* KEY Input Port control */ -#define PA_OUTPORT 0xa4000036 /* LED control */ -#define PA_DMPORT 0xa4000038 /* DM270 Output Port control */ - -#define PA_AX88796L 0xaa000400 /* AX88796L Area */ -#define PA_VOYAGER 0xab000000 /* VOYAGER GX Area */ -#define PA_IDE_OFFSET 0x1f0 /* CF IDE Offset */ -#define AX88796L_IO_BASE 0x1000 /* AX88796L IO Base Address */ - -#define IRLCNTR1 (PA_BCR + 0) /* Interrupt Control Register1 */ - -#if defined(CONFIG_RTS7751R2D_REV11) -#define IRQ_PCIETH 0 /* PCI Ethernet IRQ */ -#define IRQ_CFCARD 1 /* CF Card IRQ */ -#define IRQ_CFINST 2 /* CF Card Insert IRQ */ -#define IRQ_PCMCIA 3 /* PCMCIA IRQ */ -#define IRQ_VOYAGER 4 /* VOYAGER IRQ */ -#define IRQ_ONETH 5 /* On board Ethernet IRQ */ -#else -#define IRQ_KEYIN 0 /* Key Input IRQ */ -#define IRQ_PCIETH 1 /* PCI Ethernet IRQ */ -#define IRQ_CFCARD 2 /* CF Card IRQ */ -#define IRQ_CFINST 3 /* CF Card Insert IRQ */ -#define IRQ_PCMCIA 4 /* PCMCIA IRQ */ -#define IRQ_VOYAGER 5 /* VOYAGER IRQ */ -#endif -#define IRQ_RTCALM 6 /* RTC Alarm IRQ */ -#define IRQ_RTCTIME 7 /* RTC Timer IRQ */ -#define IRQ_SDCARD 8 /* SD Card IRQ */ -#define IRQ_PCISLOT1 9 /* PCI Slot #1 IRQ */ -#define IRQ_PCISLOT2 10 /* PCI Slot #2 IRQ */ -#define IRQ_EXTENTION 11 /* EXTn IRQ */ - -#define __IO_PREFIX rts7751r2d -#include - -#endif /* __ASM_SH_RENESAS_RTS7751R2D */ diff --git a/include/asm-sh/shmin/shmin.h b/include/asm-sh/shmin/shmin.h deleted file mode 100644 index 36ba138a81fb..000000000000 --- a/include/asm-sh/shmin/shmin.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef __ASM_SH_SHMIN_H -#define __ASM_SH_SHMIN_H - -#define SHMIN_IO_BASE 0xb0000000UL - -#define SHMIN_NE_IRQ IRQ2_IRQ -#define SHMIN_NE_BASE 0x300 - -#endif diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index 3b3b4da8cfd3..51f554154c48 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #define MODNAME "sh_dac_audio" -- cgit v1.2.3 From 58f539740b1ccfc5ef4e509ec2efe82621b546e3 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 20 Oct 2006 00:32:41 -0700 Subject: [NET]: Can use __get_cpu_var() instead of per_cpu() in loopback driver. As BHs are off in loopback_xmit(), preemption cannot occurs, so we can use __get_cpu_var() instead of per_cpu() (and avoid a preempt_enable()/preempt_disable() pair) Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/loopback.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 93fbea1c9271..82c10dec1b5a 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -153,14 +153,14 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) #endif dev->last_rx = jiffies; - lb_stats = &per_cpu(pcpu_lstats, get_cpu()); + /* it's OK to use __get_cpu_var() because BHs are off */ + lb_stats = &__get_cpu_var(pcpu_lstats); lb_stats->bytes += skb->len; lb_stats->packets++; - put_cpu(); netif_rx(skb); - return(0); + return 0; } static struct net_device_stats loopback_stats; -- cgit v1.2.3 From 0eab934f4b9668669cffebfa8a9542fedf9082af Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 20 Oct 2006 08:55:29 +0200 Subject: [Bluetooth] Add support for newer ANYCOM USB dongles This patch adds the vendor and product id of the ANYCOM Bluetooth USB-200 and USB-250 dongles and sets a flag to send HCI_Reset as the first command. Signed-off-by: Marcel Holtmann Date: Fri, 20 Oct 2006 08:55:34 +0200 Subject: [Bluetooth] Add missing entry for Nokia DTL-4 PCMCIA card The device id for the Nokia DTL-4 PCMCIA card was missing. This patch adds it back to the list of supported devices. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/dtl1_cs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index e7c800f4c3ad..07eafbc5dc3a 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -711,6 +711,7 @@ static void dtl1_release(struct pcmcia_device *link) static struct pcmcia_device_id dtl1_ids[] = { PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-1", 0xe1bfdd64, 0xe168480d), + PCMCIA_DEVICE_PROD_ID12("Nokia Mobile Phones", "DTL-4", 0xe1bfdd64, 0x9102bc82), PCMCIA_DEVICE_PROD_ID12("Socket", "CF", 0xb38bcc2e, 0x44ebf863), PCMCIA_DEVICE_PROD_ID12("Socket", "CF+ Personal Network Card", 0xb38bcc2e, 0xe732bae3), PCMCIA_DEVICE_NULL -- cgit v1.2.3 From e8e82b76e0312827f5ae04b573a05b02854a447e Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Thu, 19 Oct 2006 23:28:12 -0700 Subject: [PATCH] e100: fix reboot -f with netconsole enabled When rebooting with netconsole over e100, the driver shutdown code would deadlock with netpoll. Reduce shutdown code to a bare minimum while retaining WoL and suspend functionality. Signed-off-by: Auke Kok Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/e100.c | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 27d5d2f02533..a3a08a5dd185 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2039,7 +2039,6 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu) return 0; } -#ifdef CONFIG_PM static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ @@ -2048,7 +2047,6 @@ static int e100_asf(struct nic *nic) !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE)); } -#endif static int e100_up(struct nic *nic) { @@ -2715,34 +2713,32 @@ static void __devexit e100_remove(struct pci_dev *pdev) } } +#ifdef CONFIG_PM static int e100_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - if (netif_running(netdev)) - e100_down(nic); - e100_hw_reset(nic); - netif_device_detach(netdev); + netif_poll_disable(nic->netdev); + del_timer_sync(&nic->watchdog); + netif_carrier_off(nic->netdev); -#ifdef CONFIG_PM pci_save_state(pdev); - if (nic->flags & (wol_magic | e100_asf(nic))) -#else - if (nic->flags & (wol_magic)) -#endif - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - else - /* disable PME */ - pci_enable_wake(pdev, 0, 0); + + if ((nic->flags & wol_magic) | e100_asf(nic)) { + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); + pci_set_power_state(pdev, PCI_D3hot); return 0; } -#ifdef CONFIG_PM static int e100_resume(struct pci_dev *pdev) { struct net_device *netdev = pci_get_drvdata(pdev); @@ -2764,7 +2760,23 @@ static int e100_resume(struct pci_dev *pdev) static void e100_shutdown(struct pci_dev *pdev) { - e100_suspend(pdev, PMSG_SUSPEND); + struct net_device *netdev = pci_get_drvdata(pdev); + struct nic *nic = netdev_priv(netdev); + + netif_poll_disable(nic->netdev); + del_timer_sync(&nic->watchdog); + netif_carrier_off(nic->netdev); + + if ((nic->flags & wol_magic) | e100_asf(nic)) { + pci_enable_wake(pdev, PCI_D3hot, 1); + pci_enable_wake(pdev, PCI_D3cold, 1); + } else { + pci_enable_wake(pdev, PCI_D3hot, 0); + pci_enable_wake(pdev, PCI_D3cold, 0); + } + + pci_disable_device(pdev); + pci_set_power_state(pdev, PCI_D3hot); } /* ------------------ PCI Error Recovery infrastructure -------------- */ @@ -2848,9 +2860,9 @@ static struct pci_driver e100_driver = { .id_table = e100_id_table, .probe = e100_probe, .remove = __devexit_p(e100_remove), +#ifdef CONFIG_PM /* Power Management hooks */ .suspend = e100_suspend, -#ifdef CONFIG_PM .resume = e100_resume, #endif .shutdown = e100_shutdown, -- cgit v1.2.3 From 3fcfab16c5b86eaa3db3a9a31adba550c5b67141 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 19 Oct 2006 23:28:16 -0700 Subject: [PATCH] separate bdi congestion functions from queue congestion functions Separate out the concept of "queue congestion" from "backing-dev congestion". Congestion is a backing-dev concept, not a queue concept. The blk_* congestion functions are retained, as wrappers around the core backing-dev congestion functions. This proper layering is needed so that NFS can cleanly use the congestion functions, and so that CONFIG_BLOCK=n actually links. Cc: "Thomas Maier" Cc: "Jens Axboe" Cc: Trond Myklebust Cc: David Howells Cc: Peter Osterlund Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/lib/usercopy.c | 3 +- block/ll_rw_blk.c | 71 --------------------------------------------- drivers/md/dm-crypt.c | 3 +- fs/fat/file.c | 3 +- fs/nfs/write.c | 4 ++- fs/reiserfs/journal.c | 3 +- fs/xfs/linux-2.6/kmem.c | 5 ++-- fs/xfs/linux-2.6/xfs_buf.c | 3 +- include/linux/backing-dev.h | 7 +++++ include/linux/blkdev.h | 24 ++++++++++++--- include/linux/writeback.h | 1 - mm/Makefile | 3 +- mm/backing-dev.c | 69 +++++++++++++++++++++++++++++++++++++++++++ mm/page-writeback.c | 17 +++-------- mm/page_alloc.c | 5 ++-- mm/shmem.c | 3 +- mm/vmscan.c | 6 ++-- 17 files changed, 126 insertions(+), 104 deletions(-) create mode 100644 mm/backing-dev.c (limited to 'drivers') diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c index 258df6b4d7d7..d22cfc9d656c 100644 --- a/arch/i386/lib/usercopy.c +++ b/arch/i386/lib/usercopy.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -741,7 +742,7 @@ survive: if (retval == -ENOMEM && is_init(current)) { up_read(¤t->mm->mmap_sem); - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); goto survive; } diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 132a858ce2c5..136066583c68 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -56,11 +56,6 @@ static kmem_cache_t *requestq_cachep; */ static kmem_cache_t *iocontext_cachep; -static wait_queue_head_t congestion_wqh[2] = { - __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), - __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) - }; - /* * Controlling structure to kblockd */ @@ -112,37 +107,6 @@ static void blk_queue_congestion_threshold(struct request_queue *q) q->nr_congestion_off = nr; } -/* - * A queue has just exitted congestion. Note this in the global counter of - * congested queues, and wake up anyone who was waiting for requests to be - * put back. - */ -void blk_clear_queue_congested(request_queue_t *q, int rw) -{ - enum bdi_state bit; - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - clear_bit(bit, &q->backing_dev_info.state); - smp_mb__after_clear_bit(); - if (waitqueue_active(wqh)) - wake_up(wqh); -} -EXPORT_SYMBOL(blk_clear_queue_congested); - -/* - * A queue has just entered congestion. Flag that in the queue's VM-visible - * state flags and increment the global gounter of congested queues. - */ -void blk_set_queue_congested(request_queue_t *q, int rw) -{ - enum bdi_state bit; - - bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; - set_bit(bit, &q->backing_dev_info.state); -} -EXPORT_SYMBOL(blk_set_queue_congested); - /** * blk_get_backing_dev_info - get the address of a queue's backing_dev_info * @bdev: device @@ -2755,41 +2719,6 @@ void blk_end_sync_rq(struct request *rq, int error) } EXPORT_SYMBOL(blk_end_sync_rq); -/** - * blk_congestion_wait - wait for a queue to become uncongested - * @rw: READ or WRITE - * @timeout: timeout in jiffies - * - * Waits for up to @timeout jiffies for a queue (any queue) to exit congestion. - * If no queues are congested then just wait for the next request to be - * returned. - */ -long blk_congestion_wait(int rw, long timeout) -{ - long ret; - DEFINE_WAIT(wait); - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); - ret = io_schedule_timeout(timeout); - finish_wait(wqh, &wait); - return ret; -} - -EXPORT_SYMBOL(blk_congestion_wait); - -/** - * blk_congestion_end - wake up sleepers on a congestion queue - * @rw: READ or WRITE - */ -void blk_congestion_end(int rw) -{ - wait_queue_head_t *wqh = &congestion_wqh[rw]; - - if (waitqueue_active(wqh)) - wake_up(wqh); -} - /* * Has to be called with the request spinlock acquired */ diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 655d816760e5..a625576fdeeb 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -602,7 +603,7 @@ static void process_write(struct crypt_io *io) /* out of memory -> run queues */ if (remaining) - blk_congestion_wait(bio_data_dir(clone), HZ/100); + congestion_wait(bio_data_dir(clone), HZ/100); } } diff --git a/fs/fat/file.c b/fs/fat/file.c index f4b8f8b3fbdd..8337451e7897 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -13,6 +13,7 @@ #include #include #include +#include #include int fat_generic_ioctl(struct inode *inode, struct file *filp, @@ -118,7 +119,7 @@ static int fat_file_release(struct inode *inode, struct file *filp) if ((filp->f_mode & FMODE_WRITE) && MSDOS_SB(inode->i_sb)->options.flush) { fat_flush_inodes(inode->i_sb, inode, NULL); - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); } return 0; } diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f6675d2c386c..ca92ac36fe9d 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -57,6 +57,8 @@ #include #include #include +#include + #include #include @@ -395,7 +397,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc) out: clear_bit(BDI_write_congested, &bdi->state); wake_up_all(&nfs_write_congestion); - writeback_congestion_end(); + congestion_end(WRITE); return err; } diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index ad8cbc49883a..85ce23268302 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -53,6 +53,7 @@ #include #include #include +#include /* gets a struct reiserfs_journal_list * from a list head */ #define JOURNAL_LIST_ENTRY(h) (list_entry((h), struct reiserfs_journal_list, \ @@ -970,7 +971,7 @@ int reiserfs_async_progress_wait(struct super_block *s) DEFINE_WAIT(wait); struct reiserfs_journal *j = SB_JOURNAL(s); if (atomic_read(&j->j_async_throttle)) - blk_congestion_wait(WRITE, HZ / 10); + congestion_wait(WRITE, HZ / 10); return 0; } diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c index d59737589815..004baf600611 100644 --- a/fs/xfs/linux-2.6/kmem.c +++ b/fs/xfs/linux-2.6/kmem.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "time.h" #include "kmem.h" @@ -53,7 +54,7 @@ kmem_alloc(size_t size, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __FUNCTION__, lflags); - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); } while (1); } @@ -131,7 +132,7 @@ kmem_zone_alloc(kmem_zone_t *zone, unsigned int __nocast flags) printk(KERN_ERR "XFS: possible memory allocation " "deadlock in %s (mode:0x%x)\n", __FUNCTION__, lflags); - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); } while (1); } diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index 9bbadafdcb00..db5f5a3608ca 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "xfs_linux.h" STATIC kmem_zone_t *xfs_buf_zone; @@ -395,7 +396,7 @@ _xfs_buf_lookup_pages( XFS_STATS_INC(xb_page_retries); xfsbufd_wakeup(0, gfp_mask); - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); goto retry; } diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h index f7a1390d67f5..7011d6255593 100644 --- a/include/linux/backing-dev.h +++ b/include/linux/backing-dev.h @@ -10,6 +10,8 @@ #include +struct page; + /* * Bits in backing_dev_info.state */ @@ -88,6 +90,11 @@ static inline int bdi_rw_congested(struct backing_dev_info *bdi) (1 << BDI_write_congested)); } +void clear_bdi_congested(struct backing_dev_info *bdi, int rw); +void set_bdi_congested(struct backing_dev_info *bdi, int rw); +long congestion_wait(int rw, long timeout); +void congestion_end(int rw); + #define bdi_cap_writeback_dirty(bdi) \ (!((bdi)->capabilities & BDI_CAP_NO_WRITEBACK)) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9575e3a5ff2a..7bfcde2d5578 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -651,8 +651,26 @@ extern void blk_recount_segments(request_queue_t *, struct bio *); extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *); extern int sg_scsi_ioctl(struct file *, struct request_queue *, struct gendisk *, struct scsi_ioctl_command __user *); -extern void blk_clear_queue_congested(request_queue_t *q, int rw); -extern void blk_set_queue_congested(request_queue_t *q, int rw); + +/* + * A queue has just exitted congestion. Note this in the global counter of + * congested queues, and wake up anyone who was waiting for requests to be + * put back. + */ +static inline void blk_clear_queue_congested(request_queue_t *q, int rw) +{ + clear_bdi_congested(&q->backing_dev_info, rw); +} + +/* + * A queue has just entered congestion. Flag that in the queue's VM-visible + * state flags and increment the global gounter of congested queues. + */ +static inline void blk_set_queue_congested(request_queue_t *q, int rw) +{ + set_bdi_congested(&q->backing_dev_info, rw); +} + extern void blk_start_queue(request_queue_t *q); extern void blk_stop_queue(request_queue_t *q); extern void blk_sync_queue(struct request_queue *q); @@ -767,10 +785,8 @@ extern int blk_queue_init_tags(request_queue_t *, int, struct blk_queue_tag *); extern void blk_queue_free_tags(request_queue_t *); extern int blk_queue_resize_tags(request_queue_t *, int); extern void blk_queue_invalidate_tags(request_queue_t *); -extern long blk_congestion_wait(int rw, long timeout); extern struct blk_queue_tag *blk_init_tags(int); extern void blk_free_tags(struct blk_queue_tag *); -extern void blk_congestion_end(int rw); static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt, int tag) diff --git a/include/linux/writeback.h b/include/linux/writeback.h index a341c8032866..fc35e6bdfb93 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -85,7 +85,6 @@ int wakeup_pdflush(long nr_pages); void laptop_io_completion(void); void laptop_sync_completion(void); void throttle_vm_writeout(void); -void writeback_congestion_end(void); /* These are exported to sysctl. */ extern int dirty_background_ratio; diff --git a/mm/Makefile b/mm/Makefile index 12b3a4eee88d..f3c077eb0b8e 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -10,7 +10,8 @@ mmu-$(CONFIG_MMU) := fremap.o highmem.o madvise.o memory.o mincore.o \ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \ page_alloc.o page-writeback.o pdflush.o \ readahead.o swap.o truncate.o vmscan.o \ - prio_tree.o util.o mmzone.o vmstat.o $(mmu-y) + prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ + $(mmu-y) ifeq ($(CONFIG_MMU)$(CONFIG_BLOCK),yy) obj-y += bounce.o diff --git a/mm/backing-dev.c b/mm/backing-dev.c new file mode 100644 index 000000000000..f50a2811f9dc --- /dev/null +++ b/mm/backing-dev.c @@ -0,0 +1,69 @@ + +#include +#include +#include +#include +#include + +static wait_queue_head_t congestion_wqh[2] = { + __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), + __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) + }; + + +void clear_bdi_congested(struct backing_dev_info *bdi, int rw) +{ + enum bdi_state bit; + wait_queue_head_t *wqh = &congestion_wqh[rw]; + + bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; + clear_bit(bit, &bdi->state); + smp_mb__after_clear_bit(); + if (waitqueue_active(wqh)) + wake_up(wqh); +} +EXPORT_SYMBOL(clear_bdi_congested); + +void set_bdi_congested(struct backing_dev_info *bdi, int rw) +{ + enum bdi_state bit; + + bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; + set_bit(bit, &bdi->state); +} +EXPORT_SYMBOL(set_bdi_congested); + +/** + * congestion_wait - wait for a backing_dev to become uncongested + * @rw: READ or WRITE + * @timeout: timeout in jiffies + * + * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit + * write congestion. If no backing_devs are congested then just wait for the + * next write to be completed. + */ +long congestion_wait(int rw, long timeout) +{ + long ret; + DEFINE_WAIT(wait); + wait_queue_head_t *wqh = &congestion_wqh[rw]; + + prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); + ret = io_schedule_timeout(timeout); + finish_wait(wqh, &wait); + return ret; +} +EXPORT_SYMBOL(congestion_wait); + +/** + * congestion_end - wake up sleepers on a congested backing_dev_info + * @rw: READ or WRITE + */ +void congestion_end(int rw) +{ + wait_queue_head_t *wqh = &congestion_wqh[rw]; + + if (waitqueue_active(wqh)) + wake_up(wqh); +} +EXPORT_SYMBOL(congestion_end); diff --git a/mm/page-writeback.c b/mm/page-writeback.c index a0f339057449..8d9b19f239c3 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -222,7 +222,7 @@ static void balance_dirty_pages(struct address_space *mapping) if (pages_written >= write_chunk) break; /* We've done our duty */ } - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); } if (nr_reclaimable + global_page_state(NR_WRITEBACK) @@ -314,7 +314,7 @@ void throttle_vm_writeout(void) if (global_page_state(NR_UNSTABLE_NFS) + global_page_state(NR_WRITEBACK) <= dirty_thresh) break; - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); } } @@ -351,7 +351,7 @@ static void background_writeout(unsigned long _min_pages) min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write; if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) { /* Wrote less than expected */ - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); if (!wbc.encountered_congestion) break; } @@ -422,7 +422,7 @@ static void wb_kupdate(unsigned long arg) writeback_inodes(&wbc); if (wbc.nr_to_write > 0) { if (wbc.encountered_congestion) - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); else break; /* All the old data is written */ } @@ -955,15 +955,6 @@ int test_set_page_writeback(struct page *page) } EXPORT_SYMBOL(test_set_page_writeback); -/* - * Wakes up tasks that are being throttled due to writeback congestion - */ -void writeback_congestion_end(void) -{ - blk_congestion_end(WRITE); -} -EXPORT_SYMBOL(writeback_congestion_end); - /* * Return true if any of the pages in the mapping are marged with the * passed tag. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 40db96a655d0..afee38f04d84 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -1050,7 +1051,7 @@ nofail_alloc: if (page) goto got_pg; if (gfp_mask & __GFP_NOFAIL) { - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); goto nofail_alloc; } } @@ -1113,7 +1114,7 @@ rebalance: do_retry = 1; } if (do_retry) { - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); goto rebalance; } diff --git a/mm/shmem.c b/mm/shmem.c index b378f66cf2f9..4959535fc14c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -1131,7 +1132,7 @@ repeat: page_cache_release(swappage); if (error == -ENOMEM) { /* let kswapd refresh zone for GFP_ATOMICs */ - blk_congestion_wait(WRITE, HZ/50); + congestion_wait(WRITE, HZ/50); } goto repeat; } diff --git a/mm/vmscan.c b/mm/vmscan.c index af73c14f9d88..f05527bf792b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1059,7 +1059,7 @@ unsigned long try_to_free_pages(struct zone **zones, gfp_t gfp_mask) /* Take a nap, wait for some writeback to complete */ if (sc.nr_scanned && priority < DEF_PRIORITY - 2) - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); } /* top priority shrink_caches still had more to do? don't OOM, then */ if (!sc.all_unreclaimable) @@ -1214,7 +1214,7 @@ scan: * another pass across the zones. */ if (total_scanned && priority < DEF_PRIORITY - 2) - blk_congestion_wait(WRITE, HZ/10); + congestion_wait(WRITE, HZ/10); /* * We do this so kswapd doesn't build up large priorities for @@ -1458,7 +1458,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages) goto out; if (sc.nr_scanned && prio < DEF_PRIORITY - 2) - blk_congestion_wait(WRITE, HZ / 10); + congestion_wait(WRITE, HZ / 10); } lru_pages = 0; -- cgit v1.2.3 From 74e8b51d254865b8abe4a94b5eb82b1940ec820c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 19 Oct 2006 23:28:26 -0700 Subject: [PATCH] Kconfig serial typos Fix typo (repeated) in serial Kconfig. Signed-off-by: Randy Dunlap Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b0d502622d94..0b71e7d18903 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -767,37 +767,37 @@ config SERIAL_CPM_SCC1 bool "Support for SCC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC1 as a serial port + Select this option to use SCC1 as a serial port config SERIAL_CPM_SCC2 bool "Support for SCC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC2 as a serial port + Select this option to use SCC2 as a serial port config SERIAL_CPM_SCC3 bool "Support for SCC3 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC3 as a serial port + Select this option to use SCC3 as a serial port config SERIAL_CPM_SCC4 bool "Support for SCC4 serial port" depends on SERIAL_CPM=y help - Select the is option to use SCC4 as a serial port + Select this option to use SCC4 as a serial port config SERIAL_CPM_SMC1 bool "Support for SMC1 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC1 as a serial port + Select this option to use SMC1 as a serial port config SERIAL_CPM_SMC2 bool "Support for SMC2 serial port" depends on SERIAL_CPM=y help - Select the is option to use SMC2 as a serial port + Select this option to use SMC2 as a serial port config SERIAL_SGI_L1_CONSOLE bool "SGI Altix L1 serial console support" -- cgit v1.2.3 From c5a114f1fb2d3c54be62779a705e088471063b47 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 19 Oct 2006 23:28:28 -0700 Subject: [PATCH] fix "ACPI: Processor native C-states using MWAIT" This patch breaks C-state discovery on my IBM IntelliStation Z30 because the return value of acpi_processor_get_power_info_fadt is not assigned to "result" in the case that acpi_processor_get_power_info_cst returns -ENODEV. Thus, if ACPI provides C-state data via the FADT and not _CST (as is the case on this machine), we incorrectly exit the function with -ENODEV after reading the FADT. The attached patch sets the value of result so that we don't exit early. Signed-off-by: Darrick J. Wong Acked-by: "Pallipadi, Venkatesh" Acked-by: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/processor_idle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e67144cf3c8b..65b3f056ad89 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -962,7 +962,7 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) - acpi_processor_get_power_info_fadt(pr); + result = acpi_processor_get_power_info_fadt(pr); if (result) return result; -- cgit v1.2.3 From 6cbe44cd8d48a92856295f445183f52bf42a544d Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Thu, 19 Oct 2006 23:28:30 -0700 Subject: [PATCH] Change log level of a message of acpi_memhotplug to KERN_DEBUG I suppose this message seems quite useless except debugging. It just shows "Hotplug Mem Device". System admin can't know anything by this message. So, I would like to change it to KERN_DEBUG. Signed-off-by: Yasunori Goto Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 98099de59b45..9090b5acc5e3 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -414,7 +414,7 @@ static int acpi_memory_device_add(struct acpi_device *device) /* Set the device state */ mem_device->state = MEMORY_POWER_ON_STATE; - printk(KERN_INFO "%s \n", acpi_device_name(device)); + printk(KERN_DEBUG "%s \n", acpi_device_name(device)); return result; } -- cgit v1.2.3 From 887b95931b4072e60e3bf4253ff7bffe372bca46 Mon Sep 17 00:00:00 2001 From: Yasunori Goto Date: Thu, 19 Oct 2006 23:28:31 -0700 Subject: [PATCH] acpi memory hotplug: remove strange add_memory fail message I wrote a patch to avoid redundant memory hot-add call at boot time. This was cause of strange fail message of memory hotplug like "ACPI: add_memory failed". Memory is recognized by early boot code with EFI/E820. But, if DSDT describes memory devices for them, then hot-add code is called for already recognized memory, and it shows fail messages with -EEXIST. So, sys admin will misunderstand this message as something wrong by it. This patch avoids them by preventing redundant hot-add call until completion of driver initialization. [akpm@osdl.org: cleanups] Signed-off-by: Yasunori Goto Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/acpi_memhotplug.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index 9090b5acc5e3..6bcd9e8e7bcb 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -85,6 +85,8 @@ struct acpi_memory_device { struct list_head res_list; }; +static int acpi_hotmem_initialized; + static acpi_status acpi_memory_get_resource(struct acpi_resource *resource, void *context) { @@ -438,6 +440,15 @@ static int acpi_memory_device_start (struct acpi_device *device) struct acpi_memory_device *mem_device; int result = 0; + /* + * Early boot code has recognized memory area by EFI/E820. + * If DSDT shows these memory devices on boot, hotplug is not necessary + * for them. So, it just returns until completion of this driver's + * start up. + */ + if (!acpi_hotmem_initialized) + return 0; + mem_device = acpi_driver_data(device); if (!acpi_memory_check_device(mem_device)) { @@ -537,6 +548,7 @@ static int __init acpi_memory_device_init(void) return -ENODEV; } + acpi_hotmem_initialized = 1; return 0; } -- cgit v1.2.3 From a31baca58cc16fe0584685f54c6d17494a231c92 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 19 Oct 2006 23:28:33 -0700 Subject: [PATCH] irq updates: make eata_pio compile Signed-off-by: Alan Cox Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/eata_pio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 811d8840707e..2dbb66d2f0a7 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -203,7 +203,7 @@ static irqreturn_t do_eata_pio_int_handler(int irq, void *dev_id) irqreturn_t ret; spin_lock_irqsave(dev->host_lock, flags); - ret = eata_pio_int_handler(irq, dev_id, regs); + ret = eata_pio_int_handler(irq, dev_id); spin_unlock_irqrestore(dev->host_lock, flags); return ret; } -- cgit v1.2.3 From fca4edb48b693d9df7de4c42d91b4158d8b7e347 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Thu, 19 Oct 2006 23:29:06 -0700 Subject: [PATCH] drivers/isdn: ioremap balanced with iounmap ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. Signed-off-by: Amol Lad Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hisax/diva.c | 26 ++++++++++++++++++++++++-- drivers/isdn/hysdn/boardergo.c | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c index 7e95f04f13da..3dacfff93f5f 100644 --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -716,8 +716,10 @@ release_io_diva(struct IsdnCardState *cs) *cfg = 0; /* disable INT0/1 */ *cfg = 2; /* reset pending INT0 */ - iounmap((void *)cs->hw.diva.cfg_reg); - iounmap((void *)cs->hw.diva.pci_cfg); + if (cs->hw.diva.cfg_reg) + iounmap((void *)cs->hw.diva.cfg_reg); + if (cs->hw.diva.pci_cfg) + iounmap((void *)cs->hw.diva.pci_cfg); return; } else if (cs->subtyp != DIVA_IPAC_ISA) { del_timer(&cs->hw.diva.tl); @@ -733,6 +735,23 @@ release_io_diva(struct IsdnCardState *cs) } } +static void +iounmap_diva(struct IsdnCardState *cs) +{ + if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_IPACX_PCI)) { + if (cs->hw.diva.cfg_reg) { + iounmap((void *)cs->hw.diva.cfg_reg); + cs->hw.diva.cfg_reg = 0; + } + if (cs->hw.diva.pci_cfg) { + iounmap((void *)cs->hw.diva.pci_cfg); + cs->hw.diva.pci_cfg = 0; + } + } + + return; +} + static void reset_diva(struct IsdnCardState *cs) { @@ -1069,11 +1088,13 @@ setup_diva(struct IsdnCard *card) if (!cs->irq) { printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); + iounmap_diva(cs); return(0); } if (!cs->hw.diva.cfg_reg) { printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); + iounmap_diva(cs); return(0); } cs->irq_flags |= IRQF_SHARED; @@ -1123,6 +1144,7 @@ ready: CardType[card->typ], cs->hw.diva.cfg_reg, cs->hw.diva.cfg_reg + bytecnt); + iounmap_diva(cs); return (0); } } diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c index 8bbe33ae06db..82e42a80dc4b 100644 --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -403,7 +403,7 @@ ergo_releasehardware(hysdn_card * card) free_irq(card->irq, card); /* release interrupt */ release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */ release_region(card->iobase + PCI9050_USER_IO, 1); - vfree(card->dpram); + iounmap(card->dpram); card->dpram = NULL; /* release shared mem */ } /* ergo_releasehardware */ -- cgit v1.2.3 From 1cd441f99819abdd2d919ff13e8c75af58a0fd9c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 19 Oct 2006 23:29:09 -0700 Subject: [PATCH] ipmi: fix return codes in failure case These returns should be negative, like the others in this function. Signed-off-by: Dave Jones Acked-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 24825bdca8f4..e5cfb1fa47d1 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1789,7 +1789,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) - return ENOMEM; + return -ENOMEM; info->addr_source = "PCI"; @@ -1810,7 +1810,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, kfree(info); printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", pci_name(pdev), class_type); - return ENOMEM; + return -ENOMEM; } rv = pci_enable_device(pdev); -- cgit v1.2.3 From b95936cb9267e4c90a0b92361609ef5fd85a0a5f Mon Sep 17 00:00:00 2001 From: Doug Warzecha Date: Thu, 19 Oct 2006 23:29:09 -0700 Subject: [PATCH] firmware/dcdbas: add size check in smi_data_write Add a size check in smi_data_write to prevent possible wrapping problems with large pos values when calling smi_data_buf_realloc on 32-bit. Signed-off-by: Doug Warzecha Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dcdbas.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/dcdbas.c b/drivers/firmware/dcdbas.c index 8bcb58cd4ac0..1865b56fb141 100644 --- a/drivers/firmware/dcdbas.c +++ b/drivers/firmware/dcdbas.c @@ -8,7 +8,7 @@ * * See Documentation/dcdbas.txt for more information. * - * Copyright (C) 1995-2005 Dell Inc. + * Copyright (C) 1995-2006 Dell Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License v2.0 as published by @@ -40,7 +40,7 @@ #include "dcdbas.h" #define DRIVER_NAME "dcdbas" -#define DRIVER_VERSION "5.6.0-2" +#define DRIVER_VERSION "5.6.0-3.2" #define DRIVER_DESCRIPTION "Dell Systems Management Base Driver" static struct platform_device *dcdbas_pdev; @@ -175,6 +175,9 @@ static ssize_t smi_data_write(struct kobject *kobj, char *buf, loff_t pos, { ssize_t ret; + if ((pos + count) > MAX_SMI_DATA_BUF_SIZE) + return -EINVAL; + mutex_lock(&smi_data_lock); ret = smi_data_buf_realloc(pos + count); -- cgit v1.2.3 From b2ef7858db6394b758818358a43c7dd5f232bbcc Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 20 Oct 2006 10:40:48 -0700 Subject: Revert "[mv643xx] Add pci device table for auto module loading." This reverts commit 4596c75c23dde2623cbeec69357d5eb13d28387e as requested by Olaf Hering. It causes compile errors, and says Olaf: "This change is also wrong, the autoloading works perfect with 2.6.18, no need to add random PCI ids. See commit a0245f7ad5214cb00131d7cd176446e067c913dc, platform devices have now a modalias entry in sysfs. The network card is not a PCI device." Signed-off-by: Linus Torvalds --- drivers/net/mv643xx_eth.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a4f861bf32d6..9997081c6dae 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -1557,12 +1557,6 @@ static void __exit mv643xx_cleanup_module(void) module_init(mv643xx_init_module); module_exit(mv643xx_cleanup_module); -static struct pci_device_id pci_marvell_mv64360[] = { - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360) }, - {} -}; -MODULE_DEVICE_TABLE(pci, pci_marvell_mv64360); - MODULE_LICENSE("GPL"); MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani" " and Dale Farnsworth"); -- cgit v1.2.3 From e17e31e388b2e49ff1c9a2bdb39d7aeb2975c19a Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Fri, 20 Oct 2006 09:23:05 +0200 Subject: [PATCH] Fix up rpaphp driver for pci hotplug header move Use grep instead of make during interface changes. Signed-off-by: Olaf Hering Signed-off-by: Linus Torvalds --- drivers/pci/hotplug/rpaphp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 310b6186c0e5..2e7accf0f734 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -28,7 +28,7 @@ #define _PPC64PHP_H #include -#include "pci_hotplug.h" +#include #define DR_INDICATOR 9002 #define DR_ENTITY_SENSE 9003 -- cgit v1.2.3 From c7a3bd177f248d01ee18a01d22048c80e071c331 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Fri, 20 Oct 2006 14:20:17 -0700 Subject: [PATCH] fix PXA2xx UDC compilation error This was apparently missed by the move to the generic IRQ code. Signed-off-by: Nicolas Pitre Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/gadget/pxa2xx_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index f42c00ef0bca..671c24bc6d75 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -43,11 +43,11 @@ #include #include #include +#include #include #include #include -#include #include #include #include -- cgit v1.2.3 From a1bae67243512ca30ceda48e3e24e25b543f8ab7 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Sat, 21 Oct 2006 18:37:02 +0200 Subject: [PATCH] i386: Disable nmi watchdog on all ThinkPads Even newer Thinkpads have bugs in SMM code that causes hangs with NMI watchdog. Signed-off-by: Andi Kleen --- arch/i386/kernel/nmi.c | 10 +++++----- drivers/firmware/dmi_scan.c | 20 ++++++++++++++++++++ include/linux/dmi.h | 2 ++ 3 files changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 3e8e3adb0489..eaafe233a5da 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c @@ -219,11 +219,11 @@ static int __init check_nmi_watchdog(void) int cpu; /* Enable NMI watchdog for newer systems. - Actually it should be safe for most systems before 2004 too except - for some IBM systems that corrupt registers when NMI happens - during SMM. Unfortunately we don't have more exact information - on these and use this coarse check. */ - if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004) + Probably safe on most older systems too, but let's be careful. + IBM ThinkPads use INT10 inside SMM and that allows early NMI inside SMM + which hangs the system. Disable watchdog for all thinkpads */ + if (nmi_watchdog == NMI_DEFAULT && dmi_get_year(DMI_BIOS_DATE) >= 2004 && + !dmi_name_in_vendors("ThinkPad")) nmi_watchdog = NMI_LOCAL_APIC; if ((nmi_watchdog == NMI_NONE) || (nmi_watchdog == NMI_DEFAULT)) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index b8b596d5778d..37deee6c0c1c 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -326,6 +326,26 @@ char *dmi_get_system_info(int field) } EXPORT_SYMBOL(dmi_get_system_info); + +/** + * dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information. + * @str: Case sensitive Name + */ +int dmi_name_in_vendors(char *str) +{ + static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR, + DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR, + DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE }; + int i; + for (i = 0; fields[i] != DMI_NONE; i++) { + int f = fields[i]; + if (dmi_ident[f] && strstr(dmi_ident[f], str)) + return 1; + } + return 0; +} +EXPORT_SYMBOL(dmi_name_in_vendors); + /** * dmi_find_device - find onboard device by type/name * @type: device type or %DMI_DEV_TYPE_ANY to match all device types diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 38dc403be70b..904bf3d2d90b 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -69,6 +69,7 @@ extern struct dmi_device * dmi_find_device(int type, const char *name, struct dmi_device *from); extern void dmi_scan_machine(void); extern int dmi_get_year(int field); +extern int dmi_name_in_vendors(char *str); #else @@ -77,6 +78,7 @@ static inline char * dmi_get_system_info(int field) { return NULL; } static inline struct dmi_device * dmi_find_device(int type, const char *name, struct dmi_device *from) { return NULL; } static inline int dmi_get_year(int year) { return 0; } +static inline int dmi_name_in_vendors(char *s) { return 0; } #endif -- cgit v1.2.3 From 718ecac2ed7ae1b3d61388ddbff2938a377b1a11 Mon Sep 17 00:00:00 2001 From: Deepak Saxena Date: Fri, 20 Oct 2006 14:42:04 -0700 Subject: [PATCH] Update smc91x driver with ARM Versatile board info We need to specify a Versatile-specific SMC_IRQ_FLAGS value or the new generic IRQ layer will complain thusly: No IRQF_TRIGGER set_type function for IRQ 25 () Signed-off-by: Deepak Saxena Cc: Jeff Garzik Cc: Russell King Cc: Nicolas Pitre Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/smc91x.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 0c9f1e7dab2e..a8640169fc77 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -416,6 +416,24 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #define SMC_IRQ_FLAGS (0) +#elif defined(CONFIG_ARCH_VERSATILE) + +#define SMC_CAN_USE_8BIT 1 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 1 +#define SMC_NOWAIT 1 + +#define SMC_inb(a, r) readb((a) + (r)) +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inl(a, r) readl((a) + (r)) +#define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) +#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l) + +#define SMC_IRQ_FLAGS (0) + #else #define SMC_CAN_USE_8BIT 1 -- cgit v1.2.3 From 6f0f6d87a2a5fc96fc54e90961d5244d668e5fbb Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 20 Oct 2006 14:43:15 -0700 Subject: [PATCH] WAN/pc300: handle, propagate minor errors - move definition of 'tmc' and 'br' locals closer to usage - handle clock_rate_calc() error - propagate errors back to upper level open routine Signed-off-by: Jeff Garzik Cc: Krzysztof Halasa Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/wan/pc300_drv.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 5823e3bca178..36d1c3ff7078 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -2867,7 +2867,6 @@ static int ch_config(pc300dev_t * d) uclong clktype = chan->conf.phys_settings.clock_type; ucshort encoding = chan->conf.proto_settings.encoding; ucshort parity = chan->conf.proto_settings.parity; - int tmc, br; ucchar md0, md2; /* Reset the channel */ @@ -2940,8 +2939,12 @@ static int ch_config(pc300dev_t * d) case PC300_RSV: case PC300_X21: if (clktype == CLOCK_INT || clktype == CLOCK_TXINT) { + int tmc, br; + /* Calculate the clkrate parameters */ tmc = clock_rate_calc(clkrate, card->hw.clock, &br); + if (tmc < 0) + return -EIO; cpc_writeb(scabase + M_REG(TMCT, ch), tmc); cpc_writeb(scabase + M_REG(TXS, ch), (TXS_DTRXC | TXS_IBRG | br)); @@ -3097,14 +3100,16 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding, return 0; } -static void cpc_opench(pc300dev_t * d) +static int cpc_opench(pc300dev_t * d) { pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; - int ch = chan->channel; + int ch = chan->channel, rc; void __iomem *scabase = card->hw.scabase; - ch_config(d); + rc = ch_config(d); + if (rc) + return rc; rx_config(d); @@ -3113,6 +3118,8 @@ static void cpc_opench(pc300dev_t * d) /* Assert RTS and DTR */ cpc_writeb(scabase + M_REG(CTL, ch), cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR)); + + return 0; } static void cpc_closech(pc300dev_t * d) @@ -3168,9 +3175,16 @@ int cpc_open(struct net_device *dev) } sprintf(ifr.ifr_name, "%s", dev->name); - cpc_opench(d); + result = cpc_opench(d); + if (result) + goto err_out; + netif_start_queue(dev); return 0; + +err_out: + hdlc_close(dev); + return result; } static int cpc_close(struct net_device *dev) -- cgit v1.2.3 From 7347b03d25ad7d7f001373cf64f709457c6af618 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 20 Oct 2006 14:42:14 -0700 Subject: [PATCH] e1000: Reset all functions after a PCI error During the handling of the PCI error recovery sequence, the current e1000 driver erroneously blocks a device reset for any but the first PCI function. It shouldn't -- this is a cut-n-paste error from a different driver (which tolerated only one hardware reset per hardware card). Signed-off-by: Linas Vepstas Cc: Jesse Brandeburg Acked-by: Auke Kok Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index ce0d35fe3947..fa849831d099 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4914,10 +4914,6 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); - /* Perform card reset only on one instance of the card */ - if (PCI_FUNC (pdev->devfn) != 0) - return PCI_ERS_RESULT_RECOVERED; - e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); -- cgit v1.2.3 From 470ea7eba4aaa517533f9b02ac9a104e77264548 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 20 Oct 2006 17:06:11 -0700 Subject: [PATCH] sky2: 88E803X transmit lockup The reason sky2 driver was locking up on transmit on the Yukon-FE chipset is that it was misconfiguring the internal RAM buffer so the transmitter and receiver were sharing the same space. The code assumed there was 16K of RAM on Yukon-FE (taken from vendor driver sk98lin which is even more f*cked up on this). Then it assigned based on that. The giveaway was that the registers would only hold 9bits so both RX/TX had 0..1ff for space. It is a wonder it worked at all! This patch addresses this, and fixes an easily reproducible hang on Transmit. Only the Yukon-FE chip is Marvell 88E803X (10/100 only) are affected. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 67ecd66f26d6..95efdb5bbbe1 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -699,16 +699,10 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) } -/* Assign Ram Buffer allocation. - * start and end are in units of 4k bytes - * ram registers are in units of 64bit words - */ -static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk) +/* Assign Ram Buffer allocation in units of 64bit (8 bytes) */ +static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 end) { - u32 start, end; - - start = startk * 4096/8; - end = (endk * 4096/8) - 1; + pr_debug(PFX "q %d %#x %#x\n", q, start, end); sky2_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); sky2_write32(hw, RB_ADDR(q, RB_START), start); @@ -717,7 +711,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u8 startk, u8 endk) sky2_write32(hw, RB_ADDR(q, RB_RP), start); if (q == Q_R1 || q == Q_R2) { - u32 space = (endk - startk) * 4096/8; + u32 space = end - start + 1; u32 tp = space - space/4; /* On receive queue's set the thresholds @@ -1199,19 +1193,16 @@ static int sky2_up(struct net_device *dev) sky2_mac_init(hw, port); - /* Determine available ram buffer space (in 4K blocks). - * Note: not sure about the FE setting below yet - */ - if (hw->chip_id == CHIP_ID_YUKON_FE) - ramsize = 4; - else - ramsize = sky2_read8(hw, B2_E_0); + /* Determine available ram buffer space in qwords. */ + ramsize = sky2_read8(hw, B2_E_0) * 4096/8; - /* Give transmitter one third (rounded up) */ - rxspace = ramsize - (ramsize + 2) / 3; + if (ramsize > 6*1024/8) + rxspace = ramsize - (ramsize + 2) / 3; + else + rxspace = ramsize / 2; - sky2_ramset(hw, rxqaddr[port], 0, rxspace); - sky2_ramset(hw, txqaddr[port], rxspace, ramsize); + sky2_ramset(hw, rxqaddr[port], 0, rxspace-1); + sky2_ramset(hw, txqaddr[port], rxspace, ramsize-1); /* Make sure SyncQ is disabled */ sky2_write8(hw, RB_ADDR(port == 0 ? Q_XS1 : Q_XS2, RB_CTRL), -- cgit v1.2.3 From 18a8e8649d2687283da51fbcf8218372dc5a8f6f Mon Sep 17 00:00:00 2001 From: Li Yang Date: Thu, 19 Oct 2006 21:07:34 -0500 Subject: [PATCH] ucc_geth: changes to ucc_geth driver as a result of qe_lib changes and bugfixes changes due to qe_lib changes include: o removed inclusion of platform header file o removed platform_device code, replaced with of_device o removed typedefs o uint -> u32 conversions o removed following defines: QE_SIZEOF_BD, BD_BUFFER_ARG, BD_BUFFER_CLEAR, BD_BUFFER, BD_STATUS_AND_LENGTH_SET, BD_STATUS_AND_LENGTH, and BD_BUFFER_SET because they hid sizeof/in_be32/out_be32 operations from the reader. o removed irrelevant comments, added others to resemble removed BD_ defines o const'd and uncasted all get_property() assignments bugfixes, courtesy of Scott Wood, include: - Read phy_address as a u32, not u8. - Match on type == "network" as well as compatible == "ucc_geth", as device_is_compatible() will only compare up to the length of the test string, allowing "ucc_geth_phy" to match as well. - fixes the MAC setting code in ucc_geth.c. The old code was overwriting and dereferencing random stack contents. Signed-off-by: Li Yang Signed-off-by: Kim Phillips Signed-off-by: Scott Wood Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 2 +- drivers/net/ucc_geth.c | 633 ++++++++++++++++++++++++--------------------- drivers/net/ucc_geth.h | 248 +++++++++--------- drivers/net/ucc_geth_phy.c | 26 +- drivers/net/ucc_geth_phy.h | 2 +- 5 files changed, 475 insertions(+), 436 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ab92cc794c64..e2ed24918a58 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2288,7 +2288,7 @@ config UGETH_TX_ON_DEMOND config UGETH_HAS_GIGA bool - depends on UCC_GETH && MPC836x + depends on UCC_GETH && PPC_MPC836x config MV643XX_ETH tristate "MV-643XX Ethernet support" diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 12cd7b561f35..b37888011067 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2,14 +2,11 @@ * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved. * * Author: Shlomi Gridish + * Li Yang * * Description: * QE UCC Gigabit Ethernet Driver * - * Changelog: - * Jul 6, 2006 Li Yang - * - Rearrange code and style fixes - * * 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 @@ -31,9 +28,9 @@ #include #include #include -#include #include +#include #include #include #include @@ -70,7 +67,7 @@ static DEFINE_SPINLOCK(ugeth_lock); -static ucc_geth_info_t ugeth_primary_info = { +static struct ucc_geth_info ugeth_primary_info = { .uf_info = { .bd_mem_part = MEM_PART_SYSTEM, .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES, @@ -163,7 +160,7 @@ static ucc_geth_info_t ugeth_primary_info = { .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, }; -static ucc_geth_info_t ugeth_info[8]; +static struct ucc_geth_info ugeth_info[8]; #ifdef DEBUG static void mem_disp(u8 *addr, int size) @@ -219,8 +216,8 @@ static struct list_head *dequeue(struct list_head *lh) } } -static int get_interface_details(enet_interface_e enet_interface, - enet_speed_e *speed, +static int get_interface_details(enum enet_interface enet_interface, + enum enet_speed *speed, int *r10m, int *rmm, int *rpm, @@ -283,7 +280,7 @@ static int get_interface_details(enet_interface_e enet_interface, return 0; } -static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd) +static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth, u8 *bd) { struct sk_buff *skb = NULL; @@ -303,21 +300,19 @@ static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd) skb->dev = ugeth->dev; - BD_BUFFER_SET(bd, + out_be32(&((struct qe_bd *)bd)->buf, dma_map_single(NULL, skb->data, ugeth->ug_info->uf_info.max_rx_buf_length + UCC_GETH_RX_DATA_BUF_ALIGNMENT, DMA_FROM_DEVICE)); - BD_STATUS_AND_LENGTH_SET(bd, - (R_E | R_I | - (BD_STATUS_AND_LENGTH(bd) & R_W))); + out_be32((u32 *)bd, (R_E | R_I | (in_be32((u32 *)bd) & R_W))); return skb; } -static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ) +static int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ) { u8 *bd; u32 bd_status; @@ -328,7 +323,7 @@ static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ) i = 0; do { - bd_status = BD_STATUS_AND_LENGTH(bd); + bd_status = in_be32((u32*)bd); skb = get_new_skb(ugeth, bd); if (!skb) /* If can not allocate data buffer, @@ -338,19 +333,19 @@ static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ) ugeth->rx_skbuff[rxQ][i] = skb; /* advance the BD pointer */ - bd += UCC_GETH_SIZE_OF_BD; + bd += sizeof(struct qe_bd); i++; } while (!(bd_status & R_W)); return 0; } -static int fill_init_enet_entries(ucc_geth_private_t *ugeth, +static int fill_init_enet_entries(struct ucc_geth_private *ugeth, volatile u32 *p_start, u8 num_entries, u32 thread_size, u32 thread_alignment, - qe_risc_allocation_e risc, + enum qe_risc_allocation risc, int skip_page_for_first_entry) { u32 init_enet_offset; @@ -383,10 +378,10 @@ static int fill_init_enet_entries(ucc_geth_private_t *ugeth, return 0; } -static int return_init_enet_entries(ucc_geth_private_t *ugeth, +static int return_init_enet_entries(struct ucc_geth_private *ugeth, volatile u32 *p_start, u8 num_entries, - qe_risc_allocation_e risc, + enum qe_risc_allocation risc, int skip_page_for_first_entry) { u32 init_enet_offset; @@ -416,11 +411,11 @@ static int return_init_enet_entries(ucc_geth_private_t *ugeth, } #ifdef DEBUG -static int dump_init_enet_entries(ucc_geth_private_t *ugeth, +static int dump_init_enet_entries(struct ucc_geth_private *ugeth, volatile u32 *p_start, u8 num_entries, u32 thread_size, - qe_risc_allocation_e risc, + enum qe_risc_allocation risc, int skip_page_for_first_entry) { u32 init_enet_offset; @@ -456,14 +451,14 @@ static int dump_init_enet_entries(ucc_geth_private_t *ugeth, #endif #ifdef CONFIG_UGETH_FILTERING -static enet_addr_container_t *get_enet_addr_container(void) +static struct enet_addr_container *get_enet_addr_container(void) { - enet_addr_container_t *enet_addr_cont; + struct enet_addr_container *enet_addr_cont; /* allocate memory */ - enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL); + enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL); if (!enet_addr_cont) { - ugeth_err("%s: No memory for enet_addr_container_t object.", + ugeth_err("%s: No memory for enet_addr_container object.", __FUNCTION__); return NULL; } @@ -472,45 +467,43 @@ static enet_addr_container_t *get_enet_addr_container(void) } #endif /* CONFIG_UGETH_FILTERING */ -static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont) +static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont) { kfree(enet_addr_cont); } +static int set_mac_addr(__be16 __iomem *reg, u8 *mac) +{ + out_be16(®[0], ((u16)mac[5] << 8) | mac[4]); + out_be16(®[1], ((u16)mac[3] << 8) | mac[2]); + out_be16(®[2], ((u16)mac[1] << 8) | mac[0]); +} + #ifdef CONFIG_UGETH_FILTERING -static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr, u8 paddr_num) +static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth, + u8 *p_enet_addr, u8 paddr_num) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; if (!(paddr_num < NUM_OF_PADDRS)) { - ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); + ugeth_warn("%s: Illegal paddr_num.", __FUNCTION__); return -EINVAL; } p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> addressfiltering; /* Ethernet frames are defined in Little Endian mode, */ /* therefore to insert the address we reverse the bytes. */ - out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, - (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | - (u16) (*p_enet_addr)[4])); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, - (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | - (u16) (*p_enet_addr)[2])); - out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, - (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | - (u16) (*p_enet_addr)[0])); - + set_mac_addr(&p_82xx_addr_filt->paddr[paddr_num].h, p_enet_addr); return 0; } #endif /* CONFIG_UGETH_FILTERING */ -static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num) +static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; if (!(paddr_num < NUM_OF_PADDRS)) { ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__); @@ -518,7 +511,7 @@ static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num) } p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> addressfiltering; /* Writing address ff.ff.ff.ff.ff.ff disables address @@ -530,14 +523,14 @@ static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num) return 0; } -static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) +static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth, + u8 *p_enet_addr) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; u32 cecr_subblock; p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> addressfiltering; cecr_subblock = @@ -546,25 +539,18 @@ static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth, /* Ethernet frames are defined in Little Endian mode, therefor to insert */ /* the address to the hash (Big Endian mode), we reverse the bytes.*/ - out_be16(&p_82xx_addr_filt->taddr.h, - (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) | - (u16) (*p_enet_addr)[4])); - out_be16(&p_82xx_addr_filt->taddr.m, - (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) | - (u16) (*p_enet_addr)[2])); - out_be16(&p_82xx_addr_filt->taddr.l, - (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) | - (u16) (*p_enet_addr)[0])); + + set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr); qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); + QE_CR_PROTOCOL_ETHERNET, 0); } #ifdef CONFIG_UGETH_MAGIC_PACKET -static void magic_packet_detection_enable(ucc_geth_private_t *ugeth) +static void magic_packet_detection_enable(struct ucc_geth_private *ugeth) { - ucc_fast_private_t *uccf; - ucc_geth_t *ug_regs; + struct ucc_fast_private *uccf; + struct ucc_geth *ug_regs; u32 maccfg2, uccm; uccf = ugeth->uccf; @@ -581,10 +567,10 @@ static void magic_packet_detection_enable(ucc_geth_private_t *ugeth) out_be32(&ug_regs->maccfg2, maccfg2); } -static void magic_packet_detection_disable(ucc_geth_private_t *ugeth) +static void magic_packet_detection_disable(struct ucc_geth_private *ugeth) { - ucc_fast_private_t *uccf; - ucc_geth_t *ug_regs; + struct ucc_fast_private *uccf; + struct ucc_geth *ug_regs; u32 maccfg2, uccm; uccf = ugeth->uccf; @@ -602,26 +588,26 @@ static void magic_packet_detection_disable(ucc_geth_private_t *ugeth) } #endif /* MAGIC_PACKET */ -static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2) +static inline int compare_addr(u8 **addr1, u8 **addr2) { return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS); } #ifdef DEBUG -static void get_statistics(ucc_geth_private_t *ugeth, - ucc_geth_tx_firmware_statistics_t * +static void get_statistics(struct ucc_geth_private *ugeth, + struct ucc_geth_tx_firmware_statistics * tx_firmware_statistics, - ucc_geth_rx_firmware_statistics_t * + struct ucc_geth_rx_firmware_statistics * rx_firmware_statistics, - ucc_geth_hardware_statistics_t *hardware_statistics) + struct ucc_geth_hardware_statistics *hardware_statistics) { - ucc_fast_t *uf_regs; - ucc_geth_t *ug_regs; - ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; - ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; + struct ucc_fast *uf_regs; + struct ucc_geth *ug_regs; + struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram; + struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram; ug_regs = ugeth->ug_regs; - uf_regs = (ucc_fast_t *) ug_regs; + uf_regs = (struct ucc_fast *) ug_regs; p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram; p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram; @@ -727,7 +713,7 @@ static void get_statistics(ucc_geth_private_t *ugeth, } } -static void dump_bds(ucc_geth_private_t *ugeth) +static void dump_bds(struct ucc_geth_private *ugeth) { int i; int length; @@ -736,7 +722,7 @@ static void dump_bds(ucc_geth_private_t *ugeth) if (ugeth->p_tx_bd_ring[i]) { length = (ugeth->ug_info->bdRingLenTx[i] * - UCC_GETH_SIZE_OF_BD); + sizeof(struct qe_bd)); ugeth_info("TX BDs[%d]", i); mem_disp(ugeth->p_tx_bd_ring[i], length); } @@ -745,14 +731,14 @@ static void dump_bds(ucc_geth_private_t *ugeth) if (ugeth->p_rx_bd_ring[i]) { length = (ugeth->ug_info->bdRingLenRx[i] * - UCC_GETH_SIZE_OF_BD); + sizeof(struct qe_bd)); ugeth_info("RX BDs[%d]", i); mem_disp(ugeth->p_rx_bd_ring[i], length); } } } -static void dump_regs(ucc_geth_private_t *ugeth) +static void dump_regs(struct ucc_geth_private *ugeth) { int i; @@ -893,7 +879,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) ugeth_info("Base address: 0x%08x", (u32) & ugeth->p_thread_data_tx[i]); mem_disp((u8 *) & ugeth->p_thread_data_tx[i], - sizeof(ucc_geth_thread_data_tx_t)); + sizeof(struct ucc_geth_thread_data_tx)); } } if (ugeth->p_thread_data_rx) { @@ -927,7 +913,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) ugeth_info("Base address: 0x%08x", (u32) & ugeth->p_thread_data_rx[i]); mem_disp((u8 *) & ugeth->p_thread_data_rx[i], - sizeof(ucc_geth_thread_data_rx_t)); + sizeof(struct ucc_geth_thread_data_rx)); } } if (ugeth->p_exf_glbl_param) { @@ -1105,7 +1091,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) ugeth_info("Base address: 0x%08x", (u32) & ugeth->p_send_q_mem_reg->sqqd[i]); mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i], - sizeof(ucc_geth_send_queue_qd_t)); + sizeof(struct ucc_geth_send_queue_qd)); } } if (ugeth->p_scheduler) { @@ -1187,7 +1173,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) qe_muram_addr(in_be32 (&ugeth->p_rx_bd_qs_tbl[i]. bdbaseptr)), - sizeof(ucc_geth_rx_prefetched_bds_t)); + sizeof(struct ucc_geth_rx_prefetched_bds)); } } if (ugeth->p_init_enet_param_shadow) { @@ -1198,7 +1184,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) mem_disp((u8 *) ugeth->p_init_enet_param_shadow, sizeof(*ugeth->p_init_enet_param_shadow)); - size = sizeof(ucc_geth_thread_rx_pram_t); + size = sizeof(struct ucc_geth_thread_rx_pram); if (ugeth->ug_info->rxExtendedFiltering) { size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; @@ -1216,7 +1202,7 @@ static void dump_regs(ucc_geth_private_t *ugeth) &(ugeth->p_init_enet_param_shadow-> txthread[0]), ENET_INIT_PARAM_MAX_ENTRIES_TX, - sizeof(ucc_geth_thread_tx_pram_t), + sizeof(struct ucc_geth_thread_tx_pram), ugeth->ug_info->riscTx, 0); dump_init_enet_entries(ugeth, &(ugeth->p_init_enet_param_shadow-> @@ -1578,12 +1564,12 @@ static int init_min_frame_len(u16 min_frame_length, return 0; } -static int adjust_enet_interface(ucc_geth_private_t *ugeth) +static int adjust_enet_interface(struct ucc_geth_private *ugeth) { - ucc_geth_info_t *ug_info; - ucc_geth_t *ug_regs; - ucc_fast_t *uf_regs; - enet_speed_e speed; + struct ucc_geth_info *ug_info; + struct ucc_geth *ug_regs; + struct ucc_fast *uf_regs; + enum enet_speed speed; int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm = 0, limited_to_full_duplex = 0; u32 upsmr, maccfg2, utbipar, tbiBaseAddress; @@ -1691,8 +1677,8 @@ static int adjust_enet_interface(ucc_geth_private_t *ugeth) */ static void adjust_link(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_geth_t *ug_regs; + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_geth *ug_regs; u32 tempval; struct ugeth_mii_info *mii_info = ugeth->mii_info; @@ -1722,7 +1708,7 @@ static void adjust_link(struct net_device *dev) if (mii_info->speed != ugeth->oldspeed) { switch (mii_info->speed) { case 1000: -#ifdef CONFIG_MPC836x +#ifdef CONFIG_PPC_MPC836x /* FIXME: This code is for 100Mbs BUG fixing, remove this when it is fixed!!! */ if (ugeth->ug_info->enet_interface == @@ -1768,7 +1754,7 @@ remove this when it is fixed!!! */ break; case 100: case 10: -#ifdef CONFIG_MPC836x +#ifdef CONFIG_PPC_MPC836x /* FIXME: This code is for 100Mbs BUG fixing, remove this lines when it will be fixed!!! */ ugeth->ug_info->enet_interface = ENET_100_RGMII; @@ -1827,9 +1813,9 @@ remove this lines when it will be fixed!!! */ */ static int init_phy(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); struct phy_info *curphy; - ucc_mii_mng_t *mii_regs; + struct ucc_mii_mng *mii_regs; struct ugeth_mii_info *mii_info; int err; @@ -1914,17 +1900,17 @@ static int init_phy(struct net_device *dev) } #ifdef CONFIG_UGETH_TX_ON_DEMOND -static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth) +static int ugeth_transmit_on_demand(struct ucc_geth_private *ugeth) { - ucc_fast_transmit_on_demand(ugeth->uccf); + struct ucc_fastransmit_on_demand(ugeth->uccf); return 0; } #endif -static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth) +static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; u32 cecr_subblock; u32 temp; @@ -1940,7 +1926,7 @@ static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth) cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); + QE_CR_PROTOCOL_ETHERNET, 0); /* Wait for command to complete */ do { @@ -1952,9 +1938,9 @@ static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth) return 0; } -static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth) +static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; u32 cecr_subblock; u8 temp; @@ -1973,7 +1959,7 @@ static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth) ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info. ucc_num); qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock, - (u8) QE_CR_PROTOCOL_ETHERNET, 0); + QE_CR_PROTOCOL_ETHERNET, 0); temp = ugeth->p_rx_glbl_pram->rxgstpack; } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX)); @@ -1983,41 +1969,40 @@ static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth) return 0; } -static int ugeth_restart_tx(ucc_geth_private_t *ugeth) +static int ugeth_restart_tx(struct ucc_geth_private *ugeth) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; u32 cecr_subblock; uccf = ugeth->uccf; cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, - 0); + qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); uccf->stopped_tx = 0; return 0; } -static int ugeth_restart_rx(ucc_geth_private_t *ugeth) +static int ugeth_restart_rx(struct ucc_geth_private *ugeth) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; u32 cecr_subblock; uccf = ugeth->uccf; cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, + qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0); uccf->stopped_rx = 0; return 0; } -static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode) +static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; int enabled_tx, enabled_rx; uccf = ugeth->uccf; @@ -2044,9 +2029,9 @@ static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode) } -static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode) +static int ugeth_disable(struct ucc_geth_private * ugeth, enum comm_dir mode) { - ucc_fast_private_t *uccf; + struct ucc_fast_private *uccf; uccf = ugeth->uccf; @@ -2069,7 +2054,7 @@ static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode) return 0; } -static void ugeth_dump_regs(ucc_geth_private_t *ugeth) +static void ugeth_dump_regs(struct ucc_geth_private *ugeth) { #ifdef DEBUG ucc_fast_dump_regs(ugeth->uccf); @@ -2079,9 +2064,9 @@ static void ugeth_dump_regs(ucc_geth_private_t *ugeth) } #ifdef CONFIG_UGETH_FILTERING -static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t * +static int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params * p_UccGethTadParams, - qe_fltr_tad_t *qe_fltr_tad) + struct qe_fltr_tad *qe_fltr_tad) { u16 temp; @@ -2119,11 +2104,11 @@ static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t * return 0; } -static enet_addr_container_t - *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) +static struct enet_addr_container_t + *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth, + struct enet_addr *p_enet_addr) { - enet_addr_container_t *enet_addr_cont; + struct enet_addr_container *enet_addr_cont; struct list_head *p_lh; u16 i, num; int32_t j; @@ -2144,7 +2129,7 @@ static enet_addr_container_t for (i = 0; i < num; i++) { enet_addr_cont = - (enet_addr_container_t *) + (struct enet_addr_container *) ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) { if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j]) @@ -2157,11 +2142,11 @@ static enet_addr_container_t return NULL; } -static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) +static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth, + struct enet_addr *p_enet_addr) { - ucc_geth_enet_address_recognition_location_e location; - enet_addr_container_t *enet_addr_cont; + enum ucc_geth_enet_address_recognition_location location; + struct enet_addr_container *enet_addr_cont; struct list_head *p_lh; u8 i; u32 limit; @@ -2196,18 +2181,17 @@ static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth, enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ ++(*p_counter); - hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); - + hw_add_addr_in_hash(ugeth, enet_addr_cont->address); return 0; } -static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr) +static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth, + struct enet_addr *p_enet_addr) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - enet_addr_container_t *enet_addr_cont; - ucc_fast_private_t *uccf; - comm_dir_e comm_dir; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; + struct enet_addr_container *enet_addr_cont; + struct ucc_fast_private *uccf; + enum comm_dir comm_dir; u16 i, num; struct list_head *p_lh; u32 *addr_h, *addr_l; @@ -2216,7 +2200,7 @@ static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, uccf = ugeth->uccf; p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> addressfiltering; if (! @@ -2256,9 +2240,9 @@ static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, num = --(*p_counter); for (i = 0; i < num; i++) { enet_addr_cont = - (enet_addr_container_t *) + (struct enet_addr_container *) ENET_ADDR_CONT_ENTRY(dequeue(p_lh)); - hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address)); + hw_add_addr_in_hash(ugeth, enet_addr_cont->address); enqueue(p_lh, &enet_addr_cont->node); /* Put it back */ } @@ -2269,14 +2253,14 @@ static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth, } #endif /* CONFIG_UGETH_FILTERING */ -static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t * +static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private * ugeth, - enet_addr_type_e + enum enet_addr_type enet_addr_type) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - ucc_fast_private_t *uccf; - comm_dir_e comm_dir; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; + struct ucc_fast_private *uccf; + enum comm_dir comm_dir; struct list_head *p_lh; u16 i, num; u32 *addr_h, *addr_l; @@ -2285,7 +2269,7 @@ static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t * uccf = ugeth->uccf; p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram-> addressfiltering; if (enet_addr_type == ENET_ADDR_TYPE_GROUP) { @@ -2331,8 +2315,8 @@ static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t * } #ifdef CONFIG_UGETH_FILTERING -static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth, - enet_addr_t *p_enet_addr, +static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth, + struct enet_addr *p_enet_addr, u8 paddr_num) { int i; @@ -2352,14 +2336,14 @@ static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth, } #endif /* CONFIG_UGETH_FILTERING */ -static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth, +static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num) { ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */ return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */ } -static void ucc_geth_memclean(ucc_geth_private_t *ugeth) +static void ucc_geth_memclean(struct ucc_geth_private *ugeth) { u16 i, j; u8 *bd; @@ -2433,8 +2417,8 @@ static void ucc_geth_memclean(ucc_geth_private_t *ugeth) for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) { if (ugeth->tx_skbuff[i][j]) { dma_unmap_single(NULL, - BD_BUFFER_ARG(bd), - (BD_STATUS_AND_LENGTH(bd) & + ((qe_bd_t *)bd)->buf, + (in_be32((u32 *)bd) & BD_LENGTH_MASK), DMA_TO_DEVICE); dev_kfree_skb_any(ugeth->tx_skbuff[i][j]); @@ -2460,18 +2444,17 @@ static void ucc_geth_memclean(ucc_geth_private_t *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, BD_BUFFER(bd), - ugeth->ug_info-> - uf_info. - max_rx_buf_length + - UCC_GETH_RX_DATA_BUF_ALIGNMENT, - DMA_FROM_DEVICE); - - dev_kfree_skb_any(ugeth-> - rx_skbuff[i][j]); + dma_unmap_single(NULL, + ((struct qe_bd *)bd)->buf, + ugeth->ug_info-> + uf_info.max_rx_buf_length + + UCC_GETH_RX_DATA_BUF_ALIGNMENT, + DMA_FROM_DEVICE); + dev_kfree_skb_any( + ugeth->rx_skbuff[i][j]); ugeth->rx_skbuff[i][j] = NULL; } - bd += UCC_GETH_SIZE_OF_BD; + bd += sizeof(struct qe_bd); } kfree(ugeth->rx_skbuff[i]); @@ -2496,11 +2479,11 @@ static void ucc_geth_memclean(ucc_geth_private_t *ugeth) static void ucc_geth_set_multi(struct net_device *dev) { - ucc_geth_private_t *ugeth; + struct ucc_geth_private *ugeth; struct dev_mc_list *dmi; - ucc_fast_t *uf_regs; - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - enet_addr_t tempaddr; + struct ucc_fast *uf_regs; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; + u8 tempaddr[6]; u8 *mcptr, *tdptr; int i, j; @@ -2517,7 +2500,7 @@ static void ucc_geth_set_multi(struct net_device *dev) uf_regs->upsmr &= ~UPSMR_PRO; p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth-> p_rx_glbl_pram->addressfiltering; if (dev->flags & IFF_ALLMULTI) { @@ -2546,23 +2529,22 @@ static void ucc_geth_set_multi(struct net_device *dev) * copy bytes MSB first from dmi_addr. */ mcptr = (u8 *) dmi->dmi_addr + 5; - tdptr = (u8 *) & tempaddr; + tdptr = (u8 *) tempaddr; for (j = 0; j < 6; j++) *tdptr++ = *mcptr--; /* Ask CPM to run CRC and set bit in * filter mask. */ - hw_add_addr_in_hash(ugeth, &tempaddr); - + hw_add_addr_in_hash(ugeth, tempaddr); } } } } -static void ucc_geth_stop(ucc_geth_private_t *ugeth) +static void ucc_geth_stop(struct ucc_geth_private *ugeth) { - ucc_geth_t *ug_regs = ugeth->ug_regs; + struct ucc_geth *ug_regs = ugeth->ug_regs; u32 tempval; ugeth_vdbg("%s: IN", __FUNCTION__); @@ -2605,15 +2587,15 @@ static void ucc_geth_stop(ucc_geth_private_t *ugeth) ucc_geth_memclean(ugeth); } -static int ucc_geth_startup(ucc_geth_private_t *ugeth) +static int ucc_geth_startup(struct ucc_geth_private *ugeth) { - ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt; - ucc_geth_init_pram_t *p_init_enet_pram; - ucc_fast_private_t *uccf; - ucc_geth_info_t *ug_info; - ucc_fast_info_t *uf_info; - ucc_fast_t *uf_regs; - ucc_geth_t *ug_regs; + struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt; + struct ucc_geth_init_pram *p_init_enet_pram; + struct ucc_fast_private *uccf; + struct ucc_geth_info *ug_info; + struct ucc_fast_info *uf_info; + struct ucc_fast *uf_regs; + struct ucc_geth *ug_regs; int ret_val = -EINVAL; u32 remoder = UCC_GETH_REMODER_INIT; u32 init_enet_pram_offset, cecr_subblock, command, maccfg1; @@ -2788,7 +2770,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP); uf_regs = uccf->uf_regs; - ug_regs = (ucc_geth_t *) (uccf->uf_regs); + ug_regs = (struct ucc_geth *) (uccf->uf_regs); ugeth->ug_regs = ug_regs; init_default_reg_vals(&uf_regs->upsmr, @@ -2869,10 +2851,10 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Allocate in multiple of UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT, according to spec */ - length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) + length = ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; - if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) % + if ((ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)) % UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT) length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT; if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { @@ -2904,13 +2886,13 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } /* Zero unused end of bd ring, according to spec */ memset(ugeth->p_tx_bd_ring[j] + - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0, - length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD); + ug_info->bdRingLenTx[j] * sizeof(struct qe_bd), 0, + length - ug_info->bdRingLenTx[j] * sizeof(struct qe_bd)); } /* Allocate Rx bds */ for (j = 0; j < ug_info->numQueuesRx; j++) { - length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD; + length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd); if (uf_info->bd_mem_part == MEM_PART_SYSTEM) { u32 align = 4; if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4) @@ -2960,12 +2942,15 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0; bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j]; for (i = 0; i < ug_info->bdRingLenTx[j]; i++) { - BD_BUFFER_CLEAR(bd); - BD_STATUS_AND_LENGTH_SET(bd, 0); - bd += UCC_GETH_SIZE_OF_BD; + /* clear bd buffer */ + out_be32(&((struct qe_bd *)bd)->buf, 0); + /* set bd status and length */ + out_be32((u32 *)bd, 0); + bd += sizeof(struct qe_bd); } - bd -= UCC_GETH_SIZE_OF_BD; - BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */ + bd -= sizeof(struct qe_bd); + /* set bd status and length */ + out_be32((u32 *)bd, T_W); /* for last BD set Wrap bit */ } /* Init Rx bds */ @@ -2989,12 +2974,15 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) ugeth->skb_currx[j] = 0; bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j]; for (i = 0; i < ug_info->bdRingLenRx[j]; i++) { - BD_STATUS_AND_LENGTH_SET(bd, R_I); - BD_BUFFER_CLEAR(bd); - bd += UCC_GETH_SIZE_OF_BD; + /* set bd status and length */ + out_be32((u32 *)bd, R_I); + /* clear bd buffer */ + out_be32(&((struct qe_bd *)bd)->buf, 0); + bd += sizeof(struct qe_bd); } - bd -= UCC_GETH_SIZE_OF_BD; - BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */ + bd -= sizeof(struct qe_bd); + /* set bd status and length */ + out_be32((u32 *)bd, R_W); /* for last BD set Wrap bit */ } /* @@ -3003,7 +2991,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Tx global PRAM */ /* Allocate global tx parameter RAM page */ ugeth->tx_glbl_pram_offset = - qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t), + qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram), UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT); if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) { ugeth_err @@ -3013,10 +3001,10 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) return -ENOMEM; } ugeth->p_tx_glbl_pram = - (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_tx_global_pram *) qe_muram_addr(ugeth-> tx_glbl_pram_offset); /* Zero out p_tx_glbl_pram */ - memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t)); + memset(ugeth->p_tx_glbl_pram, 0, sizeof(struct ucc_geth_tx_global_pram)); /* Fill global PRAM */ @@ -3024,7 +3012,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Size varies with number of Tx threads */ ugeth->thread_dat_tx_offset = qe_muram_alloc(numThreadsTxNumerical * - sizeof(ucc_geth_thread_data_tx_t) + + sizeof(struct ucc_geth_thread_data_tx) + 32 * (numThreadsTxNumerical == 1), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) { @@ -3036,7 +3024,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_thread_data_tx = - (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_thread_data_tx *) qe_muram_addr(ugeth-> thread_dat_tx_offset); out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset); @@ -3053,7 +3041,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Size varies with number of Tx queues */ ugeth->send_q_mem_reg_offset = qe_muram_alloc(ug_info->numQueuesTx * - sizeof(ucc_geth_send_queue_qd_t), + sizeof(struct ucc_geth_send_queue_qd), UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT); if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) { ugeth_err @@ -3064,7 +3052,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_send_q_mem_reg = - (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_send_queue_mem_region *) qe_muram_addr(ugeth-> send_q_mem_reg_offset); out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset); @@ -3073,7 +3061,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) for (i = 0; i < ug_info->numQueuesTx; i++) { endOfRing = ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] - - 1) * UCC_GETH_SIZE_OF_BD; + 1) * sizeof(struct qe_bd); if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) { out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base, (u32) virt_to_phys(ugeth->p_tx_bd_ring[i])); @@ -3096,7 +3084,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) if (ug_info->numQueuesTx > 1) { /* scheduler exists only if more than 1 tx queue */ ugeth->scheduler_offset = - qe_muram_alloc(sizeof(ucc_geth_scheduler_t), + qe_muram_alloc(sizeof(struct ucc_geth_scheduler), UCC_GETH_SCHEDULER_ALIGNMENT); if (IS_MURAM_ERR(ugeth->scheduler_offset)) { ugeth_err @@ -3107,12 +3095,12 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_scheduler = - (ucc_geth_scheduler_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_scheduler *) qe_muram_addr(ugeth-> scheduler_offset); out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer, ugeth->scheduler_offset); /* Zero out p_scheduler */ - memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t)); + memset(ugeth->p_scheduler, 0, sizeof(struct ucc_geth_scheduler)); /* Set values in scheduler */ out_be32(&ugeth->p_scheduler->mblinterval, @@ -3144,7 +3132,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) { ugeth->tx_fw_statistics_pram_offset = qe_muram_alloc(sizeof - (ucc_geth_tx_firmware_statistics_pram_t), + (struct ucc_geth_tx_firmware_statistics_pram), UCC_GETH_TX_STATISTICS_ALIGNMENT); if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) { ugeth_err @@ -3154,11 +3142,11 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) return -ENOMEM; } ugeth->p_tx_fw_statistics_pram = - (ucc_geth_tx_firmware_statistics_pram_t *) + (struct ucc_geth_tx_firmware_statistics_pram *) qe_muram_addr(ugeth->tx_fw_statistics_pram_offset); /* Zero out p_tx_fw_statistics_pram */ memset(ugeth->p_tx_fw_statistics_pram, - 0, sizeof(ucc_geth_tx_firmware_statistics_pram_t)); + 0, sizeof(struct ucc_geth_tx_firmware_statistics_pram)); } /* temoder */ @@ -3183,7 +3171,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Rx global PRAM */ /* Allocate global rx parameter RAM page */ ugeth->rx_glbl_pram_offset = - qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t), + qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram), UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT); if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) { ugeth_err @@ -3193,10 +3181,10 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) return -ENOMEM; } ugeth->p_rx_glbl_pram = - (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_rx_global_pram *) qe_muram_addr(ugeth-> rx_glbl_pram_offset); /* Zero out p_rx_glbl_pram */ - memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t)); + memset(ugeth->p_rx_glbl_pram, 0, sizeof(struct ucc_geth_rx_global_pram)); /* Fill global PRAM */ @@ -3204,7 +3192,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Size varies with number of Rx threads */ ugeth->thread_dat_rx_offset = qe_muram_alloc(numThreadsRxNumerical * - sizeof(ucc_geth_thread_data_rx_t), + sizeof(struct ucc_geth_thread_data_rx), UCC_GETH_THREAD_DATA_ALIGNMENT); if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) { ugeth_err @@ -3215,7 +3203,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_thread_data_rx = - (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_thread_data_rx *) qe_muram_addr(ugeth-> thread_dat_rx_offset); out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset); @@ -3227,7 +3215,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) { ugeth->rx_fw_statistics_pram_offset = qe_muram_alloc(sizeof - (ucc_geth_rx_firmware_statistics_pram_t), + (struct ucc_geth_rx_firmware_statistics_pram), UCC_GETH_RX_STATISTICS_ALIGNMENT); if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) { ugeth_err @@ -3237,11 +3225,11 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) return -ENOMEM; } ugeth->p_rx_fw_statistics_pram = - (ucc_geth_rx_firmware_statistics_pram_t *) + (struct ucc_geth_rx_firmware_statistics_pram *) qe_muram_addr(ugeth->rx_fw_statistics_pram_offset); /* Zero out p_rx_fw_statistics_pram */ memset(ugeth->p_rx_fw_statistics_pram, 0, - sizeof(ucc_geth_rx_firmware_statistics_pram_t)); + sizeof(struct ucc_geth_rx_firmware_statistics_pram)); } /* intCoalescingPtr */ @@ -3249,7 +3237,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Size varies with number of Rx queues */ ugeth->rx_irq_coalescing_tbl_offset = qe_muram_alloc(ug_info->numQueuesRx * - sizeof(ucc_geth_rx_interrupt_coalescing_entry_t), + sizeof(struct ucc_geth_rx_interrupt_coalescing_entry), UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT); if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) { ugeth_err @@ -3260,7 +3248,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_rx_irq_coalescing_tbl = - (ucc_geth_rx_interrupt_coalescing_table_t *) + (struct ucc_geth_rx_interrupt_coalescing_table *) qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset); out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr, ugeth->rx_irq_coalescing_tbl_offset); @@ -3300,7 +3288,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) l3qt = 0; for (i = 0; i < 8; i++) l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i)); - out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt); + out_be32(&ugeth->p_rx_glbl_pram->l3qt[j/8], l3qt); } /* vlantype */ @@ -3316,8 +3304,8 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Size varies with number of Rx queues */ ugeth->rx_bd_qs_tbl_offset = qe_muram_alloc(ug_info->numQueuesRx * - (sizeof(ucc_geth_rx_bd_queues_entry_t) + - sizeof(ucc_geth_rx_prefetched_bds_t)), + (sizeof(struct ucc_geth_rx_bd_queues_entry) + + sizeof(struct ucc_geth_rx_prefetched_bds)), UCC_GETH_RX_BD_QUEUES_ALIGNMENT); if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) { ugeth_err @@ -3328,14 +3316,14 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_rx_bd_qs_tbl = - (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_rx_bd_queues_entry *) qe_muram_addr(ugeth-> rx_bd_qs_tbl_offset); out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset); /* Zero out p_rx_bd_qs_tbl */ memset(ugeth->p_rx_bd_qs_tbl, 0, - ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) + - sizeof(ucc_geth_rx_prefetched_bds_t))); + ug_info->numQueuesRx * (sizeof(struct ucc_geth_rx_bd_queues_entry) + + sizeof(struct ucc_geth_rx_prefetched_bds))); /* Setup the table */ /* Assume BD rings are already established */ @@ -3406,7 +3394,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Allocate memory for extended filtering Mode Global Parameters */ ugeth->exf_glbl_param_offset = - qe_muram_alloc(sizeof(ucc_geth_exf_global_pram_t), + qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram), UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT); if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) { ugeth_err @@ -3417,7 +3405,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_exf_glbl_param = - (ucc_geth_exf_global_pram_t *) qe_muram_addr(ugeth-> + (struct ucc_geth_exf_global_pram *) qe_muram_addr(ugeth-> exf_glbl_param_offset); out_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam, ugeth->exf_glbl_param_offset); @@ -3439,7 +3427,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) INIT_LIST_HEAD(&ugeth->ind_hash_q); } p_82xx_addr_filt = - (ucc_geth_82xx_address_filtering_pram_t *) ugeth-> + (struct ucc_geth_82xx_address_filtering_pram *) ugeth-> p_rx_glbl_pram->addressfiltering; ugeth_82xx_filtering_clear_all_addr_in_hash(ugeth, @@ -3462,7 +3450,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) * allocated resources can be released when the channel is freed. */ if (!(ugeth->p_init_enet_param_shadow = - (ucc_geth_init_pram_t *) kmalloc(sizeof(ucc_geth_init_pram_t), + (struct ucc_geth_init_pram *) kmalloc(sizeof(struct ucc_geth_init_pram), GFP_KERNEL))) { ugeth_err ("%s: Can not allocate memory for" @@ -3472,7 +3460,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } /* Zero out *p_init_enet_param_shadow */ memset((char *)ugeth->p_init_enet_param_shadow, - 0, sizeof(ucc_geth_init_pram_t)); + 0, sizeof(struct ucc_geth_init_pram)); /* Fill shadow InitEnet command parameter structure */ @@ -3506,7 +3494,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } ugeth->p_init_enet_param_shadow->largestexternallookupkeysize = ug_info->largestexternallookupkeysize; - size = sizeof(ucc_geth_thread_rx_pram_t); + size = sizeof(struct ucc_geth_thread_rx_pram); if (ug_info->rxExtendedFiltering) { size += THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING; if (ug_info->largestexternallookupkeysize == @@ -3537,7 +3525,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) fill_init_enet_entries(ugeth, &(ugeth->p_init_enet_param_shadow-> txthread[0]), numThreadsTxNumerical, - sizeof(ucc_geth_thread_tx_pram_t), + sizeof(struct ucc_geth_thread_tx_pram), UCC_GETH_THREAD_TX_PRAM_ALIGNMENT, ug_info->riscTx, 0)) != 0) { ugeth_err("%s: Can not fill p_init_enet_param_shadow.", @@ -3557,7 +3545,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) } /* Allocate InitEnet command parameter structure */ - init_enet_pram_offset = qe_muram_alloc(sizeof(ucc_geth_init_pram_t), 4); + init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4); if (IS_MURAM_ERR(init_enet_pram_offset)) { ugeth_err ("%s: Can not allocate DPRAM memory for p_init_enet_pram.", @@ -3566,7 +3554,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) return -ENOMEM; } p_init_enet_pram = - (ucc_geth_init_pram_t *) qe_muram_addr(init_enet_pram_offset); + (struct ucc_geth_init_pram *) qe_muram_addr(init_enet_pram_offset); /* Copy shadow InitEnet command parameter structure into PRAM */ p_init_enet_pram->resinit1 = ugeth->p_init_enet_param_shadow->resinit1; @@ -3591,7 +3579,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* Issue QE command */ cecr_subblock = ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num); - qe_issue_cmd(command, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET, + qe_issue_cmd(command, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, init_enet_pram_offset); /* Free InitEnet command parameter */ @@ -3603,7 +3591,7 @@ static int ucc_geth_startup(ucc_geth_private_t *ugeth) /* returns a net_device_stats structure pointer */ static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); return &(ugeth->stats); } @@ -3614,7 +3602,7 @@ static struct net_device_stats *ucc_geth_get_stats(struct net_device *dev) * starting over will fix the problem. */ static void ucc_geth_timeout(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); ugeth_vdbg("%s: IN", __FUNCTION__); @@ -3634,7 +3622,7 @@ static void ucc_geth_timeout(struct net_device *dev) /* It is pointed to by the dev->hard_start_xmit function pointer */ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); u8 *bd; /* BD pointer */ u32 bd_status; u8 txQ = 0; @@ -3647,7 +3635,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) /* Start from the next BD that should be filled */ bd = ugeth->txBd[txQ]; - bd_status = BD_STATUS_AND_LENGTH(bd); + bd_status = in_be32((u32 *)bd); /* Save the skb pointer so we can free it later */ ugeth->tx_skbuff[txQ][ugeth->skb_curtx[txQ]] = skb; @@ -3657,20 +3645,21 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) 1) & TX_RING_MOD_MASK(ugeth->ug_info->bdRingLenTx[txQ]); /* set up the buffer descriptor */ - BD_BUFFER_SET(bd, + out_be32(&((struct qe_bd *)bd)->buf, dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE)); - //printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); + /* printk(KERN_DEBUG"skb->data is 0x%x\n",skb->data); */ bd_status = (bd_status & T_W) | T_R | T_I | T_L | skb->len; - BD_STATUS_AND_LENGTH_SET(bd, bd_status); + /* set bd status and length */ + out_be32((u32 *)bd, bd_status); dev->trans_start = jiffies; /* Move to next BD in the ring */ if (!(bd_status & T_W)) - ugeth->txBd[txQ] = bd + UCC_GETH_SIZE_OF_BD; + ugeth->txBd[txQ] = bd + sizeof(struct qe_bd); else ugeth->txBd[txQ] = ugeth->p_tx_bd_ring[txQ]; @@ -3695,7 +3684,7 @@ static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev) return 0; } -static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) +static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit) { struct sk_buff *skb; u8 *bd; @@ -3709,11 +3698,11 @@ static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) /* collect received buffers */ bd = ugeth->rxBd[rxQ]; - bd_status = BD_STATUS_AND_LENGTH(bd); + bd_status = in_be32((u32 *)bd); /* while there are received buffers and BD is full (~R_E) */ while (!((bd_status & (R_E)) || (--rx_work_limit < 0))) { - bdBuffer = (u8 *) BD_BUFFER(bd); + bdBuffer = (u8 *) in_be32(&((struct qe_bd *)bd)->buf); length = (u16) ((bd_status & BD_LENGTH_MASK) - 4); skb = ugeth->rx_skbuff[rxQ][ugeth->skb_currx[rxQ]]; @@ -3768,9 +3757,9 @@ static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) if (bd_status & R_W) bd = ugeth->p_rx_bd_ring[rxQ]; else - bd += UCC_GETH_SIZE_OF_BD; + bd += sizeof(struct qe_bd); - bd_status = BD_STATUS_AND_LENGTH(bd); + bd_status = in_be32((u32 *)bd); } ugeth->rxBd[rxQ] = bd; @@ -3781,12 +3770,12 @@ static int ucc_geth_rx(ucc_geth_private_t *ugeth, u8 rxQ, int rx_work_limit) static int ucc_geth_tx(struct net_device *dev, u8 txQ) { /* Start from the next BD that should be filled */ - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); u8 *bd; /* BD pointer */ u32 bd_status; bd = ugeth->confBd[txQ]; - bd_status = BD_STATUS_AND_LENGTH(bd); + bd_status = in_be32((u32 *)bd); /* Normal processing. */ while ((bd_status & T_R) == 0) { @@ -3813,7 +3802,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) /* Advance the confirmation BD pointer */ if (!(bd_status & T_W)) - ugeth->confBd[txQ] += UCC_GETH_SIZE_OF_BD; + ugeth->confBd[txQ] += sizeof(struct qe_bd); else ugeth->confBd[txQ] = ugeth->p_tx_bd_ring[txQ]; } @@ -3823,7 +3812,7 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) #ifdef CONFIG_UGETH_NAPI static int ucc_geth_poll(struct net_device *dev, int *budget) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); int howmany; int rx_work_limit = *budget; u8 rxQ = 0; @@ -3847,9 +3836,9 @@ static int ucc_geth_poll(struct net_device *dev, int *budget) static irqreturn_t ucc_geth_irq_handler(int irq, void *info) { struct net_device *dev = (struct net_device *)info; - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_fast_private_t *uccf; - ucc_geth_info_t *ug_info; + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_fast_private *uccf; + struct ucc_geth_info *ug_info; register u32 ucce = 0; register u32 bit_mask = UCCE_RXBF_SINGLE_MASK; register u32 tx_mask = UCCE_TXBF_SINGLE_MASK; @@ -3912,7 +3901,7 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info) static irqreturn_t phy_interrupt(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); ugeth_vdbg("%s: IN", __FUNCTION__); @@ -3932,8 +3921,8 @@ static irqreturn_t phy_interrupt(int irq, void *dev_id) static void ugeth_phy_change(void *data) { struct net_device *dev = (struct net_device *)data; - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_geth_t *ug_regs; + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_geth *ug_regs; int result = 0; ugeth_vdbg("%s: IN", __FUNCTION__); @@ -3963,7 +3952,7 @@ static void ugeth_phy_change(void *data) static void ugeth_phy_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); schedule_work(&ugeth->tq); @@ -3979,7 +3968,7 @@ static void ugeth_phy_timer(unsigned long data) static void ugeth_phy_startup_timer(unsigned long data) { struct ugeth_mii_info *mii_info = (struct ugeth_mii_info *)data; - ucc_geth_private_t *ugeth = netdev_priv(mii_info->dev); + struct ucc_geth_private *ugeth = netdev_priv(mii_info->dev); static int secondary = UGETH_AN_TIMEOUT; int result; @@ -4034,7 +4023,7 @@ static void ugeth_phy_startup_timer(unsigned long data) /* Returns 0 for success. */ static int ucc_geth_open(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); int err; ugeth_vdbg("%s: IN", __FUNCTION__); @@ -4111,7 +4100,7 @@ static int ucc_geth_open(struct net_device *dev) /* Stops the kernel queue, and halts the controller */ static int ucc_geth_close(struct net_device *dev) { - ucc_geth_private_t *ugeth = netdev_priv(dev); + struct ucc_geth_private *ugeth = netdev_priv(dev); ugeth_vdbg("%s: IN", __FUNCTION__); @@ -4130,30 +4119,53 @@ static int ucc_geth_close(struct net_device *dev) const struct ethtool_ops ucc_geth_ethtool_ops = { }; -static int ucc_geth_probe(struct device *device) +static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *match) { - struct platform_device *pdev = to_platform_device(device); - struct ucc_geth_platform_data *ugeth_pdata; + struct device *device = &ofdev->dev; + struct device_node *np = ofdev->node; struct net_device *dev = NULL; struct ucc_geth_private *ugeth = NULL; struct ucc_geth_info *ug_info; - int err; + struct resource res; + struct device_node *phy; + int err, ucc_num, phy_interface; static int mii_mng_configured = 0; + const phandle *ph; + const unsigned int *prop; ugeth_vdbg("%s: IN", __FUNCTION__); - ugeth_pdata = (struct ucc_geth_platform_data *)pdev->dev.platform_data; + prop = get_property(np, "device-id", NULL); + ucc_num = *prop - 1; + if ((ucc_num < 0) || (ucc_num > 7)) + return -ENODEV; + + ug_info = &ugeth_info[ucc_num]; + ug_info->uf_info.ucc_num = ucc_num; + prop = get_property(np, "rx-clock", NULL); + ug_info->uf_info.rx_clock = *prop; + prop = get_property(np, "tx-clock", NULL); + ug_info->uf_info.tx_clock = *prop; + err = of_address_to_resource(np, 0, &res); + if (err) + return -EINVAL; + + ug_info->uf_info.regs = res.start; + ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); + + ph = get_property(np, "phy-handle", NULL); + phy = of_find_node_by_phandle(*ph); - ug_info = &ugeth_info[pdev->id]; - ug_info->uf_info.ucc_num = pdev->id; - ug_info->uf_info.rx_clock = ugeth_pdata->rx_clock; - ug_info->uf_info.tx_clock = ugeth_pdata->tx_clock; - ug_info->uf_info.regs = ugeth_pdata->phy_reg_addr; - ug_info->uf_info.irq = platform_get_irq(pdev, 0); - ug_info->phy_address = ugeth_pdata->phy_id; - ug_info->enet_interface = ugeth_pdata->phy_interface; - ug_info->board_flags = ugeth_pdata->board_flags; - ug_info->phy_interrupt = ugeth_pdata->phy_interrupt; + if (phy == NULL) + return -ENODEV; + + prop = get_property(phy, "reg", NULL); + ug_info->phy_address = *prop; + prop = get_property(phy, "interface", NULL); + ug_info->enet_interface = *prop; + ug_info->phy_interrupt = irq_of_parse_and_map(phy, 0); + ug_info->board_flags = (ug_info->phy_interrupt == NO_IRQ)? + 0:FSL_UGETH_BRD_HAS_PHY_INTR; printk(KERN_INFO "ucc_geth: UCC%1d at 0x%8x (irq = %d) \n", ug_info->uf_info.ucc_num + 1, ug_info->uf_info.regs, @@ -4161,12 +4173,44 @@ static int ucc_geth_probe(struct device *device) if (ug_info == NULL) { ugeth_err("%s: [%d] Missing additional data!", __FUNCTION__, - pdev->id); + ucc_num); return -ENODEV; } + /* FIXME: Work around for early chip rev. */ + /* There's a bug in initial chip rev(s) in the RGMII ac */ + /* timing. */ + /* The following compensates by writing to the reserved */ + /* QE Port Output Hold Registers (CPOH1?). */ + prop = get_property(phy, "interface", NULL); + phy_interface = *prop; + if ((phy_interface == ENET_1000_RGMII) || + (phy_interface == ENET_100_RGMII) || + (phy_interface == ENET_10_RGMII)) { + struct device_node *soc; + phys_addr_t immrbase = -1; + u32 *tmp_reg; + u32 tmp_val; + + soc = of_find_node_by_type(NULL, "soc"); + if (soc) { + unsigned int size; + const void *prop = get_property(soc, "reg", &size); + immrbase = of_translate_address(soc, prop); + of_node_put(soc); + }; + + tmp_reg = (u32 *) ioremap(immrbase + 0x14A8, 0x4); + tmp_val = in_be32(tmp_reg); + if (ucc_num == 1) + out_be32(tmp_reg, tmp_val | 0x00003000); + else if (ucc_num == 2) + out_be32(tmp_reg, tmp_val | 0x0c000000); + iounmap(tmp_reg); + } + if (!mii_mng_configured) { - ucc_set_qe_mux_mii_mng(ug_info->uf_info.ucc_num); + ucc_set_qe_mux_mii_mng(ucc_num); mii_mng_configured = 1; } @@ -4213,13 +4257,14 @@ static int ucc_geth_probe(struct device *device) ugeth->ug_info = ug_info; ugeth->dev = dev; - memcpy(dev->dev_addr, ugeth_pdata->mac_addr, 6); + memcpy(dev->dev_addr, get_property(np, "mac-address", NULL), 6); return 0; } -static int ucc_geth_remove(struct device *device) +static int ucc_geth_remove(struct of_device* ofdev) { + struct device *device = &ofdev->dev; struct net_device *dev = dev_get_drvdata(device); struct ucc_geth_private *ugeth = netdev_priv(dev); @@ -4230,28 +4275,38 @@ static int ucc_geth_remove(struct device *device) return 0; } -/* Structure for a device driver */ -static struct device_driver ucc_geth_driver = { - .name = DRV_NAME, - .bus = &platform_bus_type, - .probe = ucc_geth_probe, - .remove = ucc_geth_remove, +static struct of_device_id ucc_geth_match[] = { + { + .type = "network", + .compatible = "ucc_geth", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, ucc_geth_match); + +static struct of_platform_driver ucc_geth_driver = { + .name = DRV_NAME, + .match_table = ucc_geth_match, + .probe = ucc_geth_probe, + .remove = ucc_geth_remove, }; static int __init ucc_geth_init(void) { int i; + printk(KERN_INFO "ucc_geth: " DRV_DESC "\n"); for (i = 0; i < 8; i++) memcpy(&(ugeth_info[i]), &ugeth_primary_info, sizeof(ugeth_primary_info)); - return driver_register(&ucc_geth_driver); + return of_register_driver(&ucc_geth_driver); } static void __exit ucc_geth_exit(void) { - driver_unregister(&ucc_geth_driver); + of_unregister_driver(&ucc_geth_driver); } module_init(ucc_geth_init); diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 005965f5dd9b..a66561253593 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -36,24 +36,24 @@ #define ENET_INIT_PARAM_MAX_ENTRIES_RX 9 #define ENET_INIT_PARAM_MAX_ENTRIES_TX 8 -typedef struct ucc_mii_mng { +struct ucc_mii_mng { u32 miimcfg; /* MII management configuration reg */ u32 miimcom; /* MII management command reg */ u32 miimadd; /* MII management address reg */ u32 miimcon; /* MII management control reg */ u32 miimstat; /* MII management status reg */ u32 miimind; /* MII management indication reg */ -} __attribute__ ((packed)) ucc_mii_mng_t; +} __attribute__ ((packed)); -typedef struct ucc_geth { - ucc_fast_t uccf; +struct ucc_geth { + struct ucc_fast uccf; u32 maccfg1; /* mac configuration reg. 1 */ u32 maccfg2; /* mac configuration reg. 2 */ u32 ipgifg; /* interframe gap reg. */ u32 hafdup; /* half-duplex reg. */ u8 res1[0x10]; - ucc_mii_mng_t miimng; /* MII management structure */ + struct ucc_mii_mng miimng; /* MII management structure */ u32 ifctl; /* interface control reg */ u32 ifstat; /* interface statux reg */ u32 macstnaddr1; /* mac station address part 1 reg */ @@ -111,7 +111,7 @@ typedef struct ucc_geth { u32 scar; /* Statistics carry register */ u32 scam; /* Statistics caryy mask register */ u8 res5[0x200 - 0x1c4]; -} __attribute__ ((packed)) ucc_geth_t; +} __attribute__ ((packed)); /* UCC GETH TEMODR Register */ #define TEMODER_TX_RMON_STATISTICS_ENABLE 0x0100 /* enable Tx statistics @@ -508,39 +508,39 @@ typedef struct ucc_geth { /* UCC GETH UDSR (Data Synchronization Register) */ #define UDSR_MAGIC 0x067E -typedef struct ucc_geth_thread_data_tx { +struct ucc_geth_thread_data_tx { u8 res0[104]; -} __attribute__ ((packed)) ucc_geth_thread_data_tx_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_thread_data_rx { +struct ucc_geth_thread_data_rx { u8 res0[40]; -} __attribute__ ((packed)) ucc_geth_thread_data_rx_t; +} __attribute__ ((packed)); /* Send Queue Queue-Descriptor */ -typedef struct ucc_geth_send_queue_qd { +struct ucc_geth_send_queue_qd { u32 bd_ring_base; /* pointer to BD ring base address */ u8 res0[0x8]; u32 last_bd_completed_address;/* initialize to last entry in BD ring */ u8 res1[0x30]; -} __attribute__ ((packed)) ucc_geth_send_queue_qd_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_send_queue_mem_region { - ucc_geth_send_queue_qd_t sqqd[NUM_TX_QUEUES]; -} __attribute__ ((packed)) ucc_geth_send_queue_mem_region_t; +struct ucc_geth_send_queue_mem_region { + struct ucc_geth_send_queue_qd sqqd[NUM_TX_QUEUES]; +} __attribute__ ((packed)); -typedef struct ucc_geth_thread_tx_pram { +struct ucc_geth_thread_tx_pram { u8 res0[64]; -} __attribute__ ((packed)) ucc_geth_thread_tx_pram_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_thread_rx_pram { +struct ucc_geth_thread_rx_pram { u8 res0[128]; -} __attribute__ ((packed)) ucc_geth_thread_rx_pram_t; +} __attribute__ ((packed)); #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING 64 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8 64 #define THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16 96 -typedef struct ucc_geth_scheduler { +struct ucc_geth_scheduler { u16 cpucount0; /* CPU packet counter */ u16 cpucount1; /* CPU packet counter */ u16 cecount0; /* QE packet counter */ @@ -574,9 +574,9 @@ typedef struct ucc_geth_scheduler { /**< weight factor for queues */ u32 minw; /* temporary variable handled by QE */ u8 res1[0x70 - 0x64]; -} __attribute__ ((packed)) ucc_geth_scheduler_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_tx_firmware_statistics_pram { +struct ucc_geth_tx_firmware_statistics_pram { u32 sicoltx; /* single collision */ u32 mulcoltx; /* multiple collision */ u32 latecoltxfr; /* late collision */ @@ -596,9 +596,9 @@ typedef struct ucc_geth_tx_firmware_statistics_pram { and 1518 octets */ u32 txpktsjumbo; /* total packets (including bad) between 1024 and MAXLength octets */ -} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_pram_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_firmware_statistics_pram { +struct ucc_geth_rx_firmware_statistics_pram { u32 frrxfcser; /* frames with crc error */ u32 fraligner; /* frames with alignment error */ u32 inrangelenrxer; /* in range length error */ @@ -630,33 +630,33 @@ typedef struct ucc_geth_rx_firmware_statistics_pram { replaced */ u32 insertvlan; /* total frames that had their VLAN tag inserted */ -} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_pram_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_interrupt_coalescing_entry { +struct ucc_geth_rx_interrupt_coalescing_entry { u32 interruptcoalescingmaxvalue; /* interrupt coalescing max value */ u32 interruptcoalescingcounter; /* interrupt coalescing counter, initialize to interruptcoalescingmaxvalue */ -} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_entry_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_interrupt_coalescing_table { - ucc_geth_rx_interrupt_coalescing_entry_t coalescingentry[NUM_RX_QUEUES]; +struct ucc_geth_rx_interrupt_coalescing_table { + struct ucc_geth_rx_interrupt_coalescing_entry coalescingentry[NUM_RX_QUEUES]; /**< interrupt coalescing entry */ -} __attribute__ ((packed)) ucc_geth_rx_interrupt_coalescing_table_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_prefetched_bds { - qe_bd_t bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ -} __attribute__ ((packed)) ucc_geth_rx_prefetched_bds_t; +struct ucc_geth_rx_prefetched_bds { + struct qe_bd bd[NUM_BDS_IN_PREFETCHED_BDS]; /* prefetched bd */ +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_bd_queues_entry { +struct ucc_geth_rx_bd_queues_entry { u32 bdbaseptr; /* BD base pointer */ u32 bdptr; /* BD pointer */ u32 externalbdbaseptr; /* external BD base pointer */ u32 externalbdptr; /* external BD pointer */ -} __attribute__ ((packed)) ucc_geth_rx_bd_queues_entry_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_tx_global_pram { +struct ucc_geth_tx_global_pram { u16 temoder; u8 res0[0x38 - 0x02]; u32 sqptr; /* a base pointer to send queue memory region */ @@ -670,15 +670,15 @@ typedef struct ucc_geth_tx_global_pram { u32 tqptr; /* a base pointer to the Tx Queues Memory Region */ u8 res2[0x80 - 0x74]; -} __attribute__ ((packed)) ucc_geth_tx_global_pram_t; +} __attribute__ ((packed)); /* structure representing Extended Filtering Global Parameters in PRAM */ -typedef struct ucc_geth_exf_global_pram { +struct ucc_geth_exf_global_pram { u32 l2pcdptr; /* individual address filter, high */ u8 res0[0x10 - 0x04]; -} __attribute__ ((packed)) ucc_geth_exf_global_pram_t; +} __attribute__ ((packed)); -typedef struct ucc_geth_rx_global_pram { +struct ucc_geth_rx_global_pram { u32 remoder; /* ethernet mode reg. */ u32 rqptr; /* base pointer to the Rx Queues Memory Region*/ u32 res0[0x1]; @@ -710,12 +710,12 @@ typedef struct ucc_geth_rx_global_pram { u32 exfGlobalParam; /* base address for extended filtering global parameters */ u8 res6[0x100 - 0xC4]; /* Initialize to zero */ -} __attribute__ ((packed)) ucc_geth_rx_global_pram_t; +} __attribute__ ((packed)); #define GRACEFUL_STOP_ACKNOWLEDGE_RX 0x01 /* structure representing InitEnet command */ -typedef struct ucc_geth_init_pram { +struct ucc_geth_init_pram { u8 resinit1; u8 resinit2; u8 resinit3; @@ -729,7 +729,7 @@ typedef struct ucc_geth_init_pram { u32 txglobal; /* tx global */ u32 txthread[ENET_INIT_PARAM_MAX_ENTRIES_TX]; /* tx threads */ u8 res3[0x1]; -} __attribute__ ((packed)) ucc_geth_init_pram_t; +} __attribute__ ((packed)); #define ENET_INIT_PARAM_RGF_SHIFT (32 - 4) #define ENET_INIT_PARAM_TGF_SHIFT (32 - 8) @@ -746,27 +746,27 @@ typedef struct ucc_geth_init_pram { #define ENET_INIT_PARAM_MAGIC_RES_INIT5 0x0400 /* structure representing 82xx Address Filtering Enet Address in PRAM */ -typedef struct ucc_geth_82xx_enet_address { +struct ucc_geth_82xx_enet_address { u8 res1[0x2]; u16 h; /* address (MSB) */ u16 m; /* address */ u16 l; /* address (LSB) */ -} __attribute__ ((packed)) ucc_geth_82xx_enet_address_t; +} __attribute__ ((packed)); /* structure representing 82xx Address Filtering PRAM */ -typedef struct ucc_geth_82xx_address_filtering_pram { +struct ucc_geth_82xx_address_filtering_pram { u32 iaddr_h; /* individual address filter, high */ u32 iaddr_l; /* individual address filter, low */ u32 gaddr_h; /* group address filter, high */ u32 gaddr_l; /* group address filter, low */ - ucc_geth_82xx_enet_address_t taddr; - ucc_geth_82xx_enet_address_t paddr[NUM_OF_PADDRS]; + struct ucc_geth_82xx_enet_address taddr; + struct ucc_geth_82xx_enet_address paddr[NUM_OF_PADDRS]; u8 res0[0x40 - 0x38]; -} __attribute__ ((packed)) ucc_geth_82xx_address_filtering_pram_t; +} __attribute__ ((packed)); /* GETH Tx firmware statistics structure, used when calling UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_tx_firmware_statistics { +struct ucc_geth_tx_firmware_statistics { u32 sicoltx; /* single collision */ u32 mulcoltx; /* multiple collision */ u32 latecoltxfr; /* late collision */ @@ -786,11 +786,11 @@ typedef struct ucc_geth_tx_firmware_statistics { and 1518 octets */ u32 txpktsjumbo; /* total packets (including bad) between 1024 and MAXLength octets */ -} __attribute__ ((packed)) ucc_geth_tx_firmware_statistics_t; +} __attribute__ ((packed)); /* GETH Rx firmware statistics structure, used when calling UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_rx_firmware_statistics { +struct ucc_geth_rx_firmware_statistics { u32 frrxfcser; /* frames with crc error */ u32 fraligner; /* frames with alignment error */ u32 inrangelenrxer; /* in range length error */ @@ -822,11 +822,11 @@ typedef struct ucc_geth_rx_firmware_statistics { replaced */ u32 insertvlan; /* total frames that had their VLAN tag inserted */ -} __attribute__ ((packed)) ucc_geth_rx_firmware_statistics_t; +} __attribute__ ((packed)); /* GETH hardware statistics structure, used when calling UCC_GETH_GetStatistics. */ -typedef struct ucc_geth_hardware_statistics { +struct ucc_geth_hardware_statistics { u32 tx64; /* Total number of frames (including bad frames) transmitted that were exactly of the minimal length (64 for un tagged, 68 for @@ -871,7 +871,7 @@ typedef struct ucc_geth_hardware_statistics { u32 rbca; /* Total number of frames received succesfully that had destination address equal to the broadcast address */ -} __attribute__ ((packed)) ucc_geth_hardware_statistics_t; +} __attribute__ ((packed)); /* UCC GETH Tx errors returned via TxConf callback */ #define TX_ERRORS_DEF 0x0200 @@ -1013,21 +1013,21 @@ typedef struct ucc_geth_hardware_statistics { (MIIMCFG_MANAGEMENT_CLOCK_DIVIDE_BY_112) /* Ethernet speed */ -typedef enum enet_speed { +enum enet_speed { ENET_SPEED_10BT, /* 10 Base T */ ENET_SPEED_100BT, /* 100 Base T */ ENET_SPEED_1000BT /* 1000 Base T */ -} enet_speed_e; +}; /* Ethernet Address Type. */ -typedef enum enet_addr_type { +enum enet_addr_type { ENET_ADDR_TYPE_INDIVIDUAL, ENET_ADDR_TYPE_GROUP, ENET_ADDR_TYPE_BROADCAST -} enet_addr_type_e; +}; /* TBI / MII Set Register */ -typedef enum enet_tbi_mii_reg { +enum enet_tbi_mii_reg { ENET_TBI_MII_CR = 0x00, /* Control (CR ) */ ENET_TBI_MII_SR = 0x01, /* Status (SR ) */ ENET_TBI_MII_ANA = 0x04, /* AN advertisement (ANA ) */ @@ -1040,10 +1040,10 @@ typedef enum enet_tbi_mii_reg { ENET_TBI_MII_EXST = 0x0F, /* Extended status (EXST ) */ ENET_TBI_MII_JD = 0x10, /* Jitter diagnostics (JD ) */ ENET_TBI_MII_TBICON = 0x11 /* TBI control (TBICON ) */ -} enet_tbi_mii_reg_e; +}; /* UCC GETH 82xx Ethernet Address Recognition Location */ -typedef enum ucc_geth_enet_address_recognition_location { +enum ucc_geth_enet_address_recognition_location { UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_STATION_ADDRESS,/* station address */ UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_PADDR_FIRST, /* additional @@ -1065,10 +1065,10 @@ typedef enum ucc_geth_enet_address_recognition_location { UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH, /* group hash */ UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH /* individual hash */ -} ucc_geth_enet_address_recognition_location_e; +}; /* UCC GETH vlan operation tagged */ -typedef enum ucc_geth_vlan_operation_tagged { +enum ucc_geth_vlan_operation_tagged { UCC_GETH_VLAN_OPERATION_TAGGED_NOP = 0x0, /* Tagged - nop */ UCC_GETH_VLAN_OPERATION_TAGGED_REPLACE_VID_PORTION_OF_Q_TAG = 0x1, /* Tagged - replace vid portion of q tag */ @@ -1076,18 +1076,18 @@ typedef enum ucc_geth_vlan_operation_tagged { = 0x2, /* Tagged - if vid0 replace vid with default value */ UCC_GETH_VLAN_OPERATION_TAGGED_EXTRACT_Q_TAG_FROM_FRAME = 0x3 /* Tagged - extract q tag from frame */ -} ucc_geth_vlan_operation_tagged_e; +}; /* UCC GETH vlan operation non-tagged */ -typedef enum ucc_geth_vlan_operation_non_tagged { +enum ucc_geth_vlan_operation_non_tagged { UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP = 0x0, /* Non tagged - nop */ UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT = 0x1 /* Non tagged - q tag insert */ -} ucc_geth_vlan_operation_non_tagged_e; +}; /* UCC GETH Rx Quality of Service Mode */ -typedef enum ucc_geth_qos_mode { +enum ucc_geth_qos_mode { UCC_GETH_QOS_MODE_DEFAULT = 0x0, /* default queue */ UCC_GETH_QOS_MODE_QUEUE_NUM_FROM_L2_CRITERIA = 0x1, /* queue determined @@ -1097,11 +1097,11 @@ typedef enum ucc_geth_qos_mode { determined by L3 criteria */ -} ucc_geth_qos_mode_e; +}; /* UCC GETH Statistics Gathering Mode - These are bit flags, 'or' them together for combined functionality */ -typedef enum ucc_geth_statistics_gathering_mode { +enum ucc_geth_statistics_gathering_mode { UCC_GETH_STATISTICS_GATHERING_MODE_NONE = 0x00000000, /* No statistics gathering */ @@ -1122,10 +1122,10 @@ typedef enum ucc_geth_statistics_gathering_mode { statistics gathering */ -} ucc_geth_statistics_gathering_mode_e; +}; /* UCC GETH Pad and CRC Mode - Note, Padding without CRC is not possible */ -typedef enum ucc_geth_maccfg2_pad_and_crc_mode { +enum ucc_geth_maccfg2_pad_and_crc_mode { UCC_GETH_PAD_AND_CRC_MODE_NONE = MACCFG2_PAD_AND_CRC_MODE_NONE, /* Neither Padding short frames @@ -1135,61 +1135,59 @@ typedef enum ucc_geth_maccfg2_pad_and_crc_mode { CRC only */ UCC_GETH_PAD_AND_CRC_MODE_PAD_AND_CRC = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC -} ucc_geth_maccfg2_pad_and_crc_mode_e; +}; /* UCC GETH upsmr Flow Control Mode */ -typedef enum ucc_geth_flow_control_mode { +enum ucc_geth_flow_control_mode { UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE = 0x00000000, /* No automatic flow control */ UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_PAUSE_WHEN_EMERGENCY = 0x00004000 /* Send pause frame when RxFIFO reaches its emergency threshold */ -} ucc_geth_flow_control_mode_e; +}; /* UCC GETH number of threads */ -typedef enum ucc_geth_num_of_threads { +enum ucc_geth_num_of_threads { UCC_GETH_NUM_OF_THREADS_1 = 0x1, /* 1 */ UCC_GETH_NUM_OF_THREADS_2 = 0x2, /* 2 */ UCC_GETH_NUM_OF_THREADS_4 = 0x0, /* 4 */ UCC_GETH_NUM_OF_THREADS_6 = 0x3, /* 6 */ UCC_GETH_NUM_OF_THREADS_8 = 0x4 /* 8 */ -} ucc_geth_num_of_threads_e; +}; /* UCC GETH number of station addresses */ -typedef enum ucc_geth_num_of_station_addresses { +enum ucc_geth_num_of_station_addresses { UCC_GETH_NUM_OF_STATION_ADDRESSES_1, /* 1 */ UCC_GETH_NUM_OF_STATION_ADDRESSES_5 /* 5 */ -} ucc_geth_num_of_station_addresses_e; - -typedef u8 enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS]; +}; /* UCC GETH 82xx Ethernet Address Container */ -typedef struct enet_addr_container { - enet_addr_t address; /* ethernet address */ - ucc_geth_enet_address_recognition_location_e location; /* location in +struct enet_addr_container { + u8 address[ENET_NUM_OCTETS_PER_ADDRESS]; /* ethernet address */ + enum ucc_geth_enet_address_recognition_location location; /* location in 82xx address recognition hardware */ struct list_head node; -} enet_addr_container_t; +}; -#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, enet_addr_container_t, node) +#define ENET_ADDR_CONT_ENTRY(ptr) list_entry(ptr, struct enet_addr_container, node) /* UCC GETH Termination Action Descriptor (TAD) structure. */ -typedef struct ucc_geth_tad_params { +struct ucc_geth_tad_params { int rx_non_dynamic_extended_features_mode; int reject_frame; - ucc_geth_vlan_operation_tagged_e vtag_op; - ucc_geth_vlan_operation_non_tagged_e vnontag_op; - ucc_geth_qos_mode_e rqos; + enum ucc_geth_vlan_operation_tagged vtag_op; + enum ucc_geth_vlan_operation_non_tagged vnontag_op; + enum ucc_geth_qos_mode rqos; u8 vpri; u16 vid; -} ucc_geth_tad_params_t; +}; /* GETH protocol initialization structure */ -typedef struct ucc_geth_info { - ucc_fast_info_t uf_info; +struct ucc_geth_info { + struct ucc_fast_info uf_info; u8 numQueuesTx; u8 numQueuesRx; int ipCheckSumCheck; @@ -1251,51 +1249,51 @@ typedef struct ucc_geth_info { u8 iphoffset[TX_IP_OFFSET_ENTRY_MAX]; u16 bdRingLenTx[NUM_TX_QUEUES]; u16 bdRingLenRx[NUM_RX_QUEUES]; - enet_interface_e enet_interface; - ucc_geth_num_of_station_addresses_e numStationAddresses; - qe_fltr_largest_external_tbl_lookup_key_size_e + enum enet_interface enet_interface; + enum ucc_geth_num_of_station_addresses numStationAddresses; + enum qe_fltr_largest_external_tbl_lookup_key_size largestexternallookupkeysize; - ucc_geth_statistics_gathering_mode_e statisticsMode; - ucc_geth_vlan_operation_tagged_e vlanOperationTagged; - ucc_geth_vlan_operation_non_tagged_e vlanOperationNonTagged; - ucc_geth_qos_mode_e rxQoSMode; - ucc_geth_flow_control_mode_e aufc; - ucc_geth_maccfg2_pad_and_crc_mode_e padAndCrc; - ucc_geth_num_of_threads_e numThreadsTx; - ucc_geth_num_of_threads_e numThreadsRx; - qe_risc_allocation_e riscTx; - qe_risc_allocation_e riscRx; -} ucc_geth_info_t; + enum ucc_geth_statistics_gathering_mode statisticsMode; + enum ucc_geth_vlan_operation_tagged vlanOperationTagged; + enum ucc_geth_vlan_operation_non_tagged vlanOperationNonTagged; + enum ucc_geth_qos_mode rxQoSMode; + enum ucc_geth_flow_control_mode aufc; + enum ucc_geth_maccfg2_pad_and_crc_mode padAndCrc; + enum ucc_geth_num_of_threads numThreadsTx; + enum ucc_geth_num_of_threads numThreadsRx; + enum qe_risc_allocation riscTx; + enum qe_risc_allocation riscRx; +}; /* structure representing UCC GETH */ -typedef struct ucc_geth_private { - ucc_geth_info_t *ug_info; - ucc_fast_private_t *uccf; +struct ucc_geth_private { + struct ucc_geth_info *ug_info; + struct ucc_fast_private *uccf; struct net_device *dev; struct net_device_stats stats; /* linux network statistics */ - ucc_geth_t *ug_regs; - ucc_geth_init_pram_t *p_init_enet_param_shadow; - ucc_geth_exf_global_pram_t *p_exf_glbl_param; + struct ucc_geth *ug_regs; + struct ucc_geth_init_pram *p_init_enet_param_shadow; + struct ucc_geth_exf_global_pram *p_exf_glbl_param; u32 exf_glbl_param_offset; - ucc_geth_rx_global_pram_t *p_rx_glbl_pram; + struct ucc_geth_rx_global_pram *p_rx_glbl_pram; u32 rx_glbl_pram_offset; - ucc_geth_tx_global_pram_t *p_tx_glbl_pram; + struct ucc_geth_tx_global_pram *p_tx_glbl_pram; u32 tx_glbl_pram_offset; - ucc_geth_send_queue_mem_region_t *p_send_q_mem_reg; + struct ucc_geth_send_queue_mem_region *p_send_q_mem_reg; u32 send_q_mem_reg_offset; - ucc_geth_thread_data_tx_t *p_thread_data_tx; + struct ucc_geth_thread_data_tx *p_thread_data_tx; u32 thread_dat_tx_offset; - ucc_geth_thread_data_rx_t *p_thread_data_rx; + struct ucc_geth_thread_data_rx *p_thread_data_rx; u32 thread_dat_rx_offset; - ucc_geth_scheduler_t *p_scheduler; + struct ucc_geth_scheduler *p_scheduler; u32 scheduler_offset; - ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram; + struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram; u32 tx_fw_statistics_pram_offset; - ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram; + struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram; u32 rx_fw_statistics_pram_offset; - ucc_geth_rx_interrupt_coalescing_table_t *p_rx_irq_coalescing_tbl; + struct ucc_geth_rx_interrupt_coalescing_table *p_rx_irq_coalescing_tbl; u32 rx_irq_coalescing_tbl_offset; - ucc_geth_rx_bd_queues_entry_t *p_rx_bd_qs_tbl; + struct ucc_geth_rx_bd_queues_entry *p_rx_bd_qs_tbl; u32 rx_bd_qs_tbl_offset; u8 *p_tx_bd_ring[NUM_TX_QUEUES]; u32 tx_bd_ring_offset[NUM_TX_QUEUES]; @@ -1308,7 +1306,7 @@ typedef struct ucc_geth_private { u16 cpucount[NUM_TX_QUEUES]; volatile u16 *p_cpucount[NUM_TX_QUEUES]; int indAddrRegUsed[NUM_OF_PADDRS]; - enet_addr_t paddr[NUM_OF_PADDRS]; + u8 paddr[NUM_OF_PADDRS][ENET_NUM_OCTETS_PER_ADDRESS]; /* ethernet address */ u8 numGroupAddrInHash; u8 numIndAddrInHash; u8 numIndAddrInReg; @@ -1334,6 +1332,6 @@ typedef struct ucc_geth_private { int oldspeed; int oldduplex; int oldlink; -} ucc_geth_private_t; +}; #endif /* __UCC_GETH_H__ */ diff --git a/drivers/net/ucc_geth_phy.c b/drivers/net/ucc_geth_phy.c index 67260eb3188a..5360ec05eaa3 100644 --- a/drivers/net/ucc_geth_phy.c +++ b/drivers/net/ucc_geth_phy.c @@ -42,7 +42,6 @@ #include "ucc_geth.h" #include "ucc_geth_phy.h" -#include #define ugphy_printk(level, format, arg...) \ printk(level format "\n", ## arg) @@ -72,16 +71,14 @@ static int genmii_read_status(struct ugeth_mii_info *mii_info); u16 phy_read(struct ugeth_mii_info *mii_info, u16 regnum); void phy_write(struct ugeth_mii_info *mii_info, u16 regnum, u16 val); -static u8 *bcsr_regs = NULL; - /* Write value to the PHY for this device to the register at regnum, */ /* waiting until the write is done before it returns. All PHY */ /* configuration has to be done through the TSEC1 MIIM regs */ void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) { - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_mii_mng_t *mii_regs; - enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_mii_mng *mii_regs; + enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum; u32 tmp_reg; ugphy_vdbg("%s: IN", __FUNCTION__); @@ -116,9 +113,9 @@ void write_phy_reg(struct net_device *dev, int mii_id, int regnum, int value) /* configuration has to be done through the TSEC1 MIIM regs */ int read_phy_reg(struct net_device *dev, int mii_id, int regnum) { - ucc_geth_private_t *ugeth = netdev_priv(dev); - ucc_mii_mng_t *mii_regs; - enet_tbi_mii_reg_e mii_reg = (enet_tbi_mii_reg_e) regnum; + struct ucc_geth_private *ugeth = netdev_priv(dev); + struct ucc_mii_mng *mii_regs; + enum enet_tbi_mii_reg mii_reg = (enum enet_tbi_mii_reg) regnum; u32 tmp_reg; u16 value; @@ -634,11 +631,6 @@ static void dm9161_close(struct ugeth_mii_info *mii_info) static int dm9161_ack_interrupt(struct ugeth_mii_info *mii_info) { -/* FIXME: This lines are for BUG fixing in the mpc8325. -Remove this from here when it's fixed */ - if (bcsr_regs == NULL) - bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); - bcsr_regs[14] |= 0x40; ugphy_vdbg("%s: IN", __FUNCTION__); /* Clear the interrupts by reading the reg */ @@ -650,12 +642,6 @@ Remove this from here when it's fixed */ static int dm9161_config_intr(struct ugeth_mii_info *mii_info) { -/* FIXME: This lines are for BUG fixing in the mpc8325. -Remove this from here when it's fixed */ - if (bcsr_regs == NULL) { - bcsr_regs = (u8 *) ioremap(BCSR_PHYS_ADDR, BCSR_SIZE); - bcsr_regs[14] &= ~0x40; - } ugphy_vdbg("%s: IN", __FUNCTION__); if (mii_info->interrupts == MII_INTERRUPT_ENABLED) diff --git a/drivers/net/ucc_geth_phy.h b/drivers/net/ucc_geth_phy.h index 2f98b8f1bb0a..f5740783670f 100644 --- a/drivers/net/ucc_geth_phy.h +++ b/drivers/net/ucc_geth_phy.h @@ -126,7 +126,7 @@ struct ugeth_mii_info { /* And management functions */ struct phy_info *phyinfo; - ucc_mii_mng_t *mii_regs; + struct ucc_mii_mng *mii_regs; /* forced speed & duplex (no autoneg) * partner speed & duplex & pause (autoneg) -- cgit v1.2.3 From 089fff2aa8cc2a0383ea9fce17afd10bfab9ac7c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 18 Oct 2006 00:30:27 -0400 Subject: [PATCH] Remove useless comment from sb1250 Signed-off-by: Dave Jones Signed-off-by: Jeff Garzik --- drivers/net/sb1250-mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index db2324939b69..1eae16b72b4b 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2903,7 +2903,7 @@ sbmac_init_module(void) dev = alloc_etherdev(sizeof(struct sbmac_softc)); if (!dev) - return -ENOMEM; /* return ENOMEM */ + return -ENOMEM; printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port); -- cgit v1.2.3 From cfadbd298e8b3e7f2e324696b653bb74094590db Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 18 Oct 2006 02:15:37 +0100 Subject: [PATCH] Fix timer race When closing the driver or reinitializing the hardware there is the usual del_timer() race condition that exists when timers re-add themselves. Fix by conversion to del_timer_sync(). Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/ioc3-eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index e963dbf816be..f56b00ee385e 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -1017,7 +1017,7 @@ static void ioc3_init(struct net_device *dev) struct ioc3_private *ip = netdev_priv(dev); struct ioc3 *ioc3 = ip->regs; - del_timer(&ip->ioc3_timer); /* Kill if running */ + del_timer_sync(&ip->ioc3_timer); /* Kill if running */ ioc3_w_emcr(EMCR_RST); /* Reset */ (void) ioc3_r_emcr(); /* Flush WB */ @@ -1081,7 +1081,7 @@ static int ioc3_close(struct net_device *dev) { struct ioc3_private *ip = netdev_priv(dev); - del_timer(&ip->ioc3_timer); + del_timer_sync(&ip->ioc3_timer); netif_stop_queue(dev); -- cgit v1.2.3 From 5826cade4341a6298eb10d476dccc5f403ca7ad8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 13 Oct 2006 14:20:59 +1000 Subject: [PATCH] ibmveth: Fix index increment calculation On Thu, Oct 12, 2006 at 06:22:14PM +1000, David Gibson wrote: > Your recent ibmveth commit, 751ae21c6cd1493e3d0a4935b08fb298b9d89773 > ("fix int rollover panic"), causes a rapid oops on my test machine > (POWER5 LPAR). > > I've bisected it down to that commit, but am still investigating the > cause of the crash itself. Found the problem, I believe: an object lesson in the need for great caution using ++. [...] @@ -213,6 +213,7 @@ static void ibmveth_replenish_buffer_poo } free_index = pool->consumer_index++ % pool->size; + pool->consumer_index = free_index; index = pool->free_map[free_index]; ibmveth_assert(index != IBM_VETH_INVALID_MAP); Since the ++ is used as post-increment, the increment is not included in free_index, and so the added line effectively reverts the increment. The produced_index side has an analagous bug. The following change corrects this: The recent commit 751ae21c6cd1493e3d0a4935b08fb298b9d89773 introduced a bug in the producer/consumer index calculation in the ibmveth driver - incautious use of the post-increment ++ operator resulted in an increment being immediately reverted. This patch corrects the logic. Without this patch, the driver oopses almost immediately after activation on at least some machines. Signed-off-by: David Gibson Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2802db23d3cb..44c9f993dcc4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -212,8 +212,8 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc break; } - free_index = pool->consumer_index++ % pool->size; - pool->consumer_index = free_index; + free_index = pool->consumer_index; + pool->consumer_index = (pool->consumer_index + 1) % pool->size; index = pool->free_map[free_index]; ibmveth_assert(index != IBM_VETH_INVALID_MAP); @@ -329,8 +329,10 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 adapter->rx_buff_pool[pool].buff_size, DMA_FROM_DEVICE); - free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; - adapter->rx_buff_pool[pool].producer_index = free_index; + free_index = adapter->rx_buff_pool[pool].producer_index; + adapter->rx_buff_pool[pool].producer_index + = (adapter->rx_buff_pool[pool].producer_index + 1) + % adapter->rx_buff_pool[pool].size; adapter->rx_buff_pool[pool].free_map[free_index] = index; mb(); -- cgit v1.2.3 From 158f30c8945fea7cf0d0161cd9463cf2f3d2c19e Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Thu, 19 Oct 2006 13:27:39 -0700 Subject: [PATCH] libata: use correct map_db values for ICH8 Use valid values for ICH8 map_db. With the old values, when the controller was in Native mode, and SCC was 1 (drives configured for IDE), any drive plugged into a slave port was not recognized. For Combined Mode (and SCC is still 1), 2 is a value value for MAP.map_value, and needs to be recognized. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 5719704eb0ee..5250187ffce2 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -432,9 +432,9 @@ static const struct piix_map_db ich8_map_db = { .present_shift = 8, .map = { /* PM PS SM SS MAP */ - { P0, NA, P1, NA }, /* 00b (hardwired) */ + { P0, P2, P1, P3 }, /* 00b (hardwired when in AHCI) */ { RV, RV, RV, RV }, - { RV, RV, RV, RV }, /* 10b (never) */ + { IDE, IDE, NA, NA }, /* 10b (IDE mode) */ { RV, RV, RV, RV }, }, }; -- cgit v1.2.3 From bf2d401bca3681f5380f711be65f2026255cc166 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 20 Oct 2006 14:39:35 -0700 Subject: [PATCH] ATA must depend on BLOCK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the following compile error with CONFIG_ATA=y, CONFIG_BLOCK=n: ... CC drivers/ata/libata-scsi.o /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c: In function â€ata_scsi_dev_config’: /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:791: warning: implicit declaration of function â€blk_queue_max_sectors’ /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:799: error: â€request_queue_t’ undeclared (first use in this function) /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:799: error: (Each undeclared identifier is reported only once /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:799: error: for each function it appears in.) /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:799: error: â€q’ undeclared (first use in this function) /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:800: warning: implicit declaration of function â€blk_queue_max_hw_segments’ /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c: In function â€ata_scsi_slave_config’: /home/bunk/linux/kernel-2.6/git/linux-2.6/drivers/ata/libata-scsi.c:831: warning: implicit declaration of function â€blk_queue_max_phys_segments’ make[3]: *** [drivers/ata/libata-scsi.o] Error 1 Bug report by Jesper Juhl. Signed-off-by: Adrian Bunk Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 3f4aa0c99ee4..03f6338acc8f 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -6,6 +6,7 @@ menu "Serial ATA (prod) and Parallel ATA (experimental) drivers" config ATA tristate "ATA device support" + depends on BLOCK depends on !(M32R || M68K) || BROKEN depends on !SUN4 || BROKEN select SCSI -- cgit v1.2.3 From 12a87d36b3c5cb76a182c35f40d959a615d1c862 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:21:40 +0100 Subject: [PATCH] ahci: readability tweak Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 25929123ffff..cef2e70d64f8 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1041,7 +1041,7 @@ static void ahci_host_intr(struct ata_port *ap) /* hmmm... a spurious interupt */ /* some devices send D2H reg with I bit set during NCQ command phase */ - if (ap->sactive && status & PORT_IRQ_D2H_REG_FIS) + if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS)) return; /* ignore interim PIO setup fis interrupts */ -- cgit v1.2.3 From 8eb166bf805cc1c1d38d57211e8737631376b9ba Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:24:50 +0100 Subject: [PATCH] libata-sff: Allow for wacky systems There are some Linux supported platforms that simply cannot hit the low I/O addresses used by ATA legacy mode PCI mappings. These platforms have a window for PCI space that is fixed by the board logic and doesn't include the neccessary locations. Provide a config option so that such platforms faced with a controller that they cannot support simply error it and punt Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 06daaa3736a2..7645f2b30ccf 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -981,6 +981,15 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, mask = (1 << 2) | (1 << 0); if ((tmp8 & mask) != mask) legacy_mode = (1 << 3); +#if defined(CONFIG_NO_ATA_LEGACY) + /* Some platforms with PCI limits cannot address compat + port space. In that case we punt if their firmware has + left a device in compatibility mode */ + if (legacy_mode) { + printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n"); + return -EOPNOTSUPP; + } +#endif } rc = pci_request_regions(pdev, DRV_NAME); -- cgit v1.2.3 From 86fbf1486a44a4bce4fdcbe3665a7d8a62ba958a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 21 Oct 2006 10:24:01 -0700 Subject: [PATCH] Char: correct pci_get_device changes Commits 881a8c120acf7ec09c90289e2996b7c70f51e996 and efe1ec27837d6639eae82e1f5876910ba6433c3f corrects pci device matching in only one way; it no longer oopses/crashes, despite hotplug is not solved in these changes. Whenever pci_find_device -> pci_get_device change is performed, also pci_dev_get and pci_dev_put should be in most cases called to properly handle hotplug. This patch does exactly this thing -- increase refcount to let kernel know, that we are using this piece of HW just now. It affects moxa and rio char drivers. Cc: Acked-by: Amit Gud Acked-by: Greg Kroah-Hartman Acked-by: Alan Cox Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/moxa.c | 9 +++++++++ drivers/char/rio/host.h | 1 + drivers/char/rio/rio_linux.c | 9 +++++++++ 3 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index b401383808c2..96cb1f07332b 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -130,6 +130,7 @@ static moxa_isa_board_conf moxa_isa_boards[] = typedef struct _moxa_pci_devinfo { ushort busNum; ushort devNum; + struct pci_dev *pdev; } moxa_pci_devinfo; typedef struct _moxa_board_conf { @@ -324,6 +325,9 @@ static int moxa_get_PCI_conf(struct pci_dev *p, int board_type, moxa_board_conf board->busType = MOXA_BUS_TYPE_PCI; board->pciInfo.busNum = p->bus->number; board->pciInfo.devNum = p->devfn >> 3; + board->pciInfo.pdev = p; + /* don't lose the reference in the next pci_get_device iteration */ + pci_dev_get(p); return (0); } @@ -493,6 +497,11 @@ static void __exit moxa_exit(void) if (tty_unregister_driver(moxaDriver)) printk("Couldn't unregister MOXA Intellio family serial driver\n"); put_tty_driver(moxaDriver); + + for (i = 0; i < MAX_BOARDS; i++) + if (moxa_boards[i].busType == MOXA_BUS_TYPE_PCI) + pci_dev_put(moxa_boards[i].pciInfo.pdev); + if (verbose) printk("Done\n"); } diff --git a/drivers/char/rio/host.h b/drivers/char/rio/host.h index ee2ddea7a63a..23d0681fe491 100644 --- a/drivers/char/rio/host.h +++ b/drivers/char/rio/host.h @@ -44,6 +44,7 @@ ** the host. */ struct Host { + struct pci_dev *pdev; unsigned char Type; /* RIO_EISA, RIO_MCA, ... */ unsigned char Ivec; /* POLLED or ivec number */ unsigned char Mode; /* Control stuff */ diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index c382df0f82f6..7ac68cb3bedd 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -1017,6 +1017,10 @@ static int __init rio_init(void) rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); fix_rio_pci(pdev); + + p->RIOHosts[p->RIONumHosts].pdev = pdev; + pci_dev_get(pdev); + p->RIOLastPCISearch = 0; p->RIONumHosts++; found++; @@ -1066,6 +1070,9 @@ static int __init rio_init(void) ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24); rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum); + p->RIOHosts[p->RIONumHosts].pdev = pdev; + pci_dev_get(pdev); + p->RIOLastPCISearch = 0; p->RIONumHosts++; found++; @@ -1181,6 +1188,8 @@ static void __exit rio_exit(void) } /* It is safe/allowed to del_timer a non-active timer */ del_timer(&hp->timer); + if (hp->Type == RIO_PCI) + pci_dev_put(hp->pdev); } if (misc_deregister(&rio_fw_device) < 0) { -- cgit v1.2.3 From 3c5473f80770768ab5712eb5a7492c16e97209fe Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 21 Oct 2006 10:24:06 -0700 Subject: [PATCH] drivers/ide/pci/generic.c: re-add the __setup("all-generic-ide",...) The change from __setup() to module_param_named() requires users to prefix the option with "generic.". This patch re-adds the __setup() additionally to the module_param_named(). Usually it would make sense getting rid of such an obsolete __setup() at some time, but considering that drivers/ide/ is slowly approaching a RIP status it's already implicitely scheduled for removal. This patch fixes kernel Bugzilla #7353. Signed-off-by: Adrian Bunk Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/generic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index 5b77a5bcbf0c..ad418ce882ca 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -40,6 +40,19 @@ static int ide_generic_all; /* Set to claim all devices */ +/* + * the module_param_named() was added for the modular case + * the __setup() is left as compatibility for existing setups + */ +#ifndef MODULE +static int __init ide_generic_all_on(char *unused) +{ + ide_generic_all = 1; + printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers."); + return 1; +} +__setup("all-generic-ide", ide_generic_all_on); +#endif module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); -- cgit v1.2.3 From 2e333e89860431d22816c1bdaa2ea72c2753396e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 21 Oct 2006 10:24:07 -0700 Subject: [PATCH] md: fix calculation of ->degraded for multipath and raid10 Two less-used md personalities have bugs in the calculation of ->degraded (the extent to which the array is degraded). Signed-off-by: Neil Brown Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/multipath.c | 2 +- drivers/md/raid10.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 171ff41b52b0..a6260f0e3b9e 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -501,7 +501,7 @@ static int multipath_run (mddev_t *mddev) mdname(mddev)); goto out_free_conf; } - mddev->degraded = conf->raid_disks = conf->working_disks; + mddev->degraded = conf->raid_disks - conf->working_disks; conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS, sizeof(struct multipath_bh)); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 1250f0eab4af..74f17a9a6ebb 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2079,7 +2079,7 @@ static int run(mddev_t *mddev) disk = conf->mirrors + i; if (!disk->rdev || - !test_bit(In_sync, &rdev->flags)) { + !test_bit(In_sync, &disk->rdev->flags)) { disk->head_position = 0; mddev->degraded++; } -- cgit v1.2.3 From 1c05b4bc22cd640d3a534bd2851a8413d5df3709 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 21 Oct 2006 10:24:08 -0700 Subject: [PATCH] md: endian annotation for v1 superblock access Includes a couple of bugfixes found by sparse. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 13 ++++++----- include/linux/raid/md_p.h | 56 +++++++++++++++++++++++------------------------ 2 files changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index f7f19088f3be..7daa7b1e145f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -974,12 +974,13 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) * version 1 superblock */ -static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) +static __le32 calc_sb_1_csum(struct mdp_superblock_1 * sb) { - unsigned int disk_csum, csum; + __le32 disk_csum; + u32 csum; unsigned long long newcsum; int size = 256 + le32_to_cpu(sb->max_dev)*2; - unsigned int *isuper = (unsigned int*)sb; + __le32 *isuper = (__le32*)sb; int i; disk_csum = sb->sb_csum; @@ -989,7 +990,7 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) newcsum += le32_to_cpu(*isuper++); if (size == 2) - newcsum += le16_to_cpu(*(unsigned short*) isuper); + newcsum += le16_to_cpu(*(__le16*) isuper); csum = (newcsum & 0xffffffff) + (newcsum >> 32); sb->sb_csum = disk_csum; @@ -1106,7 +1107,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) if (le32_to_cpu(sb->chunksize)) rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); - if (le32_to_cpu(sb->size) > rdev->size*2) + if (le64_to_cpu(sb->size) > rdev->size*2) return -EINVAL; return ret; } @@ -1228,7 +1229,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) else sb->resync_offset = cpu_to_le64(0); - sb->cnt_corrected_read = atomic_read(&rdev->corrected_errors); + sb->cnt_corrected_read = cpu_to_le32(atomic_read(&rdev->corrected_errors)); sb->raid_disks = cpu_to_le32(mddev->raid_disks); sb->size = cpu_to_le64(mddev->size<<1); diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h index b6ebc69bae54..3f2cd98c508b 100644 --- a/include/linux/raid/md_p.h +++ b/include/linux/raid/md_p.h @@ -206,52 +206,52 @@ static inline __u64 md_event(mdp_super_t *sb) { */ struct mdp_superblock_1 { /* constant array information - 128 bytes */ - __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ - __u32 major_version; /* 1 */ - __u32 feature_map; /* bit 0 set if 'bitmap_offset' is meaningful */ - __u32 pad0; /* always set to 0 when writing */ + __le32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */ + __le32 major_version; /* 1 */ + __le32 feature_map; /* bit 0 set if 'bitmap_offset' is meaningful */ + __le32 pad0; /* always set to 0 when writing */ __u8 set_uuid[16]; /* user-space generated. */ char set_name[32]; /* set and interpreted by user-space */ - __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ - __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ - __u32 layout; /* only for raid5 and raid10 currently */ - __u64 size; /* used size of component devices, in 512byte sectors */ + __le64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/ + __le32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */ + __le32 layout; /* only for raid5 and raid10 currently */ + __le64 size; /* used size of component devices, in 512byte sectors */ - __u32 chunksize; /* in 512byte sectors */ - __u32 raid_disks; - __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts + __le32 chunksize; /* in 512byte sectors */ + __le32 raid_disks; + __le32 bitmap_offset; /* sectors after start of superblock that bitmap starts * NOTE: signed, so bitmap can be before superblock * only meaningful of feature_map[0] is set. */ /* These are only valid with feature bit '4' */ - __u32 new_level; /* new level we are reshaping to */ - __u64 reshape_position; /* next address in array-space for reshape */ - __u32 delta_disks; /* change in number of raid_disks */ - __u32 new_layout; /* new layout */ - __u32 new_chunk; /* new chunk size (bytes) */ + __le32 new_level; /* new level we are reshaping to */ + __le64 reshape_position; /* next address in array-space for reshape */ + __le32 delta_disks; /* change in number of raid_disks */ + __le32 new_layout; /* new layout */ + __le32 new_chunk; /* new chunk size (bytes) */ __u8 pad1[128-124]; /* set to 0 when written */ /* constant this-device information - 64 bytes */ - __u64 data_offset; /* sector start of data, often 0 */ - __u64 data_size; /* sectors in this device that can be used for data */ - __u64 super_offset; /* sector start of this superblock */ - __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ - __u32 dev_number; /* permanent identifier of this device - not role in raid */ - __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ + __le64 data_offset; /* sector start of data, often 0 */ + __le64 data_size; /* sectors in this device that can be used for data */ + __le64 super_offset; /* sector start of this superblock */ + __le64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */ + __le32 dev_number; /* permanent identifier of this device - not role in raid */ + __le32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */ __u8 device_uuid[16]; /* user-space setable, ignored by kernel */ __u8 devflags; /* per-device flags. Only one defined...*/ #define WriteMostly1 1 /* mask for writemostly flag in above */ __u8 pad2[64-57]; /* set to 0 when writing */ /* array state information - 64 bytes */ - __u64 utime; /* 40 bits second, 24 btes microseconds */ - __u64 events; /* incremented when superblock updated */ - __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ - __u32 sb_csum; /* checksum upto devs[max_dev] */ - __u32 max_dev; /* size of devs[] array to consider */ + __le64 utime; /* 40 bits second, 24 btes microseconds */ + __le64 events; /* incremented when superblock updated */ + __le64 resync_offset; /* data before this offset (from data_offset) known to be in sync */ + __le32 sb_csum; /* checksum upto devs[max_dev] */ + __le32 max_dev; /* size of devs[] array to consider */ __u8 pad3[64-32]; /* set to 0 when writing */ /* device state information. Indexed by dev_number. @@ -260,7 +260,7 @@ struct mdp_superblock_1 { * into the 'roles' value. If a device is spare or faulty, then it doesn't * have a meaningful role. */ - __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ + __le16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */ }; /* feature_map bits */ -- cgit v1.2.3 From 4f2e639af4bd5e152fc79256e333643d3dd6c10f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 21 Oct 2006 10:24:09 -0700 Subject: [PATCH] md: endian annotations for the bitmap superblock And a couple of bug fixes found by sparse. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 10 +++++----- include/linux/raid/bitmap.h | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index d47d38ac71b1..d6f614738bbd 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -536,7 +536,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) " "-- forcing full recovery\n", bmname(bitmap), events, (unsigned long long) bitmap->mddev->events); - sb->state |= BITMAP_STALE; + sb->state |= cpu_to_le32(BITMAP_STALE); } success: /* assign fields using values from superblock */ @@ -544,11 +544,11 @@ success: bitmap->daemon_sleep = daemon_sleep; bitmap->daemon_lastrun = jiffies; bitmap->max_write_behind = write_behind; - bitmap->flags |= sb->state; + bitmap->flags |= le32_to_cpu(sb->state); if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) bitmap->flags |= BITMAP_HOSTENDIAN; bitmap->events_cleared = le64_to_cpu(sb->events_cleared); - if (sb->state & BITMAP_STALE) + if (sb->state & cpu_to_le32(BITMAP_STALE)) bitmap->events_cleared = bitmap->mddev->events; err = 0; out: @@ -578,9 +578,9 @@ static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, spin_unlock_irqrestore(&bitmap->lock, flags); sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); switch (op) { - case MASK_SET: sb->state |= bits; + case MASK_SET: sb->state |= cpu_to_le32(bits); break; - case MASK_UNSET: sb->state &= ~bits; + case MASK_UNSET: sb->state &= cpu_to_le32(~bits); break; default: BUG(); } diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 84d887751855..ebd42a3710b4 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h @@ -146,16 +146,16 @@ enum bitmap_state { /* the superblock at the front of the bitmap file -- little endian */ typedef struct bitmap_super_s { - __u32 magic; /* 0 BITMAP_MAGIC */ - __u32 version; /* 4 the bitmap major for now, could change... */ - __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */ - __u64 events; /* 24 event counter for the bitmap (1)*/ - __u64 events_cleared;/*32 event counter when last bit cleared (2) */ - __u64 sync_size; /* 40 the size of the md device's sync range(3) */ - __u32 state; /* 48 bitmap state information */ - __u32 chunksize; /* 52 the bitmap chunk size in bytes */ - __u32 daemon_sleep; /* 56 seconds between disk flushes */ - __u32 write_behind; /* 60 number of outstanding write-behind writes */ + __le32 magic; /* 0 BITMAP_MAGIC */ + __le32 version; /* 4 the bitmap major for now, could change... */ + __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */ + __le64 events; /* 24 event counter for the bitmap (1)*/ + __le64 events_cleared;/*32 event counter when last bit cleared (2) */ + __le64 sync_size; /* 40 the size of the md device's sync range(3) */ + __le32 state; /* 48 bitmap state information */ + __le32 chunksize; /* 52 the bitmap chunk size in bytes */ + __le32 daemon_sleep; /* 56 seconds between disk flushes */ + __le32 write_behind; /* 60 number of outstanding write-behind writes */ __u8 pad[256 - 64]; /* set to zero */ } bitmap_super_t; -- cgit v1.2.3 From 78f32668e64caea8f638b9133da7b97c5aec20d1 Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Sat, 21 Oct 2006 10:24:10 -0700 Subject: [PATCH] clocksource: acpi_pm: add another greylist chipset I have an acpi_pm that goes backwards, but it's not intel. I tested the verified read and my acpi_pm started to function properly. So I added it to the greylist. I'm assuming that's the right spot. I also added an unlikely() to the while, cause it seems appropriate. Signed-off-by: Daniel Walker Acked-by: John Stultz Acked-by: OGAWA Hirofumi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/clocksource/acpi_pm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c index 7ad3be8c0f49..7fcb77a9d011 100644 --- a/drivers/clocksource/acpi_pm.c +++ b/drivers/clocksource/acpi_pm.c @@ -54,8 +54,8 @@ static cycle_t acpi_pm_read_verified(void) v1 = read_pmtmr(); v2 = read_pmtmr(); v3 = read_pmtmr(); - } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) - || (v3 > v1 && v3 < v2)); + } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2))); return (cycle_t)v2; } @@ -138,6 +138,8 @@ static void __devinit acpi_pm_check_graylist(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, acpi_pm_check_graylist); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, + acpi_pm_check_graylist); #endif -- cgit v1.2.3 From 047a66d4bb24aaf19f41d620f8f0534c2153cd0b Mon Sep 17 00:00:00 2001 From: David Gibson Date: Sat, 21 Oct 2006 10:24:13 -0700 Subject: [PATCH] ibmveth: Fix index increment calculation The recent commit 751ae21c6cd1493e3d0a4935b08fb298b9d89773 introduced a bug in the producer/consumer index calculation in the ibmveth driver - incautious use of the post-increment ++ operator resulted in an increment being immediately reverted. This patch corrects the logic. Without this patch, the driver oopses almost immediately after activation on at least some machines. Signed-off-by: David Gibson Acked-by: Santiago Leon Cc: Jeff Garzik Cc: Martin Schwidefsky Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/ibmveth.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 2802db23d3cb..44c9f993dcc4 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -212,8 +212,8 @@ static void ibmveth_replenish_buffer_pool(struct ibmveth_adapter *adapter, struc break; } - free_index = pool->consumer_index++ % pool->size; - pool->consumer_index = free_index; + free_index = pool->consumer_index; + pool->consumer_index = (pool->consumer_index + 1) % pool->size; index = pool->free_map[free_index]; ibmveth_assert(index != IBM_VETH_INVALID_MAP); @@ -329,8 +329,10 @@ static void ibmveth_remove_buffer_from_pool(struct ibmveth_adapter *adapter, u64 adapter->rx_buff_pool[pool].buff_size, DMA_FROM_DEVICE); - free_index = adapter->rx_buff_pool[pool].producer_index++ % adapter->rx_buff_pool[pool].size; - adapter->rx_buff_pool[pool].producer_index = free_index; + free_index = adapter->rx_buff_pool[pool].producer_index; + adapter->rx_buff_pool[pool].producer_index + = (adapter->rx_buff_pool[pool].producer_index + 1) + % adapter->rx_buff_pool[pool].size; adapter->rx_buff_pool[pool].free_map[free_index] = index; mb(); -- cgit v1.2.3 From 8a7822a61ca9c22f464c0b79f455e62cccee747e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 21 Oct 2006 10:24:17 -0700 Subject: [PATCH] i2o/exec-osm.c: use "unsigned long flags;" Just like everyone else. Signed-off-by: Alexey Dobriyan Cc: Markus Lidel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/message/i2o/exec-osm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 91f95d172ca5..01a5a702b037 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -127,7 +127,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, DECLARE_WAIT_QUEUE_HEAD(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; - long flags; + unsigned long flags; int rc = 0; wait = i2o_exec_wait_alloc(); -- cgit v1.2.3 From 3f7705eab6722ad1a346d748c4aad55755d6c241 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 21 Oct 2006 10:24:19 -0700 Subject: [PATCH] cciss: Fix warnings (and bug on 1TB discs) CCISS was producing warnings about shifts being greater than the size of the type and pointers being of incompatible type. Turns out this is because it's calling do_div on a 32-bit quantity. Upon further investigation, the sector_t total_size is being assigned to an int, and then we're calling do_div on that int. Obviously, sector_div is called for here, and I took the chance to refactor the code a little. Signed-off-by: Matthew Wilcox Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index dcccaf2782f3..bc6602606fb5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1923,7 +1923,6 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, { int return_code; unsigned long t; - unsigned long rem; memset(inq_buff, 0, sizeof(InquiryData_struct)); if (withirq) @@ -1939,26 +1938,23 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, printk(KERN_WARNING "cciss: reading geometry failed, volume " "does not support reading geometry\n"); - drv->block_size = block_size; - drv->nr_blocks = total_size; drv->heads = 255; drv->sectors = 32; // Sectors per track - t = drv->heads * drv->sectors; - drv->cylinders = total_size; - rem = do_div(drv->cylinders, t); } else { - drv->block_size = block_size; - drv->nr_blocks = total_size; drv->heads = inq_buff->data_byte[6]; drv->sectors = inq_buff->data_byte[7]; drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8; drv->cylinders += inq_buff->data_byte[5]; drv->raid_level = inq_buff->data_byte[8]; - t = drv->heads * drv->sectors; - if (t > 1) { - drv->cylinders = total_size; - rem = do_div(drv->cylinders, t); - } + } + drv->block_size = block_size; + drv->nr_blocks = total_size; + t = drv->heads * drv->sectors; + if (t > 1) { + unsigned rem = sector_div(total_size, t); + if (rem) + total_size++; + drv->cylinders = total_size; } } else { /* Get geometry failed */ printk(KERN_WARNING "cciss: reading geometry failed\n"); -- cgit v1.2.3 From b45eccdb51c102e3c5ff9eaecc36200ab2eb09c0 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Fri, 20 Oct 2006 19:49:45 -0700 Subject: [ATM]: No need to return void The module_exit function has return-type void and pci_unregister_driver() returns void anyway. Signed-off-by: Tobias Klauser Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/ambassador.c | 4 ++-- drivers/atm/horizon.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 323592de047b..9fffa7af6db1 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -2452,8 +2452,8 @@ static int __init amb_module_init (void) static void __exit amb_module_exit (void) { PRINTD (DBG_FLOW|DBG_INIT, "cleanup_module"); - - return pci_unregister_driver(&amb_driver); + + pci_unregister_driver(&amb_driver); } module_init(amb_module_init); diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index f59349206dd2..44268cba5a5a 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -2932,8 +2932,8 @@ static int __init hrz_module_init (void) { static void __exit hrz_module_exit (void) { PRINTD (DBG_FLOW, "cleanup_module"); - - return pci_unregister_driver(&hrz_driver); + + pci_unregister_driver(&hrz_driver); } module_init(hrz_module_init); -- cgit v1.2.3 From 663bab6fd097c18ae0c7a7fd1b4a44558b998cdb Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 20 Oct 2006 19:50:50 -0700 Subject: [ATM] firestream: handle thrown error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc emits the following warning: drivers/atm/firestream.c: In function â€fs_open’: drivers/atm/firestream.c:870: warning: â€tmc0’ may be used uninitialized in this function This indicates a real bug. We should check make_rate() return value for potential errors. Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/firestream.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 40ab9b65fae9..697ad82f6634 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1002,6 +1002,10 @@ static int fs_open(struct atm_vcc *atm_vcc) r = ROUND_UP; } error = make_rate (pcr, r, &tmc0, NULL); + if (error) { + kfree(tc); + return error; + } } fs_dprintk (FS_DEBUG_OPEN, "pcr = %d.\n", pcr); } -- cgit v1.2.3 From 69c3014763966b0ae2bd190dac3654dd6cebdd45 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 20 Oct 2006 19:51:46 -0700 Subject: [ATM] nicstar: Fix a bogus casting warning Not enough to make Nicstar 64bit friendly but got squashed in passing so might as well be applied Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/atm/nicstar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 632ede552761..bd0904594805 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -2759,7 +2759,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) { ns_dev *card; pool_levels pl; - int btype; + long btype; unsigned long flags; card = dev->dev_data; @@ -2859,7 +2859,7 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void __user *arg) case NS_ADJBUFLEV: if (!capable(CAP_NET_ADMIN)) return -EPERM; - btype = (int) arg; /* an int is the same size as a pointer */ + btype = (long) arg; /* a long is the same size as a pointer or bigger */ switch (btype) { case NS_BUFTYPE_SMALL: -- cgit v1.2.3 From 4e8a5201506423e0241202de1349422af4260296 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 22 Oct 2006 21:00:33 -0700 Subject: [PKT_SCHED] netem: Orphan SKB when adding to queue. The networking emulator can queue SKBs for a very long time, so if you're using netem on the sender side for large bandwidth/delay product testing, the SKB socket send queue sizes become artificially larger. Correct this by calling skb_orphan() in netem_enqueue(). Signed-off-by: David S. Miller --- drivers/pci/quirks.c | 4 ++-- net/sched/sch_netem.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e8a7f1b1b2bc..ecf8e4d6b9da 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1634,7 +1634,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1 * is marked here since the boot video device will be the only enabled * video device at this point. */ - +#if 0 static void __devinit fixup_video(struct pci_dev *pdev) { struct pci_dev *bridge; @@ -1663,7 +1663,7 @@ static void __devinit fixup_video(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); - +#endif static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 45939bafbdf8..ef8874babf6a 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -170,6 +170,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) return NET_XMIT_BYPASS; } + skb_orphan(skb); + /* * If we need to duplicate packet, then re-insert at top of the * qdisc tree, since parent queuer expects that only one -- cgit v1.2.3 From 00b3b3e6605d7446cd410c7c9bb98f5336a15ca1 Mon Sep 17 00:00:00 2001 From: Sven Anders & Marcus Junker Date: Mon, 16 Oct 2006 18:18:09 +0200 Subject: [WATCHDOG] NS pc87413-wdt Watchdog driver v1.1 Change the driver for proper spin_locking, remove the TEMP_MINOR stuff, make sure the device works as a Virtual File System that is non_seekable, ... Signed-off-by: Sven Anders Signed-off-by: Marcus Junker Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pc87413_wdt.c | 634 +++++++++++++++++++----------------- 1 file changed, 330 insertions(+), 304 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index a6d42cf385e6..4d5612146cde 100644 --- a/drivers/char/watchdog/pc87413_wdt.c +++ b/drivers/char/watchdog/pc87413_wdt.c @@ -1,27 +1,23 @@ /* * NS pc87413-wdt Watchdog Timer driver for Linux 2.6.x.x * - * This code is based on wdt.c with original copyright + * This code is based on wdt.c with original copyright. * - * (C) Copyright 2006 Marcus Junker, - * and Sven Anders, + * (C) Copyright 2006 Sven Anders, + * and Marcus Junker, * * 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. * - * Neither Marcus Junker, Sven Anders nor ANDURAS AG + * Neither Sven Anders, Marcus Junker nor ANDURAS AG * admit liability nor provide warranty for any of this software. * This material is provided "AS-IS" and at no charge. * - * Release 1.00. - * + * Release 1.1 */ - -/* #define DEBUG 1 */ - #include #include #include @@ -41,57 +37,44 @@ #include #include -#define WATCHDOG_NAME "pc87413 WDT" -#define PFX WATCHDOG_NAME ": " -#define DPFX WATCHDOG_NAME " - DEBUG: " - -#define WDT_INDEX_IO_PORT (io+0) /* */ -#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) -#define SWC_LDN 0x04 -#define SIOCFG2 0x22 /* Serial IO register */ -#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ -#define WDTO 0x11 /* Watchdog timeout register */ -#define WDCFG 0x12 /* Watchdog config register */ - -#define WD_TIMEOUT 1 /* minutes (1 ... 255) */ +/* #define DEBUG 1 */ +#define DEFAULT_TIMEOUT 1 /* 1 minute */ +#define MAX_TIMEOUT 255 -static int pc87413_is_open=0; +#define VERSION "1.1" +#define MODNAME "pc87413 WDT" +#define PFX MODNAME ": " +#define DPFX MODNAME " - DEBUG: " -/* - * You must set these - there is no sane way to probe for this board. - * You can use pc87413=x to set these now. - */ +#define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */ +#define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) +#define SWC_LDN 0x04 +#define SIOCFG2 0x22 /* Serial IO register */ +#define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ +#define WDTO 0x11 /* Watchdog timeout register */ +#define WDCFG 0x12 /* Watchdog config register */ +static int io = 0x2E; /* Address used on Portwell Boards */ +static int timeout = DEFAULT_TIMEOUT; /* timeout value */ +static unsigned long timer_enabled = 0; /* is the timer enabled? */ -/** - * module_params - * - * Setup options. The board isn't really probe-able so we have to - * get the user to tell us the configuration. - */ +static char expect_close; /* is the close expected? */ -static int io=0x2E; /* Normally used addres on Portwell Boards */ -module_param(io, int, 0); -MODULE_PARM_DESC(wdt_io, WATCHDOG_NAME " io port (default 0x2E)"); +static spinlock_t io_lock; /* to guard the watchdog from io races */ -static int timeout = WD_TIMEOUT; /* in minutes */ -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes. 1<= timeout <=63, default=" __MODULE_STRING(WD_TIMEOUT) "."); +static int nowayout = WATCHDOG_NOWAYOUT; +/* -- Low level function ----------------------------------------*/ -/****************************************** - * Helper functions - ******************************************/ +/* Select pins for Watchdog output */ -static void -pc87413_select_wdt_out (void) +static inline void pc87413_select_wdt_out (void) { + unsigned int cr_data = 0; - unsigned int cr_data=0; - - /* Select multiple pin,pin55,as WDT output */ + /* Step 1: Select multiple pin,pin55,as WDT output */ outb_p(SIOCFG2, WDT_INDEX_IO_PORT); @@ -102,17 +85,17 @@ pc87413_select_wdt_out (void) outb_p(cr_data, WDT_DATA_IO_PORT); - - #ifdef DEBUG - printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n", cr_data); - #endif +#ifdef DEBUG + printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:" + " Bit7 to 1: %d\n", cr_data); +#endif } -static void -pc87413_enable_swc(void) -{ +/* Enable SWC functions */ - unsigned int cr_data=0; +static inline void pc87413_enable_swc(void) +{ + unsigned int cr_data=0; /* Step 2: Enable SWC functions */ @@ -120,150 +103,162 @@ pc87413_enable_swc(void) outb_p(SWC_LDN, WDT_DATA_IO_PORT); outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */ - cr_data = inb (WDT_DATA_IO_PORT); + cr_data = inb(WDT_DATA_IO_PORT); cr_data |= 0x01; /* Set Bit0 to 1 */ outb_p(0x30, WDT_INDEX_IO_PORT); outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */ - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n"); - #endif +#endif } -static unsigned int -pc87413_get_swc_base(void) +/* Read SWC I/O base address */ + +static inline unsigned int pc87413_get_swc_base(void) { - unsigned int swc_base_addr = 0; - unsigned char addr_l, addr_h = 0; + unsigned int swc_base_addr = 0; + unsigned char addr_l, addr_h = 0; /* Step 3: Read SWC I/O Base Address */ outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */ - addr_h = inb (WDT_DATA_IO_PORT); + addr_h = inb(WDT_DATA_IO_PORT); outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */ - addr_l = inb (WDT_DATA_IO_PORT); - + addr_l = inb(WDT_DATA_IO_PORT); swc_base_addr = (addr_h << 8) + addr_l; - #ifdef DEBUG - printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d, res %d\n", addr_l, addr_h, swc_base_addr); - #endif +#ifdef DEBUG + printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d," + " res %d\n", addr_l, addr_h, swc_base_addr); +#endif return swc_base_addr; } -static void -pc87413_swc_bank3(unsigned int swc_base_addr) +/* Select Bank 3 of SWC */ + +static inline void pc87413_swc_bank3(unsigned int swc_base_addr) { /* Step 4: Select Bank3 of SWC */ - outb_p (inb (swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); + outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "Select Bank3 of SWC\n"); - #endif - +#endif } -static void -pc87413_programm_wdto (unsigned int swc_base_addr, char pc87413_time) +/* Set watchdog timeout to x minutes */ + +static inline void pc87413_programm_wdto(unsigned int swc_base_addr, + char pc87413_time) { /* Step 5: Programm WDTO, Twd. */ - outb_p (pc87413_time, swc_base_addr + WDTO); + outb_p(pc87413_time, swc_base_addr + WDTO); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time); - #endif +#endif } -static void -pc87413_enable_wden (unsigned int swc_base_addr) +/* Enable WDEN */ + +static inline void pc87413_enable_wden(unsigned int swc_base_addr) { /* Step 6: Enable WDEN */ outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "Enable WDEN\n"); - #endif +#endif } -static void -pc87413_enable_sw_wd_tren (unsigned int swc_base_addr) +/* Enable SW_WD_TREN */ +static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) { /* Enable SW_WD_TREN */ outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "Enable SW_WD_TREN\n"); - #endif +#endif } -static void -pc87413_disable_sw_wd_tren (unsigned int swc_base_addr) +/* Disable SW_WD_TREN */ + +static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) { /* Disable SW_WD_TREN */ outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n"); - #endif +#endif } +/* Enable SW_WD_TRG */ -static void -pc87413_enable_sw_wd_trg (unsigned int swc_base_addr) +static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) { - /* Enable SW_WD_TRG */ outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n"); - #endif +#endif } -static void -pc87413_disable_sw_wd_trg (unsigned int swc_base_addr) -{ +/* Disable SW_WD_TRG */ +static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) +{ /* Disable SW_WD_TRG */ outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL); - #ifdef DEBUG +#ifdef DEBUG printk(KERN_INFO DPFX "Disable SW_WD_TRG\n"); - #endif +#endif } +/* -- Higher level functions ------------------------------------*/ +/* Enable the watchdog */ -static void -pc87413_disable(void) +static void pc87413_enable(void) { - unsigned int swc_base_addr; + unsigned int swc_base_addr; + + spin_lock(&io_lock); pc87413_select_wdt_out(); pc87413_enable_swc(); swc_base_addr = pc87413_get_swc_base(); pc87413_swc_bank3(swc_base_addr); - pc87413_disable_sw_wd_tren(swc_base_addr); - pc87413_disable_sw_wd_trg(swc_base_addr); - pc87413_programm_wdto(swc_base_addr, 0); + pc87413_programm_wdto(swc_base_addr, timeout); + pc87413_enable_wden(swc_base_addr); + pc87413_enable_sw_wd_tren(swc_base_addr); + pc87413_enable_sw_wd_trg(swc_base_addr); + + spin_unlock(&io_lock); } +/* Disable the watchdog */ -static void -pc87413_refresh(char pc87413_time) +static void pc87413_disable(void) { - unsigned int swc_base_addr; + unsigned int swc_base_addr; + + spin_lock(&io_lock); pc87413_select_wdt_out(); pc87413_enable_swc(); @@ -271,102 +266,144 @@ pc87413_refresh(char pc87413_time) pc87413_swc_bank3(swc_base_addr); pc87413_disable_sw_wd_tren(swc_base_addr); pc87413_disable_sw_wd_trg(swc_base_addr); - pc87413_programm_wdto(swc_base_addr, pc87413_time); - pc87413_enable_wden(swc_base_addr); - pc87413_enable_sw_wd_tren(swc_base_addr); - pc87413_enable_sw_wd_trg(swc_base_addr); + pc87413_programm_wdto(swc_base_addr, 0); + + spin_unlock(&io_lock); } +/* Refresh the watchdog */ -static void -pc87413_enable(char pc87413_time) +static void pc87413_refresh(void) { - unsigned int swc_base_addr; + unsigned int swc_base_addr; + + spin_lock(&io_lock); pc87413_select_wdt_out(); pc87413_enable_swc(); swc_base_addr = pc87413_get_swc_base(); pc87413_swc_bank3(swc_base_addr); - pc87413_programm_wdto(swc_base_addr, pc87413_time); + pc87413_disable_sw_wd_tren(swc_base_addr); + pc87413_disable_sw_wd_trg(swc_base_addr); + pc87413_programm_wdto(swc_base_addr, timeout); pc87413_enable_wden(swc_base_addr); pc87413_enable_sw_wd_tren(swc_base_addr); pc87413_enable_sw_wd_trg(swc_base_addr); + spin_unlock(&io_lock); } +/* -- File operations -------------------------------------------*/ + +/** + * pc87413_open: + * @inode: inode of device + * @file: file handle to device + * + */ + +static int pc87413_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + + if (test_and_set_bit(0, &timer_enabled)) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); -/******************************************* - * Kernel methods. - *******************************************/ + /* Reload and activate timer */ + pc87413_refresh(); + printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to" + " %d minute(s).\n", timeout); + + return nonseekable_open(inode, file); +} /** - * pc87413_status: - * - * Extract the status information from a WDT watchdog device. There are - * several board variants so we have to know which bits are valid. Some - * bits default to one and some to zero in order to be maximally painful. + * pc87413_release: + * @inode: inode to board + * @file: file handle to board * - * we then map the bits onto the status ioctl flags. + * The watchdog has a configurable API. There is a religious dispute + * between people who want their watchdog to be able to shut down and + * those who want to be sure if the watchdog manager dies the machine + * reboots. In the former case we disable the counters, in the latter + * case you have to open it again very soon. */ -static int pc87413_status(void) +static int pc87413_release(struct inode *inode, struct file *file) { - /* Not supported */ + /* Shut off the timer. */ + + if (expect_close == 42) { + pc87413_disable(); + printk(KERN_INFO MODNAME "Watchdog disabled," + " sleeping again...\n"); + } else { + printk(KERN_CRIT MODNAME "Unexpected close, not stopping" + " watchdog!\n"); + pc87413_refresh(); + } + + clear_bit(0, &timer_enabled); + expect_close = 0; - return 1; + return 0; } -static long long pc87413_llseek(struct file *file, long long offset, int origin) +/** + * pc87413_status: + * + * return, if the watchdog is enabled (timeout is set...) + */ + + +static int pc87413_status(void) { - return -ESPIPE; + return 1; /* currently not supported */ } /** * pc87413_write: * @file: file handle to the watchdog - * @buf: buffer to write (unused as data does not matter here - * @count: count of bytes + * @data: data buffer to write + * @len: length in bytes * @ppos: pointer to the position to write. No seeks allowed * * A write to a watchdog device is defined as a keepalive signal. Any * write of data will do, as we we don't define content meaning. */ -static ssize_t -pc87413_write (struct file *file, const char __user *buf, size_t count, loff_t *ppos) +static ssize_t pc87413_write(struct file *file, const char __user *data, + size_t len, loff_t *ppos) { - if (count) { - pc87413_refresh (WD_TIMEOUT); - #ifdef DEBUG - printk(KERN_INFO DPFX "Write\n"); - #endif + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* reset expect flag */ + expect_close = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + pc87413_refresh(); } - return count; -} - -/* - * Read reports the temperature in degrees Fahrenheit. - */ -static ssize_t -pc87413_read(struct file *file, char *buf, size_t count, loff_t *ptr) -{ - -// char timeout; -// -// outb_p(0x08, WDT_EFER); /* Select locical device 8 */ -// outb_p(0x0F6, WDT_EFER); /* Select CRF6 */ -// timeout = inb(WDT_EFDR); /* Read Timeout counter from CRF6 */ - - -// if(copy_to_user(buf,&timeout,1)) -// return -EFAULT; - return 1; - - + return len; } - /** +/** * pc87413_ioctl: * @inode: inode of the device * @file: file handle to the device @@ -378,103 +415,92 @@ pc87413_read(struct file *file, char *buf, size_t count, loff_t *ptr) * querying capabilities and current status. */ -static int -pc87413_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static int pc87413_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - static struct watchdog_info ident= - { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, - .firmware_version = 1, - .identity = "pc87413(HF/F)" + int new_timeout; + + union { + struct watchdog_info __user *ident; + int __user *i; + } uarg; + + static struct watchdog_info ident = { + .options = WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = "PC87413(HF/F) watchdog" }; - ident.options=1; /* Mask down to the card we have */ + uarg.i = (int __user *)arg; - switch(cmd) - { + switch(cmd) { default: - return -ENOIOCTLCMD; + return -ENOTTY; + case WDIOC_GETSUPPORT: - return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; + return copy_to_user(uarg.ident, &ident, + sizeof(ident)) ? -EFAULT : 0; + case WDIOC_GETSTATUS: - return put_user(pc87413_status(),(int *)arg); + return put_user(pc87413_status(), uarg.i); + case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); + return put_user(0, uarg.i); + case WDIOC_KEEPALIVE: - pc87413_refresh(WD_TIMEOUT); - #ifdef DEBUG - printk(KERN_INFO DPFX "keepalive\n"); - #endif + pc87413_refresh(); +#ifdef DEBUG + printk(KERN_INFO DPFX "keepalive\n"); +#endif return 0; - } -} -/** - * pc87413_open: - * @inode: inode of device - * @file: file handle to device - * - * One of our two misc devices has been opened. The watchdog device is - * single open and on opening we load the counters. Counter zero is a - * 100Hz cascade, into counter 1 which downcounts to reboot. When the - * counter triggers counter 2 downcounts the length of the reset pulse - * which set set to be as long as possible. - */ + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, uarg.i)) + return -EFAULT; -static int -pc87413_open(struct inode *inode, struct file *file) -{ - switch(MINOR(inode->i_rdev)) - { - case WATCHDOG_MINOR: - if(pc87413_is_open) - return -EBUSY; - /* - * Activate - */ - - pc87413_is_open=1; - pc87413_refresh(WD_TIMEOUT); - #ifdef DEBUG - printk(KERN_INFO DPFX "Open\n"); - #endif - return 0; - case TEMP_MINOR: - return 0; - default: - return -ENODEV; - } -} + // the API states this is given in secs + new_timeout /= 60; -/** - * pc87413_close: - * @inode: inode to board - * @file: file handle to board - * - * The watchdog has a configurable API. There is a religious dispute - * between people who want their watchdog to be able to shut down and - * those who want to be sure if the watchdog manager dies the machine - * reboots. In the former case we disable the counters, in the latter - * case you have to open it again very soon. - */ + if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) + return -EINVAL; -static int -pc87413_release(struct inode *inode, struct file *file) -{ - if(MINOR(inode->i_rdev)==WATCHDOG_MINOR) - { -#ifndef CONFIG_WATCHDOG_NOWAYOUT - pc87413_disable(); -#endif - pc87413_is_open=0; - #ifdef DEBUG - printk(KERN_INFO DPFX "Release\n"); - #endif + timeout = new_timeout; + pc87413_refresh(); + + // fall through and return the new timeout... + + case WDIOC_GETTIMEOUT: + + new_timeout = timeout * 60; + + return put_user(new_timeout, uarg.i); + + case WDIOC_SETOPTIONS: + { + int options, retval = -EINVAL; + + if (get_user(options, uarg.i)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) { + pc87413_disable(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) { + pc87413_enable(); + retval = 0; + } + + return retval; + } } - return 0; } +/* -- Notifier funtions -----------------------------------------*/ + /** * notify_sys: * @this: our notifier block @@ -487,11 +513,11 @@ pc87413_release(struct inode *inode, struct file *file) * trust me - if it happens it does suck. */ -static int -pc87413_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) +static int pc87413_notify_sys(struct notifier_block *this, + unsigned long code, + void *unused) { - if(code==SYS_DOWN || code==SYS_HALT) + if (code == SYS_DOWN || code == SYS_HALT) { /* Turn the card off */ pc87413_disable(); @@ -499,112 +525,112 @@ pc87413_notify_sys(struct notifier_block *this, unsigned long code, return NOTIFY_DONE; } - -/***************************************************** - * Kernel Interfaces - *****************************************************/ - +/* -- Module's structures ---------------------------------------*/ static struct file_operations pc87413_fops = { .owner = THIS_MODULE, - .llseek = pc87413_llseek, - .read = pc87413_read, + .llseek = no_llseek, .write = pc87413_write, .ioctl = pc87413_ioctl, .open = pc87413_open, .release = pc87413_release, }; -static struct miscdevice pc87413_miscdev= +static struct notifier_block pc87413_notifier = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &pc87413_fops + .notifier_call = pc87413_notify_sys, }; -/* - * The WDT card needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block pc87413_notifier= +static struct miscdevice pc87413_miscdev= { - pc87413_notify_sys, - NULL, - 0 + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &pc87413_fops }; +/* -- Module init functions -------------------------------------*/ /** - * pc87413_exit: - * - * Unload the watchdog. You cannot do this with any file handles open. - * If your watchdog is set to continue ticking on close and you unload - * it, well it keeps ticking. We won't get the interrupt but the board - * will not touch PC memory so all is fine. You just have to load a new - * module in 60 seconds or reboot. - */ - -static void -pc87413_exit(void) -{ - pc87413_disable(); - misc_deregister(&pc87413_miscdev); - unregister_reboot_notifier(&pc87413_notifier); - /* release_region(io,2); */ -} - - -/** - * pc87413_init: + * pc87413_init: module's "constructor" * * Set up the WDT watchdog board. All we have to do is grab the * resources we require and bitch if anyone beat us to them. * The open() function will actually kick the board off. */ -static int -pc87413_init(void) +static int __init pc87413_init(void) { int ret; - printk(KERN_INFO PFX "Version 1.00 at io 0x%X\n", WDT_INDEX_IO_PORT); + spin_lock_init(&io_lock); + printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT); /* request_region(io, 2, "pc87413"); */ - ret = register_reboot_notifier(&pc87413_notifier); if (ret != 0) { - printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", - ret); + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); } - - ret = misc_register(&pc87413_miscdev); if (ret != 0) { - printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", - WATCHDOG_MINOR, ret); + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); unregister_reboot_notifier(&pc87413_notifier); return ret; } - printk (KERN_INFO PFX "initialized. timeout=%d min \n", timeout); + printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout); - - pc87413_enable(WD_TIMEOUT); + pc87413_enable(); return 0; } +/** + * pc87413_exit: module's "destructor" + * + * Unload the watchdog. You cannot do this with any file handles open. + * If your watchdog is set to continue ticking on close and you unload + * it, well it keeps ticking. We won't get the interrupt but the board + * will not touch PC memory so all is fine. You just have to load a new + * module in 60 seconds or reboot. + */ + +static void __exit pc87413_exit(void) +{ + /* Stop the timer before we leave */ + if (!nowayout) + { + pc87413_disable(); + printk(KERN_INFO MODNAME "Watchdog disabled.\n"); + } + + misc_deregister(&pc87413_miscdev); + unregister_reboot_notifier(&pc87413_notifier); + /* release_region(io,2); */ + + printk(MODNAME " watchdog component driver removed.\n"); +} module_init(pc87413_init); module_exit(pc87413_exit); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Marcus Junker , Sven Anders "); +MODULE_AUTHOR("Sven Anders , Marcus Junker ,"); MODULE_DESCRIPTION("PC87413 WDT driver"); +MODULE_LICENSE("GPL"); + MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +module_param(io, int, 0); +MODULE_PARM_DESC(wdt_io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); + +module_param(timeout, int, 0); +MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ")."); + +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); + -- cgit v1.2.3 From 0835caa2bf1933d5f41fd98e469107f4c00d547f Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Mon, 23 Oct 2006 18:21:52 +0200 Subject: [WATCHDOG] NS pc87413-wdt Watchdog driver - fixes Some small fixes: * the status should return 0 and not 1 (1 means: * wdt_io is not a module-param, io is. Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/pc87413_wdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index 4d5612146cde..bd7727ba1ad9 100644 --- a/drivers/char/watchdog/pc87413_wdt.c +++ b/drivers/char/watchdog/pc87413_wdt.c @@ -362,7 +362,7 @@ static int pc87413_release(struct inode *inode, struct file *file) static int pc87413_status(void) { - return 1; /* currently not supported */ + return 0; /* currently not supported */ } /** @@ -626,7 +626,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(io, int, 0); -MODULE_PARM_DESC(wdt_io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); +MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); module_param(timeout, int, 0); MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ")."); -- cgit v1.2.3 From 0c0e4668e0e65dd1404e8cf066d147235f95561d Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 23 Oct 2006 14:25:30 -0700 Subject: Revert unintentional and bogus change to drivers/pci/quirks.c In commit 4e8a5201506423e0241202de1349422af4260296 ("[PKT_SCHED] netem: Orphan SKB when adding to queue.") Davem mistakenly also included a temporary diff in his tree that disabled the pci_fixup_video VGA quirk, which broke sparc64. This reverts that part of the commit. Sayeth Davem: "Greg KH has a patch coming to you soon which will move that VGA code back into x86/x86_64/IA64 specific areas and will fix the sparc64 problem properly." Special thanks to Claudio Martins for noticing the error in the first place. Cc: Claudio Martins Cc: David Miller Signed-off-by: Linus Torvalds --- drivers/pci/quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index ecf8e4d6b9da..e8a7f1b1b2bc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1634,7 +1634,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1 * is marked here since the boot video device will be the only enabled * video device at this point. */ -#if 0 + static void __devinit fixup_video(struct pci_dev *pdev) { struct pci_dev *bridge; @@ -1663,7 +1663,7 @@ static void __devinit fixup_video(struct pci_dev *pdev) } } DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); -#endif + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { -- cgit v1.2.3 From a1aa28970316d7fb606321d5ab7fb3873641ab54 Mon Sep 17 00:00:00 2001 From: Roland Scheidegger Date: Tue, 24 Oct 2006 21:45:00 +1000 Subject: drm: radeon: only allow specific type-3 packetss through verifier only allow specific type-3 packets to pass the verifier instead of all for r100/r200 as others might be unsafe (r300 already does this), and add checking for these we need but aren't safe. Check the RADEON_CP_INDX_BUFFER packet on both r200 and r300 as it isn't safe neither. Signed-off-by: Dave Airlie --- drivers/char/drm/r300_cmdbuf.c | 33 +++++++++++- drivers/char/drm/radeon_state.c | 109 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 138 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 26bdf2ca59d7..d14477ba3679 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -538,6 +538,36 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, return 0; } +static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) +{ + u32 *cmd = (u32 *) cmdbuf->buf; + int count, ret; + RING_LOCALS; + + count=(cmd[0]>>16) & 0x3fff; + + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return DRM_ERR(EINVAL); + } + ret = r300_check_offset(dev_priv, cmd[2]); + if (ret) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + return DRM_ERR(EINVAL); + } + + BEGIN_RING(count+2); + OUT_RING(cmd[0]); + OUT_RING_TABLE((int *)(cmdbuf->buf + 4), count + 1); + ADVANCE_RING(); + + cmdbuf->buf += (count+2)*4; + cmdbuf->bufsz -= (count+2)*4; + + return 0; +} + static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { @@ -578,10 +608,11 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, case RADEON_CNTL_BITBLT_MULTI: return r300_emit_bitblt_multi(dev_priv, cmdbuf); + case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ + return r300_emit_indx_buffer(dev_priv, cmdbuf); case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ - case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index feac5f005d47..6e04fdd732ac 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -275,6 +275,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * unsigned int *cmdsz) { u32 *cmd = (u32 *) cmdbuf->buf; + u32 offset, narrays; + int count, i, k; *cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16); @@ -288,10 +290,106 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * return DRM_ERR(EINVAL); } - /* Check client state and fix it up if necessary */ - if (cmd[0] & 0x8000) { /* MSB of opcode: next DWORD GUI_CNTL */ - u32 offset; + switch(cmd[0] & 0xff00) { + /* XXX Are there old drivers needing other packets? */ + case RADEON_3D_DRAW_IMMD: + case RADEON_3D_DRAW_VBUF: + case RADEON_3D_DRAW_INDX: + case RADEON_WAIT_FOR_IDLE: + case RADEON_CP_NOP: + case RADEON_3D_CLEAR_ZMASK: +/* case RADEON_CP_NEXT_CHAR: + case RADEON_CP_PLY_NEXTSCAN: + case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ + /* these packets are safe */ + break; + + case RADEON_CP_3D_DRAW_IMMD_2: + case RADEON_CP_3D_DRAW_VBUF_2: + case RADEON_CP_3D_DRAW_INDX_2: + case RADEON_3D_CLEAR_HIZ: + /* safe but r200 only */ + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_3D_LOAD_VBPNTR: + count = (cmd[0] >> 16) & 0x3fff; + + if (count > 18) { /* 12 arrays max */ + DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", + count); + return DRM_ERR(EINVAL); + } + + /* carefully check packet contents */ + narrays = cmd[1] & ~0xc000; + k = 0; + i = 2; + while ((k < narrays) && (i < (count + 2))) { + i++; /* skip attribute field */ + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return DRM_ERR(EINVAL); + } + k++; + i++; + if (k == narrays) + break; + /* have one more to process, they come in pairs */ + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + DRM_ERROR + ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", + k, i); + return DRM_ERR(EINVAL); + } + k++; + i++; + } + /* do the counts match what we expect ? */ + if ((k != narrays) || (i != (count + 2))) { + DRM_ERROR + ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", + k, i, narrays, count + 1); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_3D_RNDR_GEN_INDX_PRIM: + if (dev_priv->microcode_version != UCODE_R100) { + DRM_ERROR("Invalid 3d packet for r200-class chip\n"); + return DRM_ERR(EINVAL); + } + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { + DRM_ERROR("Invalid rndr_gen_indx offset\n"); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CP_INDX_BUFFER: + if (dev_priv->microcode_version != UCODE_R200) { + DRM_ERROR("Invalid 3d packet for r100-class chip\n"); + return DRM_ERR(EINVAL); + } + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return DRM_ERR(EINVAL); + } + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + return DRM_ERR(EINVAL); + } + break; + + case RADEON_CNTL_HOSTDATA_BLT: + case RADEON_CNTL_PAINT_MULTI: + case RADEON_CNTL_BITBLT_MULTI: + /* MSB of opcode: next DWORD GUI_CNTL */ if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[2] << 10; @@ -313,6 +411,11 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * } cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; } + break; + + default: + DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); + return DRM_ERR(EINVAL); } return 0; -- cgit v1.2.3 From 10eee0fe9114694401c7ae154e8cfb2ab2f59c10 Mon Sep 17 00:00:00 2001 From: Michael Karcher Date: Tue, 24 Oct 2006 21:46:55 +1000 Subject: drm: savage: dev->agp_buffer_map is not initialized for AGP DMA on savages fd.o bug 8662 Signed-off-by: Dave Airlie --- drivers/char/drm/savage_bci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 59c7520bf9a2..a9a84f88df5e 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c @@ -728,6 +728,7 @@ static int savage_do_init_bci(drm_device_t * dev, drm_savage_init_t * init) dev_priv->status = NULL; } if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { + dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { -- cgit v1.2.3 From 958de71b1ab01c20c1b385035235746c9227b24f Mon Sep 17 00:00:00 2001 From: Tilman Sauerbeck Date: Tue, 24 Oct 2006 21:52:23 +1000 Subject: drm: mga: set dev_priv_size fd.o bug 1746 Signed-off-by: Dave Airlie --- drivers/char/drm/mga_drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index e30f556b79f1..be49dbb9ec3f 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c @@ -47,6 +47,7 @@ static struct drm_driver driver = { DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, + .dev_priv_size = sizeof(drm_mga_buf_priv_t), .load = mga_driver_load, .unload = mga_driver_unload, .lastclose = mga_driver_lastclose, -- cgit v1.2.3 From f586fbd0ef273a80d88a07f911d9f2f2a8ac1679 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 20 Oct 2006 00:56:28 +0100 Subject: [ARM] 3897/1: corgi_bl fix module compiling Fix module compiling: WARNING: drivers/video/backlight/corgi_bl.o - Section mismatch: reference to .init.text: from .data between '$d' (at offset 0x0) and 'bl_mutex' Cc: Richard Purdie Signed-off-by: Anton Vorontsov Signed-off-by: Russell King --- drivers/video/backlight/corgi_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 2ebbfd95145f..6697778650d2 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -111,7 +111,7 @@ static struct backlight_properties corgibl_data = { .update_status = corgibl_set_intensity, }; -static int __init corgibl_probe(struct platform_device *pdev) +static int corgibl_probe(struct platform_device *pdev) { struct corgibl_machinfo *machinfo = pdev->dev.platform_data; -- cgit v1.2.3 From 62c877b9b7c463aa16ffbc9a322cb094fdb5827a Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 20 Oct 2006 00:58:49 +0100 Subject: [ARM] 3898/1: corgi_bl fix module loading Fix module loading: corgi_bl: module license 'GPLv2' taints kernel. corgi_bl: Unknown symbol platform_driver_unregister corgi_bl: Unknown symbol __symbol_get corgi_bl: Unknown symbol platform_driver_register Cc: Richard Purdie Signed-off-by: pHilipp Zabel Signed-off-by: Anton Vorontsov Signed-off-by: Russell King --- drivers/video/backlight/corgi_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c index 6697778650d2..d07ecb53c68b 100644 --- a/drivers/video/backlight/corgi_bl.c +++ b/drivers/video/backlight/corgi_bl.c @@ -166,4 +166,4 @@ module_exit(corgibl_exit); MODULE_AUTHOR("Richard Purdie "); MODULE_DESCRIPTION("Corgi Backlight Driver"); -MODULE_LICENSE("GPLv2"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4ccc12aeece8ab14ad96461c4db269aea080715d Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 24 Oct 2006 14:45:53 -0700 Subject: e1000: FIX: don't poke at manageability registers for incompatible adapters The MANC register should not be read for PCI-E adapters at all, as well as 82543 and older where 82543 would master abort when this register was accessed. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_ethtool.c | 3 ++- drivers/net/e1000/e1000_main.c | 21 ++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 773821e4cf57..71fb27880f65 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -461,7 +461,8 @@ e1000_get_regs(struct net_device *netdev, regs_buff[24] = (uint32_t)phy_data; /* phy local receiver status */ regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ if (hw->mac_type >= e1000_82540 && - hw->media_type == e1000_media_type_copper) { + hw->mac_type < e1000_82571 && + hw->media_type == e1000_media_type_copper) { regs_buff[26] = E1000_READ_REG(hw, MANC); } } diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fa849831d099..fb83082c4f75 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -699,7 +699,10 @@ e1000_reset(struct e1000_adapter *adapter) phy_data); } - if ((adapter->en_mng_pt) && (adapter->hw.mac_type < e1000_82571)) { + if ((adapter->en_mng_pt) && + (adapter->hw.mac_type >= e1000_82540) && + (adapter->hw.mac_type < e1000_82571) && + (adapter->hw.media_type == e1000_media_type_copper)) { manc = E1000_READ_REG(&adapter->hw, MANC); manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST); E1000_WRITE_REG(&adapter->hw, MANC, manc); @@ -1076,8 +1079,9 @@ e1000_remove(struct pci_dev *pdev) flush_scheduled_work(); - if (adapter->hw.mac_type < e1000_82571 && - adapter->hw.media_type == e1000_media_type_copper) { + if (adapter->hw.mac_type >= e1000_82540 && + adapter->hw.mac_type < e1000_82571 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if (manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -4773,8 +4777,9 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) pci_enable_wake(pdev, PCI_D3cold, 0); } - if (adapter->hw.mac_type < e1000_82571 && - adapter->hw.media_type == e1000_media_type_copper) { + if (adapter->hw.mac_type >= e1000_82540 && + adapter->hw.mac_type < e1000_82571 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); if (manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; @@ -4825,8 +4830,9 @@ e1000_resume(struct pci_dev *pdev) netif_device_attach(netdev); - if (adapter->hw.mac_type < e1000_82571 && - adapter->hw.media_type == e1000_media_type_copper) { + if (adapter->hw.mac_type >= e1000_82540 && + adapter->hw.mac_type < e1000_82571 && + adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(&adapter->hw, MANC, manc); @@ -4944,6 +4950,7 @@ static void e1000_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); if (adapter->hw.mac_type >= e1000_82540 && + adapter->hw.mac_type < e1000_82571 && adapter->hw.media_type == e1000_media_type_copper) { manc = E1000_READ_REG(&adapter->hw, MANC); manc &= ~(E1000_MANC_ARP_EN); -- cgit v1.2.3 From dc1f71f6b30c258704885cd488582eb3d68b3e8e Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 24 Oct 2006 14:45:55 -0700 Subject: e1000: FIX: 82542 doesn't support WoL Exclude 82542 when setting up WoL. This card does not do WoL at all. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_ethtool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 71fb27880f65..c564adbd669b 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1691,6 +1691,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol int retval = 1; /* fail by default */ switch (hw->device_id) { + case E1000_DEV_ID_82542: case E1000_DEV_ID_82543GC_FIBER: case E1000_DEV_ID_82543GC_COPPER: case E1000_DEV_ID_82544EI_FIBER: -- cgit v1.2.3 From 225a5dbd68f5271b7425f2f783ae64a1f6863b51 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Tue, 24 Oct 2006 14:45:58 -0700 Subject: e1000: FIX: fix wrong txdctl threshold bitmasks Threshold bitmasks for prefetch, host and writeback were clearing bits that they were not supposed to. The leftmost 2 bits in the byte for each threshold are reserved. Signed-off-by: Bruce Allan Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_hw.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 112447fd8bf2..449a60303e07 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1961,9 +1961,9 @@ struct e1000_hw { #define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ /* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x000000FF /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x0000FF00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x00FF0000 /* TXDCTL Writeback Threshold */ +#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ +#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ +#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ #define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ -- cgit v1.2.3 From e64d7d02090e475cfd7efbc830146d0c6dd579bc Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 24 Oct 2006 14:46:01 -0700 Subject: e1000: FIX: Disable Packet Split for non jumbo frames Allocations using alloc_page are taking too long for normal MTU, so use LPE only for jumbo frames. Signed-off-bu: Jesse Brandeburg Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fb83082c4f75..7362e1240178 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1808,9 +1808,11 @@ e1000_setup_rctl(struct e1000_adapter *adapter) * followed by the page buffers. Therefore, skb->data is * sized to hold the largest protocol header. */ + /* allocations using alloc_page take too long for regular MTU + * so only enable packet split for jumbo frames */ pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if ((adapter->hw.mac_type > e1000_82547_rev_2) && (pages <= 3) && - PAGE_SIZE <= 16384) + if ((adapter->hw.mac_type >= e1000_82571) && (pages <= 3) && + PAGE_SIZE <= 16384 && (rctl & E1000_RCTL_LPE)) adapter->rx_ps_pages = pages; else adapter->rx_ps_pages = 0; -- cgit v1.2.3 From 032fe6e9e253ebb37a0df0893844674dea9210fd Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 24 Oct 2006 14:46:04 -0700 Subject: e1000: FIX: Don't limit descriptor size to 4kb for PCI-E adapters 82571 and newer chispets don't need to limit desc. length to 4kb and can handle 8kb sizes. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7362e1240178..e75909ee6d85 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2992,6 +2992,11 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } + /* 82571 and newer doesn't need the workaround that limited descriptor + * length to 4kB */ + if (adapter->hw.mac_type >= e1000_82571) + max_per_txd = 8192; + #ifdef NETIF_F_TSO mss = skb_shinfo(skb)->gso_size; /* The controller does a simple calculation to -- cgit v1.2.3 From d2a1e2131aee7b3feb815636dc7917a96e49fd8e Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 24 Oct 2006 14:46:06 -0700 Subject: e1000: FIX: move length adjustment due to crc stripping disabled. Move the length (rx_bytes counter) adjustment of 4 bytes down to after the TBI_ACCEPT workaround. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index e75909ee6d85..66ed920df406 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3786,9 +3786,6 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, length = le16_to_cpu(rx_desc->length); - /* adjust length to remove Ethernet CRC */ - length -= 4; - if (unlikely(!(status & E1000_RXD_STAT_EOP))) { /* All receives must fit into a single buffer */ E1000_DBG("%s: Receive packet consumed multiple" @@ -3816,6 +3813,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, } } + /* adjust length to remove Ethernet CRC, this must be + * done after the TBI_ACCEPT workaround above */ + length -= 4; + /* code added for copybreak, this should improve * performance for small packets with large amounts * of reassembly being done in the stack */ -- cgit v1.2.3 From ff1e55b078676d3c449ace6b99d95c0e22c905d6 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 24 Oct 2006 14:46:09 -0700 Subject: e1000: Increment version to 7.2.9-k4 Significant fixes -> increment driver version. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 66ed920df406..8d04752777a8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -35,7 +35,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "7.2.9-k2"DRIVERNAPI +#define DRV_VERSION "7.2.9-k4"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; -- cgit v1.2.3 From 824545e7031541f83245d254caca012bf6bdc6cd Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 24 Oct 2006 14:49:44 -0700 Subject: e100: account for closed interface when shutting down Account for the interface being closed before disabling polling on a device, to fix shutdown on some systems that explcitly close the netdevice before calling shutdown. Signed-off-by: Auke Kok --- drivers/net/e100.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index a3a08a5dd185..19ab3441269c 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -2719,7 +2719,10 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state) struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - netif_poll_disable(nic->netdev); +#ifdef CONFIG_E100_NAPI + if (netif_running(netdev)) + netif_poll_disable(nic->netdev); +#endif del_timer_sync(&nic->watchdog); netif_carrier_off(nic->netdev); @@ -2763,7 +2766,10 @@ static void e100_shutdown(struct pci_dev *pdev) struct net_device *netdev = pci_get_drvdata(pdev); struct nic *nic = netdev_priv(netdev); - netif_poll_disable(nic->netdev); +#ifdef CONFIG_E100_NAPI + if (netif_running(netdev)) + netif_poll_disable(nic->netdev); +#endif del_timer_sync(&nic->watchdog); netif_carrier_off(nic->netdev); -- cgit v1.2.3 From 977a415f2b70b5693aaa23b1a16ad57ea20a1dce Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 24 Oct 2006 16:16:39 -0700 Subject: [ATM] horizon: read_bia() needs to be __devinit Thanks to Randy Dunlap. Signed-off-by: David S. Miller --- drivers/atm/horizon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index 44268cba5a5a..4dc10105d610 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -1789,7 +1789,7 @@ static inline void CLOCK_IT (const hrz_dev *dev, u32 ctrl) WRITE_IT_WAIT(dev, ctrl | SEEPROM_SK); } -static u16 __init read_bia (const hrz_dev * dev, u16 addr) +static u16 __devinit read_bia (const hrz_dev * dev, u16 addr) { u32 ctrl = rd_regl (dev, CONTROL_0_REG); -- cgit v1.2.3 From aa6c2e62bbe7a20ccc85906f75bc63465d899227 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Oct 2006 11:16:29 +0100 Subject: [PATCH] IOC4 should depend on PCI Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/misc/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index b6c045dc97b4..00db31c314e0 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -30,6 +30,7 @@ config IBM_ASM config SGI_IOC4 tristate "SGI IOC4 Base IO support" + depends on PCI ---help--- This option enables basic support for the IOC4 chip on certain SGI IO controller cards (IO9, IO10, and PCI-RT). This option -- cgit v1.2.3 From 016002312d50004908a79df37174b336e3682e18 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Oct 2006 11:17:37 +0100 Subject: [PATCH] missing include of dma-mapping.h Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h index ea16078cfe98..d1105e569a41 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From 2099c99e3b24f86b131566aa9854249189ae9ea2 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Oct 2006 11:17:06 +0100 Subject: [PATCH] missing includes of io.h Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- drivers/misc/ioc4.c | 1 + drivers/mmc/tifm_sd.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 1c3c14a3839c..79354bbbbd6a 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -32,6 +32,7 @@ #include #include #include +#include /*************** * Definitions * diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index 2bacff60913d..0fdc55b08a6d 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c @@ -14,6 +14,7 @@ #include #include #include +#include #define DRIVER_NAME "tifm_sd" #define DRIVER_VERSION "0.6" -- cgit v1.2.3 From bcbaecbb9968750d4bfb2686a97e396f681f88ef Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 25 Oct 2006 16:49:36 +1000 Subject: [CRYPTO] users: Select ECB/CBC where needed CRYPTO_MANAGER is selected automatically by CONFIG_ECB and CONFIG_CBC. config CRYPTO_ECB tristate "ECB support" select CRYPTO_BLKCIPHER select CRYPTO_MANAGER I've added CONFIG_ECB to the ones you mentioned and CONFIG_CBC to gssapi. Signed-off-by: Patrick McHardy Signed-off-by: Herbert Xu --- drivers/net/Kconfig | 1 + fs/Kconfig | 2 ++ net/ieee80211/Kconfig | 2 ++ 3 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e2ed24918a58..e38846eb51fa 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2717,6 +2717,7 @@ config PPP_MPPE select CRYPTO select CRYPTO_SHA1 select CRYPTO_ARC4 + select CRYPTO_ECB ---help--- Support for the MPPE Encryption protocol, as employed by the Microsoft Point-to-Point Tunneling Protocol. diff --git a/fs/Kconfig b/fs/Kconfig index fee318e6f4bb..133dcc8a4150 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1777,6 +1777,7 @@ config RPCSEC_GSS_KRB5 select CRYPTO select CRYPTO_MD5 select CRYPTO_DES + select CRYPTO_CBC help Provides for secure RPC calls by means of a gss-api mechanism based on Kerberos V5. This is required for @@ -1795,6 +1796,7 @@ config RPCSEC_GSS_SPKM3 select CRYPTO_MD5 select CRYPTO_DES select CRYPTO_CAST5 + select CRYPTO_CBC help Provides for secure RPC calls by means of a gss-api mechanism based on the SPKM3 public-key mechanism. diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index f7e84e9d13ad..a64be6cdf078 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -32,6 +32,7 @@ config IEEE80211_CRYPT_WEP depends on IEEE80211 select CRYPTO select CRYPTO_ARC4 + select CRYPTO_ECB select CRC32 ---help--- Include software based cipher suites in support of IEEE @@ -58,6 +59,7 @@ config IEEE80211_CRYPT_TKIP depends on IEEE80211 && NET_RADIO select CRYPTO select CRYPTO_MICHAEL_MIC + select CRYPTO_ECB select CRC32 ---help--- Include software based cipher suites in support of IEEE 802.11i -- cgit v1.2.3 From 0d960d26c42888cf327df7faa1a8aa62bab53fa4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 18 Oct 2006 00:26:39 -0400 Subject: fix return code in error case. The other failure returns in this function are negative, so make this one do the same. Signed-off-by: Dave Jones Signed-off-by: Dave Airlie --- drivers/char/drm/savage_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index ef2581d16146..1ca1e9cb5a33 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c @@ -994,7 +994,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) if (cmdbuf.size) { kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); if (kcmd_addr == NULL) - return ENOMEM; + return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, cmdbuf.size * 8)) -- cgit v1.2.3 From 24f73c92a990ecd3d1bb846267780a264d830065 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 10 Oct 2006 14:23:37 -0700 Subject: drm: fix error returns, sysfs error handling - callers of drm_sysfs_create() and drm_sysfs_device_add() looked for errors using IS_ERR(), but the functions themselves only ever returned NULL on error. Fixed. - unwind from, and propagate sysfs errors Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/char/drm/drm_sysfs.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 51ad98c685c3..ba4b8de83cf0 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c @@ -42,13 +42,24 @@ static CLASS_ATTR(version, S_IRUGO, version_show, NULL); struct class *drm_sysfs_create(struct module *owner, char *name) { struct class *class; + int err; class = class_create(owner, name); - if (!class) - return class; + if (!class) { + err = -ENOMEM; + goto err_out; + } + + err = class_create_file(class, &class_attr_version); + if (err) + goto err_out_class; - class_create_file(class, &class_attr_version); return class; + +err_out_class: + class_destroy(class); +err_out: + return ERR_PTR(err); } /** @@ -96,20 +107,36 @@ static struct class_device_attribute class_device_attrs[] = { struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) { struct class_device *class_dev; - int i; + int i, j, err; class_dev = class_device_create(cs, NULL, MKDEV(DRM_MAJOR, head->minor), &(head->dev->pdev)->dev, "card%d", head->minor); - if (!class_dev) - return NULL; + if (!class_dev) { + err = -ENOMEM; + goto err_out; + } class_set_devdata(class_dev, head); - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_create_file(class_dev, &class_device_attrs[i]); + for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { + err = class_device_create_file(class_dev, + &class_device_attrs[i]); + if (err) + goto err_out_files; + } + return class_dev; + +err_out_files: + if (i > 0) + for (j = 0; j < i; j++) + class_device_remove_file(class_dev, + &class_device_attrs[i]); + class_device_unregister(class_dev); +err_out: + return ERR_PTR(err); } /** -- cgit v1.2.3 From 85abb3f95010b277a6efbc9b8031a7854af87e10 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Wed, 25 Oct 2006 09:55:34 -0700 Subject: drm: ioremap balanced with iounmap for drivers/char/drm ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. Tested (compilation only) to make sure the files are compiling without any warning/error due to new changes Signed-off-by: Amol Lad Signed-off-by: Dave Airlie --- drivers/char/drm/drm_bufs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 029baea33b62..6eafff13dab6 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -237,6 +237,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, list = drm_alloc(sizeof(*list), DRM_MEM_MAPS); if (!list) { + if (map->type == _DRM_REGISTERS) + drm_ioremapfree(map->handle, map->size, dev); drm_free(map, sizeof(*map), DRM_MEM_MAPS); return -EINVAL; } @@ -252,6 +254,8 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, map->offset; ret = drm_map_handle(dev, &list->hash, user_token, 0); if (ret) { + if (map->type == _DRM_REGISTERS) + drm_ioremapfree(map->handle, map->size, dev); drm_free(map, sizeof(*map), DRM_MEM_MAPS); drm_free(list, sizeof(*list), DRM_MEM_MAPS); mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From a77b8950019289611f836c8fc19f91592822efcd Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 20 Oct 2006 14:36:00 -0700 Subject: intel fb: switch to pci_get API Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/video/intelfb/intelfbhw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index eeeeff9a09eb..eae60f97e266 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -161,7 +161,7 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, return 1; /* Find the bridge device. It is always 0:0.0 */ - if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) { + if (!(bridge_dev = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)))) { ERR_MSG("cannot find bridge device\n"); return 1; } @@ -169,6 +169,8 @@ intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size, /* Get the fb aperture size and "stolen" memory amount. */ tmp = 0; pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp); + pci_dev_put(bridge_dev); + switch (pdev->device) { case PCI_DEVICE_ID_INTEL_915G: case PCI_DEVICE_ID_INTEL_915GM: -- cgit v1.2.3 From f84fcb06a1f7ab4ac0444ece82b25b0701369641 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Fri, 20 Oct 2006 14:35:59 -0700 Subject: Remove unnecessary check in drivers/video/intelfb/intelfbhw.c All callers and the function itself dereference dinfo, so we can remove the check. (coverity id #1371) Signed-off-by: Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: Dave Airlie --- drivers/video/intelfb/intelfbhw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index eae60f97e266..a95836839e1e 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -664,7 +664,7 @@ intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw) int index = dinfo->pll_index; DBG_MSG("intelfbhw_print_hw_state\n"); - if (!hw || !dinfo) + if (!hw) return; /* Read in as much of the HW state as possible. */ printk("hw state dump start\n"); -- cgit v1.2.3 From 811c93666c3f4a0e99382c24a84480b03c7262f6 Mon Sep 17 00:00:00 2001 From: Henne Date: Tue, 3 Oct 2006 19:51:59 +0200 Subject: [SCSI] Scsi_Cmnd convertion in sun3-driver Change the obsolete Scsi_Cmnd to struct scsi_cmnd in the sun3-driver. Signed-off-by: Henrik Kretzschmar Signed-off-by: James Bottomley --- drivers/scsi/sun3_NCR5380.c | 109 ++++++++++++++++++++++--------------------- drivers/scsi/sun3_scsi.c | 7 +-- drivers/scsi/sun3_scsi.h | 7 +-- drivers/scsi/sun3_scsi_vme.c | 7 +-- 4 files changed, 69 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 5ec5af8e3379..3b3f3050a877 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -266,8 +266,8 @@ static struct scsi_host_template *the_template = NULL; (struct NCR5380_hostdata *)(in)->hostdata #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) -#define NEXT(cmd) ((Scsi_Cmnd *)((cmd)->host_scribble)) -#define NEXTADDR(cmd) ((Scsi_Cmnd **)&((cmd)->host_scribble)) +#define NEXT(cmd) ((struct scsi_cmnd *)((cmd)->host_scribble)) +#define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble)) #define HOSTNO instance->host_no #define H_NO(cmd) (cmd)->device->host->host_no @@ -360,7 +360,7 @@ static void __init init_tags( void ) * conditions. */ -static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) +static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) { SETUP_HOSTDATA(cmd->device->host); @@ -384,7 +384,7 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) * untagged. */ -static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) +static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) { SETUP_HOSTDATA(cmd->device->host); @@ -416,7 +416,7 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) * unlock the LUN. */ -static void cmd_free_tag( Scsi_Cmnd *cmd ) +static void cmd_free_tag(struct scsi_cmnd *cmd) { SETUP_HOSTDATA(cmd->device->host); @@ -460,18 +460,18 @@ static void free_all_tags( void ) /* - * Function: void merge_contiguous_buffers( Scsi_Cmnd *cmd ) + * Function: void merge_contiguous_buffers(struct scsi_cmnd *cmd) * * Purpose: Try to merge several scatter-gather requests into one DMA * transfer. This is possible if the scatter buffers lie on * physical contiguous addresses. * - * Parameters: Scsi_Cmnd *cmd + * Parameters: struct scsi_cmnd *cmd * The command to work on. The first scatter buffer's data are * assumed to be already transfered into ptr/this_residual. */ -static void merge_contiguous_buffers( Scsi_Cmnd *cmd ) +static void merge_contiguous_buffers(struct scsi_cmnd *cmd) { unsigned long endaddr; #if (NDEBUG & NDEBUG_MERGING) @@ -501,15 +501,15 @@ static void merge_contiguous_buffers( Scsi_Cmnd *cmd ) } /* - * Function : void initialize_SCp(Scsi_Cmnd *cmd) + * Function : void initialize_SCp(struct scsi_cmnd *cmd) * * Purpose : initialize the saved data pointers for cmd to point to the * start of the buffer. * - * Inputs : cmd - Scsi_Cmnd structure to have pointers reset. + * Inputs : cmd - struct scsi_cmnd structure to have pointers reset. */ -static __inline__ void initialize_SCp(Scsi_Cmnd *cmd) +static __inline__ void initialize_SCp(struct scsi_cmnd *cmd) { /* * Initialize the Scsi Pointer field so that all of the commands in the @@ -753,14 +753,15 @@ static void NCR5380_print_status (struct Scsi_Host *instance) do { if (pos + strlen(fmt) + 20 /* slop */ < buffer + length) \ pos += sprintf(pos, fmt , ## args); } while(0) static -char *lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length); +char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer, + int length); -static int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **start, - off_t offset, int length, int inout) +static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, + char **start, off_t offset, int length, int inout) { char *pos = buffer; struct NCR5380_hostdata *hostdata; - Scsi_Cmnd *ptr; + struct scsi_cmnd *ptr; unsigned long flags; off_t begin = 0; #define check_offset() \ @@ -784,18 +785,19 @@ static int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **s if (!hostdata->connected) SPRINTF("scsi%d: no currently connected command\n", HOSTNO); else - pos = lprint_Scsi_Cmnd ((Scsi_Cmnd *) hostdata->connected, + pos = lprint_Scsi_Cmnd ((struct scsi_cmnd *) hostdata->connected, pos, buffer, length); SPRINTF("scsi%d: issue_queue\n", HOSTNO); check_offset(); - for (ptr = (Scsi_Cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) { + for (ptr = (struct scsi_cmnd *) hostdata->issue_queue; ptr; ptr = NEXT(ptr)) + { pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); check_offset(); } SPRINTF("scsi%d: disconnected_queue\n", HOSTNO); check_offset(); - for (ptr = (Scsi_Cmnd *) hostdata->disconnected_queue; ptr; + for (ptr = (struct scsi_cmnd *) hostdata->disconnected_queue; ptr; ptr = NEXT(ptr)) { pos = lprint_Scsi_Cmnd (ptr, pos, buffer, length); check_offset(); @@ -810,8 +812,8 @@ static int NCR5380_proc_info (struct Scsi_Host *instance, char *buffer, char **s return length; } -static char * -lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) +static char *lprint_Scsi_Cmnd(struct scsi_cmnd *cmd, char *pos, char *buffer, + int length) { int i, s; unsigned char *command; @@ -888,8 +890,8 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags) } /* - * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) + * Function : int NCR5380_queue_command (struct scsi_cmnd *cmd, + * void (*done)(struct scsi_cmnd *)) * * Purpose : enqueues a SCSI command * @@ -906,10 +908,11 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags) */ /* Only make static if a wrapper function is used */ -static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) +static int NCR5380_queue_command(struct scsi_cmnd *cmd, + void (*done)(struct scsi_cmnd *)) { SETUP_HOSTDATA(cmd->device->host); - Scsi_Cmnd *tmp; + struct scsi_cmnd *tmp; unsigned long flags; #if (NDEBUG & NDEBUG_NO_WRITE) @@ -990,7 +993,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) NEXT(cmd) = hostdata->issue_queue; hostdata->issue_queue = cmd; } else { - for (tmp = (Scsi_Cmnd *)hostdata->issue_queue; + for (tmp = (struct scsi_cmnd *)hostdata->issue_queue; NEXT(tmp); tmp = NEXT(tmp)) ; LIST(cmd, tmp); @@ -1030,7 +1033,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) static void NCR5380_main (void *bl) { - Scsi_Cmnd *tmp, *prev; + struct scsi_cmnd *tmp, *prev; struct Scsi_Host *instance = first_instance; struct NCR5380_hostdata *hostdata = HOSTDATA(instance); int done; @@ -1073,12 +1076,12 @@ static void NCR5380_main (void *bl) * for a target that's not busy. */ #if (NDEBUG & NDEBUG_LISTS) - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; + for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp)) ; if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/ #endif - for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, + for (tmp = (struct scsi_cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { #if (NDEBUG & NDEBUG_LISTS) @@ -1339,7 +1342,8 @@ static irqreturn_t NCR5380_intr (int irq, void *dev_id) } #ifdef NCR5380_STATS -static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) +static void collect_stats(struct NCR5380_hostdata *hostdata, + struct scsi_cmnd *cmd) { # ifdef NCR5380_STAT_LIMIT if (cmd->request_bufflen > NCR5380_STAT_LIMIT) @@ -1365,8 +1369,8 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) #endif /* - * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, - * int tag); + * Function : int NCR5380_select(struct Scsi_Host *instance, + * struct scsi_cmnd *cmd, int tag); * * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, * including ARBITRATION, SELECTION, and initial message out for @@ -1395,7 +1399,8 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) * cmd->result host byte set to DID_BAD_TARGET. */ -static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) +static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd, + int tag) { SETUP_HOSTDATA(instance); unsigned char tmp[3], phase; @@ -1985,7 +1990,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) #endif unsigned char *data; unsigned char phase, tmp, extended_msg[10], old_phase=0xff; - Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected; + struct scsi_cmnd *cmd = (struct scsi_cmnd *) hostdata->connected; #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; @@ -2272,7 +2277,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) local_irq_save(flags); LIST(cmd,hostdata->issue_queue); NEXT(cmd) = hostdata->issue_queue; - hostdata->issue_queue = (Scsi_Cmnd *) cmd; + hostdata->issue_queue = (struct scsi_cmnd *) cmd; local_irq_restore(flags); QU_PRINTK("scsi%d: REQUEST SENSE added to head of " "issue queue\n", H_NO(cmd)); @@ -2502,7 +2507,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * Function : void NCR5380_reselect (struct Scsi_Host *instance) * * Purpose : does reselection, initializing the instance->connected - * field to point to the Scsi_Cmnd for which the I_T_L or I_T_L_Q + * field to point to the struct scsi_cmnd for which the I_T_L or I_T_L_Q * nexus has been reestablished, * * Inputs : instance - this instance of the NCR5380. @@ -2521,7 +2526,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) unsigned char tag; #endif unsigned char msg[3]; - Scsi_Cmnd *tmp = NULL, *prev; + struct scsi_cmnd *tmp = NULL, *prev; /* unsigned long flags; */ /* @@ -2577,7 +2582,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) * just reestablished, and remove it from the disconnected queue. */ - for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; + for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) #ifdef SUPPORT_TAGS @@ -2668,11 +2673,11 @@ static void NCR5380_reselect (struct Scsi_Host *instance) /* - * Function : int NCR5380_abort (Scsi_Cmnd *cmd) + * Function : int NCR5380_abort(struct scsi_cmnd *cmd) * * Purpose : abort a command * - * Inputs : cmd - the Scsi_Cmnd to abort, code - code to set the + * Inputs : cmd - the struct scsi_cmnd to abort, code - code to set the * host byte of the result field to, if zero DID_ABORTED is * used. * @@ -2684,11 +2689,11 @@ static void NCR5380_reselect (struct Scsi_Host *instance) * called where the loop started in NCR5380_main(). */ -static int NCR5380_abort (Scsi_Cmnd *cmd) +static int NCR5380_abort(struct scsi_cmnd *cmd) { struct Scsi_Host *instance = cmd->device->host; SETUP_HOSTDATA(instance); - Scsi_Cmnd *tmp, **prev; + struct scsi_cmnd *tmp, **prev; unsigned long flags; printk(KERN_NOTICE "scsi%d: aborting command\n", HOSTNO); @@ -2753,9 +2758,9 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) * Case 2 : If the command hasn't been issued yet, we simply remove it * from the issue queue. */ - for (prev = (Scsi_Cmnd **) &(hostdata->issue_queue), - tmp = (Scsi_Cmnd *) hostdata->issue_queue; - tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) ) + for (prev = (struct scsi_cmnd **) &(hostdata->issue_queue), + tmp = (struct scsi_cmnd *) hostdata->issue_queue; + tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp)) if (cmd == tmp) { REMOVE(5, *prev, tmp, NEXT(tmp)); (*prev) = NEXT(tmp); @@ -2812,7 +2817,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) * it from the disconnected queue. */ - for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; tmp; + for (tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; tmp = NEXT(tmp)) if (cmd == tmp) { local_irq_restore(flags); @@ -2826,8 +2831,8 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) do_abort (instance); local_irq_save(flags); - for (prev = (Scsi_Cmnd **) &(hostdata->disconnected_queue), - tmp = (Scsi_Cmnd *) hostdata->disconnected_queue; + for (prev = (struct scsi_cmnd **) &(hostdata->disconnected_queue), + tmp = (struct scsi_cmnd *) hostdata->disconnected_queue; tmp; prev = NEXTADDR(tmp), tmp = NEXT(tmp) ) if (cmd == tmp) { REMOVE(5, *prev, tmp, NEXT(tmp)); @@ -2868,7 +2873,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) /* - * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd) + * Function : int NCR5380_bus_reset(struct scsi_cmnd *cmd) * * Purpose : reset the SCSI bus. * @@ -2876,13 +2881,13 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) * */ -static int NCR5380_bus_reset( Scsi_Cmnd *cmd) +static int NCR5380_bus_reset(struct scsi_cmnd *cmd) { SETUP_HOSTDATA(cmd->device->host); int i; unsigned long flags; #if 1 - Scsi_Cmnd *connected, *disconnected_queue; + struct scsi_cmnd *connected, *disconnected_queue; #endif @@ -2914,9 +2919,9 @@ static int NCR5380_bus_reset( Scsi_Cmnd *cmd) * remembered in local variables first. */ local_irq_save(flags); - connected = (Scsi_Cmnd *)hostdata->connected; + connected = (struct scsi_cmnd *)hostdata->connected; hostdata->connected = NULL; - disconnected_queue = (Scsi_Cmnd *)hostdata->disconnected_queue; + disconnected_queue = (struct scsi_cmnd *)hostdata->disconnected_queue; hostdata->disconnected_queue = NULL; #ifdef SUPPORT_TAGS free_all_tags(); diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index e625b4c5833a..d56d85dd9ba0 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -119,7 +119,7 @@ module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); -static Scsi_Cmnd *sun3_dma_setup_done = NULL; +static struct scsi_cmnd *sun3_dma_setup_done = NULL; #define AFTER_RESET_DELAY (HZ/2) @@ -521,8 +521,9 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) return last_residual; } -static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, - int write_flag) +static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, + struct scsi_cmnd *cmd, + int write_flag) { if(blk_fs_request(cmd->request)) return wanted; diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h index 834dab428019..a1103b3e2034 100644 --- a/drivers/scsi/sun3_scsi.h +++ b/drivers/scsi/sun3_scsi.h @@ -47,11 +47,12 @@ #define IOBASE_SUN3_VMESCSI 0xff200000 -static int sun3scsi_abort (Scsi_Cmnd *); +static int sun3scsi_abort(struct scsi_cmnd *); static int sun3scsi_detect (struct scsi_host_template *); static const char *sun3scsi_info (struct Scsi_Host *); -static int sun3scsi_bus_reset(Scsi_Cmnd *); -static int sun3scsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +static int sun3scsi_bus_reset(struct scsi_cmnd *); +static int sun3scsi_queue_command(struct scsi_cmnd *, + void (*done)(struct scsi_cmnd *)); static int sun3scsi_release (struct Scsi_Host *); #ifndef CMD_PER_LUN diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index e8faab16567b..92def310a84c 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -84,7 +84,7 @@ module_param(setup_use_tagged_queuing, int, 0); static int setup_hostid = -1; module_param(setup_hostid, int, 0); -static Scsi_Cmnd *sun3_dma_setup_done = NULL; +static struct scsi_cmnd *sun3_dma_setup_done = NULL; #define AFTER_RESET_DELAY (HZ/2) @@ -455,8 +455,9 @@ static inline unsigned long sun3scsi_dma_residual(struct Scsi_Host *instance) return last_residual; } -static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, Scsi_Cmnd *cmd, - int write_flag) +static inline unsigned long sun3scsi_dma_xfer_len(unsigned long wanted, + struct scsi_cmnd *cmd, + int write_flag) { if(blk_fs_request(cmd->request)) return wanted; -- cgit v1.2.3 From a24342b90c9c829fc5fea9ee01b127f81bca18ef Mon Sep 17 00:00:00 2001 From: Henne Date: Tue, 3 Oct 2006 21:31:14 +0200 Subject: [SCSI] Scsi_Cmnd conversion in qlogicfas408 driver Change obsolete Scsi_Cmnd to struct scsi_cmnd in the Qlocic FAS408 driver. Signed-off-by: Henrik Kretzschmar rejections fixed and Signed-off-by: James Bottomley --- drivers/scsi/qlogicfas408.c | 18 +++++++++--------- drivers/scsi/qlogicfas408.h | 29 +++++++++++++++-------------- 2 files changed, 24 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c index e0725353c99c..2e7db18f5aef 100644 --- a/drivers/scsi/qlogicfas408.c +++ b/drivers/scsi/qlogicfas408.c @@ -209,7 +209,7 @@ static int ql_wai(struct qlogicfas408_priv *priv) * caller must hold host lock */ -static void ql_icmd(Scsi_Cmnd * cmd) +static void ql_icmd(struct scsi_cmnd *cmd) { struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); int qbase = priv->qbase; @@ -256,7 +256,7 @@ static void ql_icmd(Scsi_Cmnd * cmd) * Process scsi command - usually after interrupt */ -static unsigned int ql_pcmd(Scsi_Cmnd * cmd) +static unsigned int ql_pcmd(struct scsi_cmnd *cmd) { unsigned int i, j; unsigned long k; @@ -407,7 +407,7 @@ static unsigned int ql_pcmd(Scsi_Cmnd * cmd) static void ql_ihandl(void *dev_id) { - Scsi_Cmnd *icmd; + struct scsi_cmnd *icmd; struct Scsi_Host *host = dev_id; struct qlogicfas408_priv *priv = get_priv_by_host(host); int qbase = priv->qbase; @@ -447,7 +447,8 @@ irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id) * Queued command */ -int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +int qlogicfas408_queuecommand(struct scsi_cmnd *cmd, + void (*done) (struct scsi_cmnd *)) { struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); if (scmd_id(cmd) == priv->qinitid) { @@ -470,9 +471,8 @@ int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) * Return bios parameters */ -int qlogicfas408_biosparam(struct scsi_device * disk, - struct block_device *dev, - sector_t capacity, int ip[]) +int qlogicfas408_biosparam(struct scsi_device *disk, struct block_device *dev, + sector_t capacity, int ip[]) { /* This should mimic the DOS Qlogic driver's behavior exactly */ ip[0] = 0x40; @@ -494,7 +494,7 @@ int qlogicfas408_biosparam(struct scsi_device * disk, * Abort a command in progress */ -int qlogicfas408_abort(Scsi_Cmnd * cmd) +int qlogicfas408_abort(struct scsi_cmnd *cmd) { struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); priv->qabort = 1; @@ -508,7 +508,7 @@ int qlogicfas408_abort(Scsi_Cmnd * cmd) * the PCMCIA qlogic_stub code. This wants fixing */ -int qlogicfas408_bus_reset(Scsi_Cmnd * cmd) +int qlogicfas408_bus_reset(struct scsi_cmnd *cmd) { struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd); unsigned long flags; diff --git a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h index 8fd5555c75b1..260626427a32 100644 --- a/drivers/scsi/qlogicfas408.h +++ b/drivers/scsi/qlogicfas408.h @@ -75,15 +75,15 @@ /*----------------------------------------------------------------*/ struct qlogicfas408_priv { - int qbase; /* Port */ - int qinitid; /* initiator ID */ - int qabort; /* Flag to cause an abort */ - int qlirq; /* IRQ being used */ - int int_type; /* type of irq, 2 for ISA board, 0 for PCMCIA */ - char qinfo[80]; /* description */ - Scsi_Cmnd *qlcmd; /* current command being processed */ - struct Scsi_Host *shost; /* pointer back to host */ - struct qlogicfas408_priv *next; /* next private struct */ + int qbase; /* Port */ + int qinitid; /* initiator ID */ + int qabort; /* Flag to cause an abort */ + int qlirq; /* IRQ being used */ + int int_type; /* type of irq, 2 for ISA board, 0 for PCMCIA */ + char qinfo[80]; /* description */ + struct scsi_cmnd *qlcmd; /* current command being processed */ + struct Scsi_Host *shost; /* pointer back to host */ + struct qlogicfas408_priv *next; /* next private struct */ }; /* The qlogic card uses two register maps - These macros select which one */ @@ -103,12 +103,13 @@ struct qlogicfas408_priv { #define get_priv_by_host(x) (struct qlogicfas408_priv *)&((x)->hostdata[0]) irqreturn_t qlogicfas408_ihandl(int irq, void *dev_id); -int qlogicfas408_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); +int qlogicfas408_queuecommand(struct scsi_cmnd * cmd, + void (*done) (struct scsi_cmnd *)); int qlogicfas408_biosparam(struct scsi_device * disk, - struct block_device *dev, - sector_t capacity, int ip[]); -int qlogicfas408_abort(Scsi_Cmnd * cmd); -int qlogicfas408_bus_reset(Scsi_Cmnd * cmd); + struct block_device *dev, + sector_t capacity, int ip[]); +int qlogicfas408_abort(struct scsi_cmnd * cmd); +int qlogicfas408_bus_reset(struct scsi_cmnd * cmd); const char *qlogicfas408_info(struct Scsi_Host *host); int qlogicfas408_get_chip_type(int qbase, int int_type); void qlogicfas408_setup(int qbase, int id, int int_type); -- cgit v1.2.3 From 413f73272090a69e35a03c938272ec661b1d3d4c Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Thu, 5 Oct 2006 22:59:46 +0300 Subject: [SCSI] st: Fixup -ENOMEDIUM Based on the original patch from Hannes Reinecke Fix st_open() to return -ENOMEDIUM instead of -EIO if no medium is found. Signed-off-by: Kai Makisara Signed-off-by: James Bottomley --- drivers/scsi/st.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3babdc76b3fb..e1a52c525ed4 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -1177,7 +1177,10 @@ static int st_open(struct inode *inode, struct file *filp) goto err_out; if ((filp->f_flags & O_NONBLOCK) == 0 && retval != CHKRES_READY) { - retval = (-EIO); + if (STp->ready == NO_TAPE) + retval = (-ENOMEDIUM); + else + retval = (-EIO); goto err_out; } return 0; -- cgit v1.2.3 From 75c28851c9eee889ef4347ff6f55b2dd1e1ceb81 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Fri, 6 Oct 2006 00:11:17 +0200 Subject: [SCSI] tmscsim: set max_sectors AM53C974A's Start Transfer Counter register has 24 bits, thus maximum transfer length is 16MiB. But the maximum I can test is 8MiB, so use that until somebody tests 16MiB. Signed-off-by: Guennadi Liakhovetski Signed-off-by: James Bottomley --- drivers/scsi/tmscsim.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index d03aa6ce8fe8..fa5382e354be 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -2304,6 +2304,7 @@ static struct scsi_host_template driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = ENABLE_CLUSTERING, + .max_sectors = 0x4000, /* 8MiB = 16 * 1024 * 512 */ }; /*********************************************************************** -- cgit v1.2.3 From 5ae16db36988e811410494fb5d07c81e14453e7b Mon Sep 17 00:00:00 2001 From: Doug Maxey Date: Thu, 5 Oct 2006 23:50:07 -0500 Subject: [SCSI] qla4xxx: fix double printk on load There is a dup printk at the tail of qla4xxx_module_init(). Remove the first instance as it's before the complete success of the function. Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 178fcddcfd81..4fa01535fb64 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -1724,13 +1724,13 @@ static int __init qla4xxx_module_init(void) goto release_srb_cache; } - printk(KERN_INFO "QLogic iSCSI HBA Driver\n"); ret = pci_register_driver(&qla4xxx_pci_driver); if (ret) goto unregister_transport; printk(KERN_INFO "QLogic iSCSI HBA Driver\n"); return 0; + unregister_transport: iscsi_unregister_transport(&qla4xxx_iscsi_transport); release_srb_cache: -- cgit v1.2.3 From 80f1443c66de3ec42e28d151bd43a80de398877e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 6 Oct 2006 09:22:41 +0200 Subject: [SCSI] aic7xxx: Adjust .max_sectors According to the adaptec sources aic7xxx / aic79xx really can do 4MB transfers. So we should adjust .max_sectors. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 1 + drivers/scsi/aic7xxx/aic7xxx_osm.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index f8e60486167d..d8d6687e20ad 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -773,6 +773,7 @@ struct scsi_host_template aic79xx_driver_template = { #endif .can_queue = AHD_MAX_QUEUE, .this_id = -1, + .max_sectors = 8192, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, .slave_alloc = ahd_linux_slave_alloc, diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 43ab753d2739..ad8578e95937 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -777,6 +777,7 @@ struct scsi_host_template aic7xxx_driver_template = { #endif .can_queue = AHC_MAX_QUEUE, .this_id = -1, + .max_sectors = 8192, .cmd_per_lun = 2, .use_clustering = ENABLE_CLUSTERING, .slave_alloc = ahc_linux_slave_alloc, -- cgit v1.2.3 From 11010fecd2a1fdae684237b61709367ae6a93289 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 6 Oct 2006 09:54:59 -0700 Subject: [SCSI] Maintain module-parameter name consistency with qla2xxx/qla4xxx. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.h | 14 +++++++------- drivers/scsi/qla2xxx/qla_gbl.h | 2 +- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 8 ++++---- drivers/scsi/qla4xxx/ql4_dbg.h | 4 ++-- drivers/scsi/qla4xxx/ql4_glbl.h | 2 +- drivers/scsi/qla4xxx/ql4_mbx.c | 2 +- drivers/scsi/qla4xxx/ql4_os.c | 8 ++++---- 8 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index 90dad7e88985..5b12278968e0 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -38,7 +38,7 @@ * Macros use for debugging the driver. */ -#define DEBUG(x) do { if (qla2_extended_error_logging) { x; } } while (0) +#define DEBUG(x) do { if (ql2xextended_error_logging) { x; } } while (0) #if defined(QL_DEBUG_LEVEL_1) #define DEBUG1(x) do {x;} while (0) @@ -46,12 +46,12 @@ #define DEBUG1(x) do {} while (0) #endif -#define DEBUG2(x) do { if (qla2_extended_error_logging) { x; } } while (0) -#define DEBUG2_3(x) do { if (qla2_extended_error_logging) { x; } } while (0) -#define DEBUG2_3_11(x) do { if (qla2_extended_error_logging) { x; } } while (0) -#define DEBUG2_9_10(x) do { if (qla2_extended_error_logging) { x; } } while (0) -#define DEBUG2_11(x) do { if (qla2_extended_error_logging) { x; } } while (0) -#define DEBUG2_13(x) do { if (qla2_extended_error_logging) { x; } } while (0) +#define DEBUG2(x) do { if (ql2xextended_error_logging) { x; } } while (0) +#define DEBUG2_3(x) do { if (ql2xextended_error_logging) { x; } } while (0) +#define DEBUG2_3_11(x) do { if (ql2xextended_error_logging) { x; } } while (0) +#define DEBUG2_9_10(x) do { if (ql2xextended_error_logging) { x; } } while (0) +#define DEBUG2_11(x) do { if (ql2xextended_error_logging) { x; } } while (0) +#define DEBUG2_13(x) do { if (ql2xextended_error_logging) { x; } } while (0) #if defined(QL_DEBUG_LEVEL_3) #define DEBUG3(x) do {x;} while (0) diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index 7da69832d74c..b51ce8f59cb9 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -60,7 +60,7 @@ extern int ql2xplogiabsentdevice; extern int ql2xloginretrycount; extern int ql2xfdmienable; extern int ql2xallocfwdump; -extern int qla2_extended_error_logging; +extern int ql2xextended_error_logging; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 833b93085fd3..d5e0a124c4f4 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1644,7 +1644,7 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) * Set host adapter parameters. */ if (nv->host_p[0] & BIT_7) - qla2_extended_error_logging = 1; + ql2xextended_error_logging = 1; ha->flags.disable_risc_code_load = ((nv->host_p[0] & BIT_4) ? 1 : 0); /* Always load RISC code on non ISP2[12]00 chips. */ if (!IS_QLA2100(ha) && !IS_QLA2200(ha)) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 3f20d765563e..34b6eb71e450 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -61,9 +61,9 @@ MODULE_PARM_DESC(ql2xallocfwdump, "during HBA initialization. Memory allocation requirements " "vary by ISP type. Default is 1 - allocate memory."); -int qla2_extended_error_logging; -module_param(qla2_extended_error_logging, int, S_IRUGO|S_IRUSR); -MODULE_PARM_DESC(qla2_extended_error_logging, +int ql2xextended_error_logging; +module_param(ql2xextended_error_logging, int, S_IRUGO|S_IRUSR); +MODULE_PARM_DESC(ql2xextended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging. 1 - log errors."); @@ -2697,7 +2697,7 @@ qla2x00_module_init(void) /* Derive version string. */ strcpy(qla2x00_version_str, QLA2XXX_VERSION); - if (qla2_extended_error_logging) + if (ql2xextended_error_logging) strcat(qla2x00_version_str, "-debug"); qla2xxx_transport_template = diff --git a/drivers/scsi/qla4xxx/ql4_dbg.h b/drivers/scsi/qla4xxx/ql4_dbg.h index 3e99dcfd5a9f..d861c3b411c8 100644 --- a/drivers/scsi/qla4xxx/ql4_dbg.h +++ b/drivers/scsi/qla4xxx/ql4_dbg.h @@ -22,14 +22,14 @@ #endif #if defined(QL_DEBUG_LEVEL_2) -#define DEBUG2(x) do {if(qla4_extended_error_logging == 2) x;} while (0); +#define DEBUG2(x) do {if(ql4xextended_error_logging == 2) x;} while (0); #define DEBUG2_3(x) do {x;} while (0); #else /* */ #define DEBUG2(x) do {} while (0); #endif /* */ #if defined(QL_DEBUG_LEVEL_3) -#define DEBUG3(x) do {if(qla4_extended_error_logging == 3) x;} while (0); +#define DEBUG3(x) do {if(ql4xextended_error_logging == 3) x;} while (0); #else /* */ #define DEBUG3(x) do {} while (0); #if !defined(QL_DEBUG_LEVEL_2) diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 2c803edf2de8..1b221ff0f6f7 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -72,7 +72,7 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, uint32_t fw_ddb_index, uint32_t state); -extern int qla4_extended_error_logging; +extern int ql4xextended_error_logging; extern int ql4xdiscoverywait; extern int ql4xdontresethba; #endif /* _QLA4x_GBL_H */ diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index ef82399c0858..b721dc5dd711 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -701,7 +701,7 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha) DEBUG3(printk("scsi%ld: Connection Event Log Dump (%d entries):\n", ha->host_no, num_valid_entries)); - if (qla4_extended_error_logging == 3) { + if (ql4xextended_error_logging == 3) { if (oldest_entry == 0) { /* Circular Buffer has not wrapped around */ for (i=0; i < num_valid_entries; i++) { diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 4fa01535fb64..5b8db6109536 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -34,9 +34,9 @@ MODULE_PARM_DESC(ql4xdontresethba, " default it will reset hba :0" " set to 1 to avoid resetting HBA"); -int qla4_extended_error_logging = 0; /* 0 = off, 1 = log errors */ -module_param(qla4_extended_error_logging, int, S_IRUGO | S_IRUSR); -MODULE_PARM_DESC(qla4_extended_error_logging, +int ql4xextended_error_logging = 0; /* 0 = off, 1 = log errors */ +module_param(ql4xextended_error_logging, int, S_IRUGO | S_IRUSR); +MODULE_PARM_DESC(ql4xextended_error_logging, "Option to enable extended error logging, " "Default is 0 - no logging, 1 - debug logging"); @@ -1714,7 +1714,7 @@ static int __init qla4xxx_module_init(void) /* Derive version string. */ strcpy(qla4xxx_version_str, QLA4XXX_DRIVER_VERSION); - if (qla4_extended_error_logging) + if (ql4xextended_error_logging) strcat(qla4xxx_version_str, "-debug"); qla4xxx_scsi_transport = -- cgit v1.2.3 From 35508e46aae4b57bd07d095eb11533e296b254dc Mon Sep 17 00:00:00 2001 From: Michael Reed Date: Fri, 6 Oct 2006 15:39:25 -0500 Subject: [SCSI] mptfc: stall eh handlers if resetting while rport blocked Thanks to James Smart for the inspiration. Stall error handler if attempting recovery while an rport is blocked. This avoids device offline scenarios due to errors in the error handler. Also verify that VirtDevice is available before issuing scsi command. VirtDevice is removed when fc transport removes a target. See James Smart's patch of 08/17/2006 for greater detail. http://marc.theaimsgroup.com/?l=linux-scsi&m=115583213624803&w=2 Also bump version number per Eric's request. Signed-off-by: Michael Reed Acked-by: Eric Moore Signed-off-by: James Bottomley --- drivers/message/fusion/mptbase.h | 4 +- drivers/message/fusion/mptfc.c | 89 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index c537d71c18e4..a4afad4ecab2 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -75,8 +75,8 @@ #define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.01" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.01" +#define MPT_LINUX_VERSION_COMMON "3.04.02" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.02" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index e57bb035a021..1dd491773150 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -96,6 +96,10 @@ static int mptfc_qcmd(struct scsi_cmnd *SCpnt, static void mptfc_target_destroy(struct scsi_target *starget); static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout); static void __devexit mptfc_remove(struct pci_dev *pdev); +static int mptfc_abort(struct scsi_cmnd *SCpnt); +static int mptfc_dev_reset(struct scsi_cmnd *SCpnt); +static int mptfc_bus_reset(struct scsi_cmnd *SCpnt); +static int mptfc_host_reset(struct scsi_cmnd *SCpnt); static struct scsi_host_template mptfc_driver_template = { .module = THIS_MODULE, @@ -110,10 +114,10 @@ static struct scsi_host_template mptfc_driver_template = { .target_destroy = mptfc_target_destroy, .slave_destroy = mptscsih_slave_destroy, .change_queue_depth = mptscsih_change_queue_depth, - .eh_abort_handler = mptscsih_abort, - .eh_device_reset_handler = mptscsih_dev_reset, - .eh_bus_reset_handler = mptscsih_bus_reset, - .eh_host_reset_handler = mptscsih_host_reset, + .eh_abort_handler = mptfc_abort, + .eh_device_reset_handler = mptfc_dev_reset, + .eh_bus_reset_handler = mptfc_bus_reset, + .eh_host_reset_handler = mptfc_host_reset, .bios_param = mptscsih_bios_param, .can_queue = MPT_FC_CAN_QUEUE, .this_id = -1, @@ -171,6 +175,77 @@ static struct fc_function_template mptfc_transport_functions = { .show_host_symbolic_name = 1, }; +static int +mptfc_block_error_handler(struct scsi_cmnd *SCpnt, + int (*func)(struct scsi_cmnd *SCpnt), + const char *caller) +{ + struct scsi_device *sdev = SCpnt->device; + struct Scsi_Host *shost = sdev->host; + struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); + unsigned long flags; + int ready; + + spin_lock_irqsave(shost->host_lock, flags); + while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) { + spin_unlock_irqrestore(shost->host_lock, flags); + dfcprintk ((MYIOC_s_INFO_FMT + "mptfc_block_error_handler.%d: %d:%d, port status is " + "DID_IMM_RETRY, deferring %s recovery.\n", + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, + SCpnt->device->id,SCpnt->device->lun,caller)); + msleep(1000); + spin_lock_irqsave(shost->host_lock, flags); + } + spin_unlock_irqrestore(shost->host_lock, flags); + + if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) { + dfcprintk ((MYIOC_s_INFO_FMT + "%s.%d: %d:%d, failing recovery, " + "port state %d, vdev %p.\n", caller, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, + SCpnt->device->id,SCpnt->device->lun,ready, + SCpnt->device->hostdata)); + return FAILED; + } + dfcprintk ((MYIOC_s_INFO_FMT + "%s.%d: %d:%d, executing recovery.\n", caller, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, + SCpnt->device->id,SCpnt->device->lun)); + return (*func)(SCpnt); +} + +static int +mptfc_abort(struct scsi_cmnd *SCpnt) +{ + return + mptfc_block_error_handler(SCpnt, mptscsih_abort, __FUNCTION__); +} + +static int +mptfc_dev_reset(struct scsi_cmnd *SCpnt) +{ + return + mptfc_block_error_handler(SCpnt, mptscsih_dev_reset, __FUNCTION__); +} + +static int +mptfc_bus_reset(struct scsi_cmnd *SCpnt) +{ + return + mptfc_block_error_handler(SCpnt, mptscsih_bus_reset, __FUNCTION__); +} + +static int +mptfc_host_reset(struct scsi_cmnd *SCpnt) +{ + return + mptfc_block_error_handler(SCpnt, mptscsih_host_reset, __FUNCTION__); +} + static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { @@ -562,6 +637,12 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return 0; } + if (!SCpnt->device->hostdata) { /* vdev */ + SCpnt->result = DID_NO_CONNECT << 16; + done(SCpnt); + return 0; + } + /* dd_data is null until finished adding target */ ri = *((struct mptfc_rport_info **)rport->dd_data); if (unlikely(!ri)) { -- cgit v1.2.3 From 8e394aec14f24e3b41a315a2dc53537024190c8a Mon Sep 17 00:00:00 2001 From: Henne Date: Mon, 9 Oct 2006 15:38:34 +0200 Subject: [SCSI] fix typo in previous Scsi_Cmnd convertion in aic7xxx_old.c Fixes a typo in the aic7xxx_old.c. Signed-off-by: Olaf Hering Signed-off-by: Henrik Kretzschmar Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx_old.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index bcd7fffab907..46eed10b25d9 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -2646,7 +2646,7 @@ static void aic7xxx_done_cmds_complete(struct aic7xxx_host *p) while (p->completeq.head != NULL) { cmd = p->completeq.head; - p->completeq.head = (struct scsi_Cmnd *) cmd->host_scribble; + p->completeq.head = (struct scsi_cmnd *) cmd->host_scribble; cmd->host_scribble = NULL; cmd->scsi_done(cmd); } -- cgit v1.2.3 From 46c43db1eabcdc46ad9a3d711edff1d698ecd21f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sun, 8 Oct 2006 15:55:55 +0400 Subject: [SCSI] scsi_lib.c: use BUILD_BUG_ON Signed-off-by: Alexey Dobriyan Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 743f67ed7640..d2c02df12fdc 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1084,7 +1084,7 @@ static void scsi_setup_blk_pc_cmnd(struct scsi_cmnd *cmd) { struct request *req = cmd->request; - BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); + BUILD_BUG_ON(sizeof(req->cmd) > sizeof(cmd->cmnd)); memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); cmd->cmd_len = req->cmd_len; if (!req->data_len) -- cgit v1.2.3 From 0b3a82d391563da15df2b3a0d245d41748822489 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 10 Oct 2006 14:41:43 -0700 Subject: [SCSI] lpfc: check before dereference in lpfc_ct.c If we fail to allocate mp->virt during the first while loop iteration, mlist is still uninitialized, therefore we should check if before dereferencing. Signed-off-by: Eric Sesterhenn Acked-by: James Smart Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_ct.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 1b53afb1cb57..3add7c237859 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -188,7 +188,8 @@ lpfc_alloc_ct_rsp(struct lpfc_hba * phba, int cmdcode, struct ulp_bde64 * bpl, if (!mp->virt) { kfree(mp); - lpfc_free_ct_rsp(phba, mlist); + if (mlist) + lpfc_free_ct_rsp(phba, mlist); return NULL; } -- cgit v1.2.3 From c543a3739c2a3034c80d77a189bd187c43a00feb Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:41:45 -0700 Subject: [SCSI] Scsi_Cmnd conversion in psi240i driver Changes the obsolete Scsi_Cmnd to struct scsi_cmnd in psi240i-driver. Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/psi240i.c | 31 ++++++++++++++++++------------- drivers/scsi/psi240i.h | 6 +++--- 2 files changed, 21 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index a720c9265e66..ac0419e2714a 100644 --- a/drivers/scsi/psi240i.c +++ b/drivers/scsi/psi240i.c @@ -87,11 +87,11 @@ typedef struct { USHORT ports[13]; OUR_DEVICE device[8]; - Scsi_Cmnd *pSCmnd; + struct scsi_cmnd *pSCmnd; IDE_STRUCT ide; ULONG startSector; USHORT sectorCount; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; VOID *buffer; USHORT expectingIRQ; } ADAPTER240I, *PADAPTER240I; @@ -253,12 +253,12 @@ static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status) ****************************************************************/ static void Irq_Handler (int irq, void *dev_id) { - struct Scsi_Host *shost; // Pointer to host data block - PADAPTER240I padapter; // Pointer to adapter control structure - USHORT *pports; // I/O port array - Scsi_Cmnd *SCpnt; - UCHAR status; - int z; + struct Scsi_Host *shost; // Pointer to host data block + PADAPTER240I padapter; // Pointer to adapter control structure + USHORT *pports; // I/O port array + struct scsi_cmnd *SCpnt; + UCHAR status; + int z; DEB(printk ("\npsi240i received interrupt\n")); @@ -389,12 +389,17 @@ static irqreturn_t do_Irq_Handler (int irq, void *dev_id) * Returns: Status code. * ****************************************************************/ -static int Psi240i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static int Psi240i_QueueCommand(struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) { - UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB - PADAPTER240I padapter = HOSTDATA (SCpnt->device->host); // Pointer to adapter control structure - POUR_DEVICE pdev = &padapter->device [SCpnt->device->id];// Pointer to device information - UCHAR rc; // command return code + UCHAR *cdb = (UCHAR *)SCpnt->cmnd; + // Pointer to SCSI CDB + PADAPTER240I padapter = HOSTDATA (SCpnt->device->host); + // Pointer to adapter control structure + POUR_DEVICE pdev = &padapter->device [SCpnt->device->id]; + // Pointer to device information + UCHAR rc; + // command return code SCpnt->scsi_done = done; padapter->ide.ide.ides.spigot = pdev->spigot; diff --git a/drivers/scsi/psi240i.h b/drivers/scsi/psi240i.h index 6a598766df51..21ebb9214004 100644 --- a/drivers/scsi/psi240i.h +++ b/drivers/scsi/psi240i.h @@ -309,7 +309,7 @@ typedef struct _IDENTIFY_DATA2 { #endif // PSI_EIDE_SCSIOP // function prototypes -int Psi240i_Command (Scsi_Cmnd *SCpnt); -int Psi240i_Abort (Scsi_Cmnd *SCpnt); -int Psi240i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags); +int Psi240i_Command(struct scsi_cmnd *SCpnt); +int Psi240i_Abort(struct scsi_cmnd *SCpnt); +int Psi240i_Reset(struct scsi_cmnd *SCpnt, unsigned int flags); #endif -- cgit v1.2.3 From 0fc82d5e84825ab43006f40935633120d23c2e15 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:41:41 -0700 Subject: [SCSI] convert ninja driver to struct scsi_cmnd Changes the obsolete typedefd Scsi_Cmnd to struct scsi_cmnd in the ninja scsi pcmcia driver. Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/pcmcia/nsp_cs.c | 42 ++++++++++++++++++----------------- drivers/scsi/pcmcia/nsp_cs.h | 46 +++++++++++++++++++++------------------ drivers/scsi/pcmcia/nsp_debug.c | 4 ++-- drivers/scsi/pcmcia/nsp_message.c | 4 ++-- 4 files changed, 51 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index b1d346049525..f2d79c3f0b8e 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -183,7 +183,7 @@ static void nsp_cs_dmessage(const char *func, int line, int mask, char *fmt, ... * Clenaup parameters and call done() functions. * You must be set SCpnt->result before call this function. */ -static void nsp_scsi_done(Scsi_Cmnd *SCpnt) +static void nsp_scsi_done(struct scsi_cmnd *SCpnt) { nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; @@ -192,7 +192,8 @@ static void nsp_scsi_done(Scsi_Cmnd *SCpnt) SCpnt->scsi_done(SCpnt); } -static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) +static int nsp_queuecommand(struct scsi_cmnd *SCpnt, + void (*done)(struct scsi_cmnd *)) { #ifdef NSP_DEBUG /*unsigned int host_id = SCpnt->device->host->this_id;*/ @@ -365,7 +366,7 @@ static int nsphw_init(nsp_hw_data *data) /* * Start selection phase */ -static int nsphw_start_selection(Scsi_Cmnd *SCpnt) +static int nsphw_start_selection(struct scsi_cmnd *SCpnt) { unsigned int host_id = SCpnt->device->host->this_id; unsigned int base = SCpnt->device->host->io_port; @@ -446,7 +447,7 @@ static struct nsp_sync_table nsp_sync_table_20M[] = { /* * setup synchronous data transfer mode */ -static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt) +static int nsp_analyze_sdtr(struct scsi_cmnd *SCpnt) { unsigned char target = scmd_id(SCpnt); // unsigned char lun = SCpnt->device->lun; @@ -504,7 +505,7 @@ static int nsp_analyze_sdtr(Scsi_Cmnd *SCpnt) /* * start ninja hardware timer */ -static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time) +static void nsp_start_timer(struct scsi_cmnd *SCpnt, int time) { unsigned int base = SCpnt->device->host->io_port; nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; @@ -517,7 +518,8 @@ static void nsp_start_timer(Scsi_Cmnd *SCpnt, int time) /* * wait for bus phase change */ -static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str) +static int nsp_negate_signal(struct scsi_cmnd *SCpnt, unsigned char mask, + char *str) { unsigned int base = SCpnt->device->host->io_port; unsigned char reg; @@ -544,9 +546,9 @@ static int nsp_negate_signal(Scsi_Cmnd *SCpnt, unsigned char mask, char *str) /* * expect Ninja Irq */ -static int nsp_expect_signal(Scsi_Cmnd *SCpnt, - unsigned char current_phase, - unsigned char mask) +static int nsp_expect_signal(struct scsi_cmnd *SCpnt, + unsigned char current_phase, + unsigned char mask) { unsigned int base = SCpnt->device->host->io_port; int time_out; @@ -579,7 +581,7 @@ static int nsp_expect_signal(Scsi_Cmnd *SCpnt, /* * transfer SCSI message */ -static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase) +static int nsp_xfer(struct scsi_cmnd *SCpnt, int phase) { unsigned int base = SCpnt->device->host->io_port; nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; @@ -619,7 +621,7 @@ static int nsp_xfer(Scsi_Cmnd *SCpnt, int phase) /* * get extra SCSI data from fifo */ -static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt) +static int nsp_dataphase_bypass(struct scsi_cmnd *SCpnt) { nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; unsigned int count; @@ -651,7 +653,7 @@ static int nsp_dataphase_bypass(Scsi_Cmnd *SCpnt) /* * accept reselection */ -static int nsp_reselected(Scsi_Cmnd *SCpnt) +static int nsp_reselected(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned int host_id = SCpnt->device->host->this_id; @@ -690,7 +692,7 @@ static int nsp_reselected(Scsi_Cmnd *SCpnt) /* * count how many data transferd */ -static int nsp_fifo_count(Scsi_Cmnd *SCpnt) +static int nsp_fifo_count(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned int count; @@ -717,7 +719,7 @@ static int nsp_fifo_count(Scsi_Cmnd *SCpnt) /* * read data in DATA IN phase */ -static void nsp_pio_read(Scsi_Cmnd *SCpnt) +static void nsp_pio_read(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned long mmio_base = SCpnt->device->host->base; @@ -812,7 +814,7 @@ static void nsp_pio_read(Scsi_Cmnd *SCpnt) /* * write data in DATA OUT phase */ -static void nsp_pio_write(Scsi_Cmnd *SCpnt) +static void nsp_pio_write(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned long mmio_base = SCpnt->device->host->base; @@ -905,7 +907,7 @@ static void nsp_pio_write(Scsi_Cmnd *SCpnt) /* * setup synchronous/asynchronous data transfer mode */ -static int nsp_nexus(Scsi_Cmnd *SCpnt) +static int nsp_nexus(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; unsigned char target = scmd_id(SCpnt); @@ -952,7 +954,7 @@ static irqreturn_t nspintr(int irq, void *dev_id) { unsigned int base; unsigned char irq_status, irq_phase, phase; - Scsi_Cmnd *tmpSC; + struct scsi_cmnd *tmpSC; unsigned char target, lun; unsigned int *sync_neg; int i, tmp; @@ -1530,7 +1532,7 @@ nsp_proc_info( /*---------------------------------------------------------------*/ /* -static int nsp_eh_abort(Scsi_Cmnd *SCpnt) +static int nsp_eh_abort(struct scsi_cmnd *SCpnt) { nsp_dbg(NSP_DEBUG_BUSRESET, "SCpnt=0x%p", SCpnt); @@ -1558,7 +1560,7 @@ static int nsp_bus_reset(nsp_hw_data *data) return SUCCESS; } -static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt) +static int nsp_eh_bus_reset(struct scsi_cmnd *SCpnt) { nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; @@ -1567,7 +1569,7 @@ static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt) return nsp_bus_reset(data); } -static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt) +static int nsp_eh_host_reset(struct scsi_cmnd *SCpnt) { nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index a88714f4c05b..625ca97da52d 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -266,7 +266,7 @@ typedef struct _nsp_hw_data { int TimerCount; int SelectionTimeOut; - Scsi_Cmnd *CurrentSC; + struct scsi_cmnd *CurrentSC; //int CurrnetTarget; int FifoCount; @@ -319,30 +319,34 @@ static int nsp_proc_info ( int hostno, #endif int inout); -static int nsp_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *SCpnt)); +static int nsp_queuecommand(struct scsi_cmnd *SCpnt, + void (* done)(struct scsi_cmnd *SCpnt)); /* Error handler */ -/*static int nsp_eh_abort (Scsi_Cmnd *SCpnt);*/ -/*static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt);*/ -static int nsp_eh_bus_reset (Scsi_Cmnd *SCpnt); -static int nsp_eh_host_reset (Scsi_Cmnd *SCpnt); +/*static int nsp_eh_abort (struct scsi_cmnd *SCpnt);*/ +/*static int nsp_eh_device_reset(struct scsi_cmnd *SCpnt);*/ +static int nsp_eh_bus_reset (struct scsi_cmnd *SCpnt); +static int nsp_eh_host_reset (struct scsi_cmnd *SCpnt); static int nsp_bus_reset (nsp_hw_data *data); /* */ static int nsphw_init (nsp_hw_data *data); -static int nsphw_start_selection(Scsi_Cmnd *SCpnt); -static void nsp_start_timer (Scsi_Cmnd *SCpnt, int time); -static int nsp_fifo_count (Scsi_Cmnd *SCpnt); -static void nsp_pio_read (Scsi_Cmnd *SCpnt); -static void nsp_pio_write (Scsi_Cmnd *SCpnt); -static int nsp_nexus (Scsi_Cmnd *SCpnt); -static void nsp_scsi_done (Scsi_Cmnd *SCpnt); -static int nsp_analyze_sdtr (Scsi_Cmnd *SCpnt); -static int nsp_negate_signal (Scsi_Cmnd *SCpnt, unsigned char mask, char *str); -static int nsp_expect_signal (Scsi_Cmnd *SCpnt, unsigned char current_phase, unsigned char mask); -static int nsp_xfer (Scsi_Cmnd *SCpnt, int phase); -static int nsp_dataphase_bypass (Scsi_Cmnd *SCpnt); -static int nsp_reselected (Scsi_Cmnd *SCpnt); +static int nsphw_start_selection(struct scsi_cmnd *SCpnt); +static void nsp_start_timer (struct scsi_cmnd *SCpnt, int time); +static int nsp_fifo_count (struct scsi_cmnd *SCpnt); +static void nsp_pio_read (struct scsi_cmnd *SCpnt); +static void nsp_pio_write (struct scsi_cmnd *SCpnt); +static int nsp_nexus (struct scsi_cmnd *SCpnt); +static void nsp_scsi_done (struct scsi_cmnd *SCpnt); +static int nsp_analyze_sdtr (struct scsi_cmnd *SCpnt); +static int nsp_negate_signal (struct scsi_cmnd *SCpnt, + unsigned char mask, char *str); +static int nsp_expect_signal (struct scsi_cmnd *SCpnt, + unsigned char current_phase, + unsigned char mask); +static int nsp_xfer (struct scsi_cmnd *SCpnt, int phase); +static int nsp_dataphase_bypass (struct scsi_cmnd *SCpnt); +static int nsp_reselected (struct scsi_cmnd *SCpnt); static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht); /* Interrupt handler */ @@ -355,8 +359,8 @@ static void __exit nsp_cs_exit(void); /* Debug */ #ifdef NSP_DEBUG -static void show_command (Scsi_Cmnd *SCpnt); -static void show_phase (Scsi_Cmnd *SCpnt); +static void show_command (struct scsi_cmnd *SCpnt); +static void show_phase (struct scsi_cmnd *SCpnt); static void show_busphase(unsigned char stat); static void show_message (nsp_hw_data *data); #else diff --git a/drivers/scsi/pcmcia/nsp_debug.c b/drivers/scsi/pcmcia/nsp_debug.c index 62e5c60067fd..2f75fe6e35a7 100644 --- a/drivers/scsi/pcmcia/nsp_debug.c +++ b/drivers/scsi/pcmcia/nsp_debug.c @@ -138,12 +138,12 @@ static void print_commandk (unsigned char *command) printk("\n"); } -static void show_command(Scsi_Cmnd *SCpnt) +static void show_command(struct scsi_cmnd *SCpnt) { print_commandk(SCpnt->cmnd); } -static void show_phase(Scsi_Cmnd *SCpnt) +static void show_phase(struct scsi_cmnd *SCpnt) { int i = SCpnt->SCp.phase; diff --git a/drivers/scsi/pcmcia/nsp_message.c b/drivers/scsi/pcmcia/nsp_message.c index d7057737ff34..ef593b70d0f0 100644 --- a/drivers/scsi/pcmcia/nsp_message.c +++ b/drivers/scsi/pcmcia/nsp_message.c @@ -8,7 +8,7 @@ /* $Id: nsp_message.c,v 1.6 2003/07/26 14:21:09 elca Exp $ */ -static void nsp_message_in(Scsi_Cmnd *SCpnt) +static void nsp_message_in(struct scsi_cmnd *SCpnt) { unsigned int base = SCpnt->device->host->io_port; nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; @@ -50,7 +50,7 @@ static void nsp_message_in(Scsi_Cmnd *SCpnt) } -static void nsp_message_out(Scsi_Cmnd *SCpnt) +static void nsp_message_out(struct scsi_cmnd *SCpnt) { nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; int ret = 1; -- cgit v1.2.3 From 9531c330f14c02d9f4eff7345071f485dc62dab1 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:41:42 -0700 Subject: [SCSI] fc4: Conversion to struct scsi_cmnd in fc4 Changes the obsolete Scsi_Cmnd to struct scsi_cmnd in the Fibre Channel driver (fc4). Signed-off-by: Henrik Kretzschmar Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/fc4/fc.c | 28 +++++++++++++++------------- drivers/fc4/fcp_impl.h | 15 ++++++++------- 2 files changed, 23 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 22d17474755f..ca4e67a022d0 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -70,9 +70,9 @@ #define FCP_CMND(SCpnt) ((fcp_cmnd *)&(SCpnt->SCp)) #define FC_SCMND(SCpnt) ((fc_channel *)(SCpnt->device->host->hostdata[0])) -#define SC_FCMND(fcmnd) ((Scsi_Cmnd *)((long)fcmnd - (long)&(((Scsi_Cmnd *)0)->SCp))) +#define SC_FCMND(fcmnd) ((struct scsi_cmnd *)((long)fcmnd - (long)&(((struct scsi_cmnd *)0)->SCp))) -static int fcp_scsi_queue_it(fc_channel *, Scsi_Cmnd *, fcp_cmnd *, int); +static int fcp_scsi_queue_it(fc_channel *, struct scsi_cmnd *, fcp_cmnd *, int); void fcp_queue_empty(fc_channel *); static void fcp_scsi_insert_queue (fc_channel *fc, fcp_cmnd *fcmd) @@ -378,14 +378,14 @@ void fcp_register(fc_channel *fc, u8 type, int unregister) printk ("FC: %segistering unknown type %02x\n", unregister ? "Unr" : "R", type); } -static void fcp_scsi_done(Scsi_Cmnd *SCpnt); +static void fcp_scsi_done(struct scsi_cmnd *SCpnt); static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hdr *fch) { fcp_cmnd *fcmd; fcp_rsp *rsp; int host_status; - Scsi_Cmnd *SCpnt; + struct scsi_cmnd *SCpnt; int sense_len; int rsp_status; @@ -757,13 +757,14 @@ void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */ } -static void fcp_scsi_done (Scsi_Cmnd *SCpnt) +static void fcp_scsi_done(struct scsi_cmnd *SCpnt) { if (FCP_CMND(SCpnt)->done) FCP_CMND(SCpnt)->done(SCpnt); } -static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, int prepare) +static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt, + fcp_cmnd *fcmd, int prepare) { long i; fcp_cmd *cmd; @@ -837,7 +838,8 @@ static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, i return 0; } -int fcp_scsi_queuecommand(Scsi_Cmnd *SCpnt, void (* done)(Scsi_Cmnd *)) +int fcp_scsi_queuecommand(struct scsi_cmnd *SCpnt, + void (* done)(struct scsi_cmnd *)) { fcp_cmnd *fcmd = FCP_CMND(SCpnt); fc_channel *fc = FC_SCMND(SCpnt); @@ -873,7 +875,7 @@ void fcp_queue_empty(fc_channel *fc) } } -int fcp_scsi_abort(Scsi_Cmnd *SCpnt) +int fcp_scsi_abort(struct scsi_cmnd *SCpnt) { /* Internal bookkeeping only. Lose 1 cmd_slots slot. */ fcp_cmnd *fcmd = FCP_CMND(SCpnt); @@ -910,7 +912,7 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt) } #if 0 -void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt) +void fcp_scsi_reset_done(struct scsi_cmnd *SCpnt) { fc_channel *fc = FC_SCMND(SCpnt); @@ -921,7 +923,7 @@ void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt) #define FCP_RESET_TIMEOUT (2*HZ) -int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) +int fcp_scsi_dev_reset(struct scsi_cmnd *SCpnt) { #if 0 /* broken junk, but if davem wants to compile this driver, let him.. */ unsigned long flags; @@ -931,7 +933,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) DECLARE_MUTEX_LOCKED(sem); if (!fc->rst_pkt) { - fc->rst_pkt = (Scsi_Cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL); + fc->rst_pkt = (struct scsi_cmnd *) kmalloc(sizeof(SCpnt), GFP_KERNEL); if (!fc->rst_pkt) return FAILED; fcmd = FCP_CMND(fc->rst_pkt); @@ -999,7 +1001,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt) return SUCCESS; } -static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) +static int __fcp_scsi_host_reset(struct scsi_cmnd *SCpnt) { fc_channel *fc = FC_SCMND(SCpnt); fcp_cmnd *fcmd = FCP_CMND(SCpnt); @@ -1020,7 +1022,7 @@ static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) else return FAILED; } -int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt) +int fcp_scsi_host_reset(struct scsi_cmnd *SCpnt) { unsigned long flags; int rc; diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h index c397c84bef63..1ac61330592e 100644 --- a/drivers/fc4/fcp_impl.h +++ b/drivers/fc4/fcp_impl.h @@ -39,7 +39,7 @@ struct _fc_channel; typedef struct fcp_cmnd { struct fcp_cmnd *next; struct fcp_cmnd *prev; - void (*done)(Scsi_Cmnd *); + void (*done)(struct scsi_cmnd *); unsigned short proto; unsigned short token; unsigned int did; @@ -94,14 +94,14 @@ typedef struct _fc_channel { long *scsi_bitmap; long scsi_bitmap_end; int scsi_free; - int (*encode_addr)(Scsi_Cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *); + int (*encode_addr)(struct scsi_cmnd *, u16 *, struct _fc_channel *, fcp_cmnd *); fcp_cmnd *scsi_que; char scsi_name[4]; fcp_cmnd **cmd_slots; int channels; int targets; long *ages; - Scsi_Cmnd *rst_pkt; + struct scsi_cmnd *rst_pkt; fcp_posmap *posmap; /* LOGIN stuff */ fcp_cmnd *login; @@ -155,9 +155,10 @@ int fc_do_prli(fc_channel *, unsigned char); for_each_fc_channel(fc) \ if (fc->state == FC_STATE_ONLINE) -int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -int fcp_scsi_abort(Scsi_Cmnd *); -int fcp_scsi_dev_reset(Scsi_Cmnd *); -int fcp_scsi_host_reset(Scsi_Cmnd *); +int fcp_scsi_queuecommand(struct scsi_cmnd *, + void (* done) (struct scsi_cmnd *)); +int fcp_scsi_abort(struct scsi_cmnd *); +int fcp_scsi_dev_reset(struct scsi_cmnd *); +int fcp_scsi_host_reset(struct scsi_cmnd *); #endif /* !(_FCP_SCSI_H) */ -- cgit v1.2.3 From 8d1a006049ff1c084d57fbea1106ecad3455bd27 Mon Sep 17 00:00:00 2001 From: Swen Schillig Date: Thu, 12 Oct 2006 11:43:44 +0200 Subject: [SCSI] zfcp: initialize scsi_host_template.max_sectors with appropriate value Define ZFCP_MAX_SECTORS and initialize scsi_host_template.max_sectors with appropriate value. Signed-off-by: Swen Schillig Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_def.h | 4 ++++ drivers/s390/scsi/zfcp_scsi.c | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index 8f882690994d..74c0eac083e4 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -107,6 +107,10 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) (ZFCP_MAX_SBALS_PER_REQ * ZFCP_MAX_SBALES_PER_SBAL - 2) /* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */ +#define ZFCP_MAX_SECTORS (ZFCP_MAX_SBALES_PER_REQ * 8) + /* max. number of (data buffer) SBALEs in largest SBAL chain + multiplied with number of sectors per 4k block */ + /* FIXME(tune): free space should be one max. SBAL chain plus what? */ #define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \ - (ZFCP_MAX_SBALS_PER_REQ + 4)) diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 4d2bc7981324..452d96f92a14 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -58,6 +58,7 @@ struct zfcp_data zfcp_data = { .cmd_per_lun = 1, .use_clustering = 1, .sdev_attrs = zfcp_sysfs_sdev_attrs, + .max_sectors = ZFCP_MAX_SECTORS, }, .driver_version = ZFCP_VERSION, }; -- cgit v1.2.3 From f1663ad5dbb801e03c4c99c24d698ad5dba9aaff Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 13 Oct 2006 09:33:37 -0700 Subject: [SCSI] qla2xxx: Check return value of sysfs_create_bin_file() usage. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 51 ++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index ee75a71f3c66..285c8e8ff1a0 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -379,21 +379,37 @@ static struct bin_attribute sysfs_sfp_attr = { .read = qla2x00_sysfs_read_sfp, }; +static struct sysfs_entry { + char *name; + struct bin_attribute *attr; + int is4GBp_only; +} bin_file_entries[] = { + { "fw_dump", &sysfs_fw_dump_attr, }, + { "nvram", &sysfs_nvram_attr, }, + { "optrom", &sysfs_optrom_attr, }, + { "optrom_ctl", &sysfs_optrom_ctl_attr, }, + { "vpd", &sysfs_vpd_attr, 1 }, + { "sfp", &sysfs_sfp_attr, 1 }, + { 0 }, +}; + void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *ha) { struct Scsi_Host *host = ha->host; + struct sysfs_entry *iter; + int ret; - sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); - sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); - sysfs_create_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); - sysfs_create_bin_file(&host->shost_gendev.kobj, - &sysfs_optrom_ctl_attr); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { - sysfs_create_bin_file(&host->shost_gendev.kobj, - &sysfs_vpd_attr); - sysfs_create_bin_file(&host->shost_gendev.kobj, - &sysfs_sfp_attr); + for (iter = bin_file_entries; iter->name; iter++) { + if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + continue; + + ret = sysfs_create_bin_file(&host->shost_gendev.kobj, + iter->attr); + if (ret) + qla_printk(KERN_INFO, ha, + "Unable to create sysfs %s binary attribute " + "(%d).\n", iter->name, ret); } } @@ -401,17 +417,14 @@ void qla2x00_free_sysfs_attr(scsi_qla_host_t *ha) { struct Scsi_Host *host = ha->host; + struct sysfs_entry *iter; + + for (iter = bin_file_entries; iter->name; iter++) { + if (iter->is4GBp_only && (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))) + continue; - sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_fw_dump_attr); - sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_nvram_attr); - sysfs_remove_bin_file(&host->shost_gendev.kobj, &sysfs_optrom_attr); - sysfs_remove_bin_file(&host->shost_gendev.kobj, - &sysfs_optrom_ctl_attr); - if (IS_QLA24XX(ha) || IS_QLA54XX(ha)) { - sysfs_remove_bin_file(&host->shost_gendev.kobj, - &sysfs_vpd_attr); sysfs_remove_bin_file(&host->shost_gendev.kobj, - &sysfs_sfp_attr); + iter->attr); } if (ha->beacon_blink_led == 1) -- cgit v1.2.3 From 18c6c12759813c988bb05796d1b3352e98ae77de Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 13 Oct 2006 09:33:38 -0700 Subject: [SCSI] qla2xxx: Workaround D3 power-management issues. Early ISP2432 parts have a known hardware issue when coming out of a D3 hot state. This issue can result in a hung PCIe link. Recent firmwares contain a workaround whereby the stop-firmware mailbox command prevents the ISP from entering the D3 hot state. In order to ensure that the workaround succeeded the driver must verify that the stop-firmware mailbox command completes successfully. In the event of a failure, the driver attempts a shutdown-retry after resetting the ISP and re-executing firmware. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_init.c | 21 +++++++++++++++++++++ drivers/scsi/qla2xxx/qla_os.c | 6 +++--- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index b51ce8f59cb9..ca2f660a5438 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -48,6 +48,7 @@ extern void qla2x00_update_fcport(scsi_qla_host_t *, fc_port_t *); extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *); extern void qla2x00_alloc_fw_dump(scsi_qla_host_t *); +extern void qla2x00_try_to_stop_firmware(scsi_qla_host_t *); /* * Global Data in qla_os.c source file. diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d5e0a124c4f4..08cb5e3fb553 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3948,3 +3948,24 @@ qla24xx_load_risc(scsi_qla_host_t *ha, uint32_t *srisc_addr) fail_fw_integrity: return QLA_FUNCTION_FAILED; } + +void +qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) +{ + int ret, retries; + + if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha)) + return; + + ret = qla2x00_stop_firmware(ha); + for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) { + qla2x00_reset_chip(ha); + if (qla2x00_chip_diag(ha) != QLA_SUCCESS) + continue; + if (qla2x00_setup_chip(ha) != QLA_SUCCESS) + continue; + qla_printk(KERN_INFO, ha, + "Attempting retry of stop-firmware command...\n"); + ret = qla2x00_stop_firmware(ha); + } +} diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 34b6eb71e450..54f561d9c7a7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1712,8 +1712,10 @@ qla2x00_free_device(scsi_qla_host_t *ha) if (ha->eft) qla2x00_trace_control(ha, TC_DISABLE, 0, 0); + ha->flags.online = 0; + /* Stop currently executing firmware. */ - qla2x00_stop_firmware(ha); + qla2x00_try_to_stop_firmware(ha); /* turn-off interrupts on the card */ if (ha->interrupts_on) @@ -1721,8 +1723,6 @@ qla2x00_free_device(scsi_qla_host_t *ha) qla2x00_mem_free(ha); - ha->flags.online = 0; - /* Detach interrupts */ if (ha->host->irq) free_irq(ha->host->irq, ha); -- cgit v1.2.3 From df7baa506c2db1c2d12abd6f05c43f911da55a2e Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 13 Oct 2006 09:33:39 -0700 Subject: [SCSI] qla2xxx: Correct QUEUE_FULL handling. - Drop queue-depths across all luns for a given fcport during TASK_SET_FULL statuses. - Ramp-up I/Os after throttling. - Consolidate completion-status handling of CS_QUEUE_FULL with CS_COMPLETE as ISP24xx firmware no longer reports CS_QUEUE_FULL. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 4 ++ drivers/scsi/qla2xxx/qla_gbl.h | 1 + drivers/scsi/qla2xxx/qla_isr.c | 91 +++++++++++++++++++++++++++++++++++++----- drivers/scsi/qla2xxx/qla_os.c | 21 +++++++++- 4 files changed, 104 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index bab33f6d0bdb..c4fc40f8e8ca 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -1545,6 +1545,9 @@ typedef struct fc_port { spinlock_t rport_lock; struct fc_rport *rport, *drport; u32 supported_classes; + + unsigned long last_queue_full; + unsigned long last_ramp_up; } fc_port_t; /* @@ -2255,6 +2258,7 @@ typedef struct scsi_qla_host { uint16_t mgmt_svr_loop_id; uint32_t login_retry_count; + int max_q_depth; /* Fibre Channel Device List. */ struct list_head fcports; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index ca2f660a5438..32ebeec45ff0 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -62,6 +62,7 @@ extern int ql2xloginretrycount; extern int ql2xfdmienable; extern int ql2xallocfwdump; extern int ql2xextended_error_logging; +extern int ql2xqfullrampup; extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *); diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 626c7178a434..d3b6df4d55c8 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -6,6 +6,8 @@ */ #include "qla_def.h" +#include + static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); static void qla2x00_async_event(scsi_qla_host_t *, uint16_t *); static void qla2x00_process_completed_request(struct scsi_qla_host *, uint32_t); @@ -593,6 +595,67 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint16_t *mb) } } +static void +qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, void *data) +{ + fc_port_t *fcport = data; + + if (fcport->ha->max_q_depth <= sdev->queue_depth) + return; + + if (sdev->ordered_tags) + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, + sdev->queue_depth + 1); + else + scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, + sdev->queue_depth + 1); + + fcport->last_ramp_up = jiffies; + + DEBUG2(qla_printk(KERN_INFO, fcport->ha, + "scsi(%ld:%d:%d:%d): Queue depth adjusted-up to %d.\n", + fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, + sdev->queue_depth)); +} + +static void +qla2x00_adjust_sdev_qdepth_down(struct scsi_device *sdev, void *data) +{ + fc_port_t *fcport = data; + + if (!scsi_track_queue_full(sdev, sdev->queue_depth - 1)) + return; + + DEBUG2(qla_printk(KERN_INFO, fcport->ha, + "scsi(%ld:%d:%d:%d): Queue depth adjusted-down to %d.\n", + fcport->ha->host_no, sdev->channel, sdev->id, sdev->lun, + sdev->queue_depth)); +} + +static inline void +qla2x00_ramp_up_queue_depth(scsi_qla_host_t *ha, srb_t *sp) +{ + fc_port_t *fcport; + struct scsi_device *sdev; + + sdev = sp->cmd->device; + if (sdev->queue_depth >= ha->max_q_depth) + return; + + fcport = sp->fcport; + if (time_before(jiffies, + fcport->last_ramp_up + ql2xqfullrampup * HZ)) + return; + if (time_before(jiffies, + fcport->last_queue_full + ql2xqfullrampup * HZ)) + return; + + spin_unlock_irq(&ha->hardware_lock); + starget_for_each_device(sdev->sdev_target, fcport, + qla2x00_adjust_sdev_qdepth_up); + spin_lock_irq(&ha->hardware_lock); +} + /** * qla2x00_process_completed_request() - Process a Fast Post response. * @ha: SCSI driver HA context @@ -624,6 +687,8 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index) /* Save ISP completion status */ sp->cmd->result = DID_OK << 16; + + qla2x00_ramp_up_queue_depth(ha, sp); qla2x00_sp_compl(ha, sp); } else { DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n", @@ -823,6 +888,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) */ switch (comp_status) { case CS_COMPLETE: + case CS_QUEUE_FULL: if (scsi_status == 0) { cp->result = DID_OK << 16; break; @@ -849,6 +915,20 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) } cp->result = DID_OK << 16 | lscsi_status; + if (lscsi_status == SAM_STAT_TASK_SET_FULL) { + DEBUG2(printk(KERN_INFO + "scsi(%ld): QUEUE FULL status detected " + "0x%x-0x%x.\n", ha->host_no, comp_status, + scsi_status)); + + /* Adjust queue depth for all luns on the port. */ + fcport->last_queue_full = jiffies; + spin_unlock_irq(&ha->hardware_lock); + starget_for_each_device(cp->device->sdev_target, + fcport, qla2x00_adjust_sdev_qdepth_down); + spin_lock_irq(&ha->hardware_lock); + break; + } if (lscsi_status != SS_CHECK_CONDITION) break; @@ -1066,17 +1146,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) qla2x00_mark_device_lost(ha, fcport, 1, 1); break; - case CS_QUEUE_FULL: - DEBUG2(printk(KERN_INFO - "scsi(%ld): QUEUE FULL status detected 0x%x-0x%x.\n", - ha->host_no, comp_status, scsi_status)); - - /* SCSI Mid-Layer handles device queue full */ - - cp->result = DID_OK << 16 | lscsi_status; - - break; - default: DEBUG3(printk("scsi(%ld): Error detected (unknown status) " "0x%x-0x%x.\n", ha->host_no, comp_status, scsi_status)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 54f561d9c7a7..208607be78c7 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -77,6 +77,19 @@ MODULE_PARM_DESC(ql2xfdmienable, "Enables FDMI registratons " "Default is 0 - no FDMI. 1 - perfom FDMI."); +#define MAX_Q_DEPTH 32 +static int ql2xmaxqdepth = MAX_Q_DEPTH; +module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(ql2xmaxqdepth, + "Maximum queue depth to report for target devices."); + +int ql2xqfullrampup = 120; +module_param(ql2xqfullrampup, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(ql2xqfullrampup, + "Number of seconds to wait to begin to ramp-up the queue " + "depth for a device after a queue-full condition has been " + "detected. Default is 120 seconds."); + /* * SCSI host template entry points */ @@ -1104,9 +1117,9 @@ qla2xxx_slave_configure(struct scsi_device *sdev) struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) - scsi_activate_tcq(sdev, 32); + scsi_activate_tcq(sdev, ha->max_q_depth); else - scsi_deactivate_tcq(sdev, 32); + scsi_deactivate_tcq(sdev, ha->max_q_depth); rport->dev_loss_tmo = ha->port_down_retry_count + 5; @@ -1413,6 +1426,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; + ha->max_q_depth = MAX_Q_DEPTH; + if (ql2xmaxqdepth != 0 && ql2xmaxqdepth <= 0xffffU) + ha->max_q_depth = ql2xmaxqdepth; + /* Assign ISP specific operations. */ ha->isp_ops.pci_config = qla2100_pci_config; ha->isp_ops.reset_chip = qla2x00_reset_chip; -- cgit v1.2.3 From 7c83a3ceb6d06e7cb908f5102687c9661e7d4d0a Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Fri, 13 Oct 2006 09:33:40 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.01.07-k3. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index e57bf45a3393..1fa0bce6b24e 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.01.07-k2" +#define QLA2XXX_VERSION "8.01.07-k3" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 1 -- cgit v1.2.3 From 9c3121feef7e1fba86f74b2677e6f54e7153d149 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Fri, 13 Oct 2006 10:22:50 -0500 Subject: [SCSI] ibmvscsi: correctly reenable CRQ The "ibmvscsi: treat busy and error conditions separately" patch submitted by Dave Boutcher back in June incorrectly reenables the CRQ. The broken logic causes the adapter to get disabled if the CRQ connection happens to close temporarily. This patch "fixes that obviously wrong logic check" (Dave's words). Signed-off-by: Santiago Leon Signed-off-by: David Boutcher Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 669ea4fff166..fbc1d5c3b0a7 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1213,7 +1213,7 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, "ibmvscsi: Re-enabling adapter!\n"); purge_requests(hostdata, DID_REQUEUE); if ((ibmvscsi_reenable_crq_queue(&hostdata->queue, - hostdata) == 0) || + hostdata)) || (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0))) { atomic_set(&hostdata->request_limit, -- cgit v1.2.3 From 3fc2aef5227dda464560a3fdafc9f4c7ce10210f Mon Sep 17 00:00:00 2001 From: Sergey Kononenko Date: Sun, 15 Oct 2006 03:12:08 +0300 Subject: [SCSI] aic94xx: Supermicro motherboards support Add PCI id. Plus correct for possibly missing resistor that can cause FLASHEX to have the wrong value. Signed-off-by: Sergey Kononenko Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_hwi.h | 1 + drivers/scsi/aic94xx/aic94xx_init.c | 2 ++ drivers/scsi/aic94xx/aic94xx_sds.c | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h index 14319d1d6804..7b6aca02cf70 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.h +++ b/drivers/scsi/aic94xx/aic94xx_hwi.h @@ -46,6 +46,7 @@ #define PCI_DEVICE_ID_ADAPTEC2_RAZOR10 0x410 #define PCI_DEVICE_ID_ADAPTEC2_RAZOR12 0x412 #define PCI_DEVICE_ID_ADAPTEC2_RAZOR1E 0x41E +#define PCI_DEVICE_ID_ADAPTEC2_RAZOR1F 0x41F #define PCI_DEVICE_ID_ADAPTEC2_RAZOR30 0x430 #define PCI_DEVICE_ID_ADAPTEC2_RAZOR32 0x432 #define PCI_DEVICE_ID_ADAPTEC2_RAZOR3E 0x43E diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 99743ca29ca1..a4cc432bbdab 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -814,6 +814,8 @@ static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { 0, 0, 1}, {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1E), 0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1F), + 0, 0, 1}, {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR30), 0, 0, 2}, {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR32), diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index 83574b5b4e69..de7c04d4254d 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -630,10 +630,6 @@ static int asd_flash_getid(struct asd_ha_struct *asd_ha) reg = asd_read_reg_dword(asd_ha, EXSICNFGR); - if (!(reg & FLASHEX)) { - ASD_DPRINTK("flash doesn't exist\n"); - return -ENOENT; - } if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR, &asd_ha->hw_prof.flash.bar)) { asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n", -- cgit v1.2.3 From 031280f6e73d9177c93333c96e37eb05f2522faa Mon Sep 17 00:00:00 2001 From: Andrey Mirkin <(amirkin@sw.ru)> Date: Mon, 16 Oct 2006 12:08:43 +0400 Subject: [SCSI] megaraid_{mm,mbox}: 64-bit DMA capability fix It is known that 2 LSI Logic MegaRAID SATA RAID Controllers (150-4 and 150-6) don't support 64-bit DMA. Unfortunately currently this check is wrong and driver sets 64-bit DMA mode for these devices. Signed-off-by: Andrey Mirkin Acked-by: "Ju, Seokmann" Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index c0edb662d863..7bac86dda88f 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -884,7 +884,7 @@ megaraid_init_mbox(adapter_t *adapter) if (((magic64 == HBA_SIGNATURE_64_BIT) && ((adapter->pdev->subsystem_device != - PCI_SUBSYS_ID_MEGARAID_SATA_150_6) || + PCI_SUBSYS_ID_MEGARAID_SATA_150_6) && (adapter->pdev->subsystem_device != PCI_SUBSYS_ID_MEGARAID_SATA_150_4))) || (adapter->pdev->vendor == PCI_VENDOR_ID_LSI_LOGIC && -- cgit v1.2.3 From ed632da84c51a39fd9c982991e0f26120a035761 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Mon, 16 Oct 2006 10:06:27 -0500 Subject: [SCSI] add can_queue to host parameters Debugging TCQ issues has shown me this is a very useful parameter to be able to view. Add it to he host class parameters. Signed-off-by: James Bottomley --- drivers/scsi/scsi_sysfs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index e7fe565b96de..e1a91665d1c2 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -192,6 +192,7 @@ static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); +shost_rd_attr(can_queue, "%hd\n"); shost_rd_attr(sg_tablesize, "%hu\n"); shost_rd_attr(unchecked_isa_dma, "%d\n"); shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); @@ -200,6 +201,7 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { &class_device_attr_unique_id, &class_device_attr_host_busy, &class_device_attr_cmd_per_lun, + &class_device_attr_can_queue, &class_device_attr_sg_tablesize, &class_device_attr_unchecked_isa_dma, &class_device_attr_proc_name, -- cgit v1.2.3 From 47bcd3546d5141e54f15e40a20dc01d7c5f5a473 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 16 Oct 2006 16:55:46 +0100 Subject: [SCSI] Switch fdomain to the pci_get API Doesn't make the hardware hot pluggable but does ensure the driver won't crash when another device is hot-unplugged at the wrong moment. Soon I propose to deprecate pci_find_device() and some of its friends. Signed-off-by: Alan Cox Signed-off-by: James Bottomley --- drivers/scsi/fdomain.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 41b05fc45380..2a964240cf4c 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -387,6 +387,7 @@ static void __iomem * bios_mem; static int bios_major; static int bios_minor; static int PCI_bus; +static struct pci_dev *PCI_dev; static int Quantum; /* Quantum board variant */ static int interrupt_level; static volatile int in_command; @@ -812,9 +813,10 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_ PCI_DEVICE_ID_FD_36C70 ); #endif - if ((pdev = pci_find_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) + if ((pdev = pci_get_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL) return 0; - if (pci_enable_device(pdev)) return 0; + if (pci_enable_device(pdev)) + goto fail; #if DEBUG_DETECT printk( "scsi: TMC-3260 detect:" @@ -831,7 +833,7 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_ pci_irq = pdev->irq; if (!request_region( pci_base, 0x10, "fdomain" )) - return 0; + goto fail; /* Now we have the I/O base address and interrupt from the PCI configuration registers. */ @@ -848,17 +850,22 @@ static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_ if (!fdomain_is_valid_port(pci_base)) { printk(KERN_ERR "scsi: PCI card detected, but driver not loaded (invalid port)\n" ); release_region(pci_base, 0x10); - return 0; + goto fail; } /* Fill in a few global variables. Ugh. */ bios_major = bios_minor = -1; PCI_bus = 1; + PCI_dev = pdev; Quantum = 0; bios_base = 0; return 1; +fail: + pci_dev_put(pdev); + return 0; } + #endif struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) @@ -909,8 +916,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) if (setup_called) { printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); } - release_region(port_base, 0x10); - return NULL; + goto fail; } if (this_id) { @@ -942,8 +948,7 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) /* Log IRQ with kernel */ if (!interrupt_level) { printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); - release_region(port_base, 0x10); - return NULL; + goto fail; } else { /* Register the IRQ with the kernel */ @@ -964,11 +969,14 @@ struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt ) printk(KERN_ERR " Send mail to faith@acm.org\n" ); } printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); - release_region(port_base, 0x10); - return NULL; + goto fail; } } return shpnt; +fail: + pci_dev_put(pdev); + release_region(port_base, 0x10); + return NULL; } static int fdomain_16x0_detect(struct scsi_host_template *tpnt) @@ -1714,6 +1722,8 @@ static int fdomain_16x0_release(struct Scsi_Host *shpnt) free_irq(shpnt->irq, shpnt); if (shpnt->io_port && shpnt->n_io_port) release_region(shpnt->io_port, shpnt->n_io_port); + if (PCI_bus) + pci_dev_put(PCI_dev); return 0; } -- cgit v1.2.3 From 43a145a3440c5c5f24ff2888801e40e2242187e6 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 16 Oct 2006 18:09:38 -0400 Subject: [SCSI] iscsi class: fix slab corruption during restart The transport class recv mempools are causing slab corruption. We could hack around netlink's lack of mempool support like dm, but it is just too ulgy (dm's hack is ugly enough :) when you need to support broadcast. This patch removes the recv pools. We have not used them even when we were allocting 20 MB per session and the system only had 64 MBs. And we have no pools on the send side and have been ok there. When Peter's work gets merged we can use that since the network guys are in favor of that approach and are not going to add mempools everywhere. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 246 +++--------------------------------- include/scsi/scsi_transport_iscsi.h | 4 - 2 files changed, 17 insertions(+), 233 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 7b0019cccce3..2d3baa99ca25 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -21,7 +21,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include -#include #include #include #include @@ -149,30 +148,6 @@ static DECLARE_TRANSPORT_CLASS(iscsi_connection_class, static struct sock *nls; static DEFINE_MUTEX(rx_queue_mutex); -struct mempool_zone { - mempool_t *pool; - atomic_t allocated; - int size; - int hiwat; - struct list_head freequeue; - spinlock_t freelock; -}; - -static struct mempool_zone *z_reply; - -/* - * Z_MAX_* - actual mempool size allocated at the mempool_zone_init() time - * Z_HIWAT_* - zone's high watermark when if_error bit will be set to -ENOMEM - * so daemon will notice OOM on NETLINK tranposrt level and will - * be able to predict or change operational behavior - */ -#define Z_MAX_REPLY 8 -#define Z_HIWAT_REPLY 6 -#define Z_MAX_PDU 8 -#define Z_HIWAT_PDU 6 -#define Z_MAX_ERROR 16 -#define Z_HIWAT_ERROR 12 - static LIST_HEAD(sesslist); static DEFINE_SPINLOCK(sesslock); static LIST_HEAD(connlist); @@ -414,59 +389,11 @@ int iscsi_destroy_session(struct iscsi_cls_session *session) } EXPORT_SYMBOL_GPL(iscsi_destroy_session); -static void mempool_zone_destroy(struct mempool_zone *zp) -{ - mempool_destroy(zp->pool); - kfree(zp); -} - -static void* -mempool_zone_alloc_skb(gfp_t gfp_mask, void *pool_data) -{ - struct mempool_zone *zone = pool_data; - - return alloc_skb(zone->size, gfp_mask); -} - -static void -mempool_zone_free_skb(void *element, void *pool_data) -{ - kfree_skb(element); -} - -static struct mempool_zone * -mempool_zone_init(unsigned max, unsigned size, unsigned hiwat) -{ - struct mempool_zone *zp; - - zp = kzalloc(sizeof(*zp), GFP_KERNEL); - if (!zp) - return NULL; - - zp->size = size; - zp->hiwat = hiwat; - INIT_LIST_HEAD(&zp->freequeue); - spin_lock_init(&zp->freelock); - atomic_set(&zp->allocated, 0); - - zp->pool = mempool_create(max, mempool_zone_alloc_skb, - mempool_zone_free_skb, zp); - if (!zp->pool) { - kfree(zp); - return NULL; - } - - return zp; -} - static void iscsi_conn_release(struct device *dev) { struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev); struct device *parent = conn->dev.parent; - mempool_zone_destroy(conn->z_pdu); - mempool_zone_destroy(conn->z_error); - kfree(conn); put_device(parent); } @@ -476,31 +403,6 @@ static int iscsi_is_conn_dev(const struct device *dev) return dev->release == iscsi_conn_release; } -static int iscsi_create_event_pools(struct iscsi_cls_conn *conn) -{ - conn->z_pdu = mempool_zone_init(Z_MAX_PDU, - NLMSG_SPACE(sizeof(struct iscsi_uevent) + - sizeof(struct iscsi_hdr) + - DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH), - Z_HIWAT_PDU); - if (!conn->z_pdu) { - dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " - "pdu zone for new conn\n"); - return -ENOMEM; - } - - conn->z_error = mempool_zone_init(Z_MAX_ERROR, - NLMSG_SPACE(sizeof(struct iscsi_uevent)), - Z_HIWAT_ERROR); - if (!conn->z_error) { - dev_printk(KERN_ERR, &conn->dev, "iscsi: can not allocate " - "error zone for new conn\n"); - mempool_zone_destroy(conn->z_pdu); - return -ENOMEM; - } - return 0; -} - /** * iscsi_create_conn - create iscsi class connection * @session: iscsi cls session @@ -533,12 +435,9 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) conn->transport = transport; conn->cid = cid; - if (iscsi_create_event_pools(conn)) - goto free_conn; - /* this is released in the dev's release function */ if (!get_device(&session->dev)) - goto free_conn_pools; + goto free_conn; snprintf(conn->dev.bus_id, BUS_ID_SIZE, "connection%d:%u", session->sid, cid); @@ -555,8 +454,6 @@ iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) release_parent_ref: put_device(&session->dev); -free_conn_pools: - free_conn: kfree(conn); return NULL; @@ -599,81 +496,31 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt) return NULL; } -static inline struct list_head *skb_to_lh(struct sk_buff *skb) -{ - return (struct list_head *)&skb->cb; -} - -static void -mempool_zone_complete(struct mempool_zone *zone) -{ - unsigned long flags; - struct list_head *lh, *n; - - spin_lock_irqsave(&zone->freelock, flags); - list_for_each_safe(lh, n, &zone->freequeue) { - struct sk_buff *skb = (struct sk_buff *)((char *)lh - - offsetof(struct sk_buff, cb)); - if (!skb_shared(skb)) { - list_del(skb_to_lh(skb)); - mempool_free(skb, zone->pool); - atomic_dec(&zone->allocated); - } - } - spin_unlock_irqrestore(&zone->freelock, flags); -} - -static struct sk_buff* -mempool_zone_get_skb(struct mempool_zone *zone) -{ - struct sk_buff *skb; - - skb = mempool_alloc(zone->pool, GFP_ATOMIC); - if (skb) - atomic_inc(&zone->allocated); - return skb; -} - static int -iscsi_broadcast_skb(struct mempool_zone *zone, struct sk_buff *skb, gfp_t gfp) +iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp) { - unsigned long flags; int rc; - skb_get(skb); rc = netlink_broadcast(nls, skb, 0, 1, gfp); if (rc < 0) { - mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc); return rc; } - spin_lock_irqsave(&zone->freelock, flags); - INIT_LIST_HEAD(skb_to_lh(skb)); - list_add(skb_to_lh(skb), &zone->freequeue); - spin_unlock_irqrestore(&zone->freelock, flags); return 0; } static int -iscsi_unicast_skb(struct mempool_zone *zone, struct sk_buff *skb, int pid) +iscsi_unicast_skb(struct sk_buff *skb, int pid) { - unsigned long flags; int rc; - skb_get(skb); rc = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); if (rc < 0) { - mempool_free(skb, zone->pool); printk(KERN_ERR "iscsi: can not unicast skb (%d)\n", rc); return rc; } - spin_lock_irqsave(&zone->freelock, flags); - INIT_LIST_HEAD(skb_to_lh(skb)); - list_add(skb_to_lh(skb), &zone->freequeue); - spin_unlock_irqrestore(&zone->freelock, flags); - return 0; } @@ -692,9 +539,7 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, if (!priv) return -EINVAL; - mempool_zone_complete(conn->z_pdu); - - skb = mempool_zone_get_skb(conn->z_pdu); + skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { iscsi_conn_error(conn, ISCSI_ERR_CONN_FAILED); dev_printk(KERN_ERR, &conn->dev, "iscsi: can not deliver " @@ -707,15 +552,13 @@ int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, memset(ev, 0, sizeof(*ev)); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_RECV_PDU; - if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) - ev->iferror = -ENOMEM; ev->r.recv_req.cid = conn->cid; ev->r.recv_req.sid = iscsi_conn_get_sid(conn); pdu = (char*)ev + sizeof(*ev); memcpy(pdu, hdr, sizeof(struct iscsi_hdr)); memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size); - return iscsi_unicast_skb(conn->z_pdu, skb, priv->daemon_pid); + return iscsi_unicast_skb(skb, priv->daemon_pid); } EXPORT_SYMBOL_GPL(iscsi_recv_pdu); @@ -731,9 +574,7 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) if (!priv) return; - mempool_zone_complete(conn->z_error); - - skb = mempool_zone_get_skb(conn->z_error); + skb = alloc_skb(len, GFP_ATOMIC); if (!skb) { dev_printk(KERN_ERR, &conn->dev, "iscsi: gracefully ignored " "conn error (%d)\n", error); @@ -744,13 +585,11 @@ void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) ev = NLMSG_DATA(nlh); ev->transport_handle = iscsi_handle(conn->transport); ev->type = ISCSI_KEVENT_CONN_ERROR; - if (atomic_read(&conn->z_error->allocated) >= conn->z_error->hiwat) - ev->iferror = -ENOMEM; ev->r.connerror.error = error; ev->r.connerror.cid = conn->cid; ev->r.connerror.sid = iscsi_conn_get_sid(conn); - iscsi_broadcast_skb(conn->z_error, skb, GFP_ATOMIC); + iscsi_broadcast_skb(skb, GFP_ATOMIC); dev_printk(KERN_INFO, &conn->dev, "iscsi: detected conn error (%d)\n", error); @@ -767,9 +606,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, int flags = multi ? NLM_F_MULTI : 0; int t = done ? NLMSG_DONE : type; - mempool_zone_complete(z_reply); - - skb = mempool_zone_get_skb(z_reply); + skb = alloc_skb(len, GFP_ATOMIC); /* * FIXME: * user is supposed to react on iferror == -ENOMEM; @@ -780,7 +617,7 @@ iscsi_if_send_reply(int pid, int seq, int type, int done, int multi, nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); nlh->nlmsg_flags = flags; memcpy(NLMSG_DATA(nlh), payload, size); - return iscsi_unicast_skb(z_reply, skb, pid); + return iscsi_unicast_skb(skb, pid); } static int @@ -810,9 +647,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) do { int actual_size; - mempool_zone_complete(conn->z_pdu); - - skbstat = mempool_zone_get_skb(conn->z_pdu); + skbstat = alloc_skb(len, GFP_ATOMIC); if (!skbstat) { dev_printk(KERN_ERR, &conn->dev, "iscsi: can not " "deliver stats: OOM\n"); @@ -825,8 +660,6 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) memset(evstat, 0, sizeof(*evstat)); evstat->transport_handle = iscsi_handle(conn->transport); evstat->type = nlh->nlmsg_type; - if (atomic_read(&conn->z_pdu->allocated) >= conn->z_pdu->hiwat) - evstat->iferror = -ENOMEM; evstat->u.get_stats.cid = ev->u.get_stats.cid; evstat->u.get_stats.sid = @@ -845,7 +678,7 @@ iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) skb_trim(skbstat, NLMSG_ALIGN(actual_size)); nlhstat->nlmsg_len = actual_size; - err = iscsi_unicast_skb(conn->z_pdu, skbstat, priv->daemon_pid); + err = iscsi_unicast_skb(skbstat, priv->daemon_pid); } while (err < 0 && err != -ECONNREFUSED); return err; @@ -876,9 +709,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn) session = iscsi_dev_to_session(conn->dev.parent); shost = iscsi_session_to_shost(session); - mempool_zone_complete(conn->z_pdu); - - skb = mempool_zone_get_skb(conn->z_pdu); + skb = alloc_skb(len, GFP_KERNEL); if (!skb) { dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session creation event\n"); @@ -896,7 +727,7 @@ int iscsi_if_destroy_session_done(struct iscsi_cls_conn *conn) * this will occur if the daemon is not up, so we just warn * the user and when the daemon is restarted it will handle it */ - rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL); + rc = iscsi_broadcast_skb(skb, GFP_KERNEL); if (rc < 0) dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session destruction event. Check iscsi daemon\n"); @@ -939,9 +770,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn) session = iscsi_dev_to_session(conn->dev.parent); shost = iscsi_session_to_shost(session); - mempool_zone_complete(conn->z_pdu); - - skb = mempool_zone_get_skb(conn->z_pdu); + skb = alloc_skb(len, GFP_KERNEL); if (!skb) { dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session creation event\n"); @@ -959,7 +788,7 @@ int iscsi_if_create_session_done(struct iscsi_cls_conn *conn) * this will occur if the daemon is not up, so we just warn * the user and when the daemon is restarted it will handle it */ - rc = iscsi_broadcast_skb(conn->z_pdu, skb, GFP_KERNEL); + rc = iscsi_broadcast_skb(skb, GFP_KERNEL); if (rc < 0) dev_printk(KERN_ERR, &conn->dev, "Cannot notify userspace of " "session creation event. Check iscsi daemon\n"); @@ -1278,9 +1107,6 @@ iscsi_if_rx(struct sock *sk, int len) err = iscsi_if_send_reply( NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq, nlh->nlmsg_type, 0, 0, ev, sizeof(*ev)); - if (atomic_read(&z_reply->allocated) >= - z_reply->hiwat) - ev->iferror = -ENOMEM; } while (err < 0 && err != -ECONNREFUSED); skb_pull(skb, rlen); } @@ -1584,32 +1410,6 @@ int iscsi_unregister_transport(struct iscsi_transport *tt) } EXPORT_SYMBOL_GPL(iscsi_unregister_transport); -static int -iscsi_rcv_nl_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct netlink_notify *n = ptr; - - if (event == NETLINK_URELEASE && - n->protocol == NETLINK_ISCSI && n->pid) { - struct iscsi_cls_conn *conn; - unsigned long flags; - - mempool_zone_complete(z_reply); - spin_lock_irqsave(&connlock, flags); - list_for_each_entry(conn, &connlist, conn_list) { - mempool_zone_complete(conn->z_error); - mempool_zone_complete(conn->z_pdu); - } - spin_unlock_irqrestore(&connlock, flags); - } - - return NOTIFY_DONE; -} - -static struct notifier_block iscsi_nl_notifier = { - .notifier_call = iscsi_rcv_nl_event, -}; - static __init int iscsi_transport_init(void) { int err; @@ -1633,25 +1433,15 @@ static __init int iscsi_transport_init(void) if (err) goto unregister_conn_class; - err = netlink_register_notifier(&iscsi_nl_notifier); - if (err) - goto unregister_session_class; - nls = netlink_kernel_create(NETLINK_ISCSI, 1, iscsi_if_rx, THIS_MODULE); if (!nls) { err = -ENOBUFS; - goto unregister_notifier; + goto unregister_session_class; } - z_reply = mempool_zone_init(Z_MAX_REPLY, - NLMSG_SPACE(sizeof(struct iscsi_uevent)), Z_HIWAT_REPLY); - if (z_reply) - return 0; + return 0; - sock_release(nls->sk_socket); -unregister_notifier: - netlink_unregister_notifier(&iscsi_nl_notifier); unregister_session_class: transport_class_unregister(&iscsi_session_class); unregister_conn_class: @@ -1665,9 +1455,7 @@ unregister_transport_class: static void __exit iscsi_transport_exit(void) { - mempool_zone_destroy(z_reply); sock_release(nls->sk_socket); - netlink_unregister_notifier(&iscsi_nl_notifier); transport_class_unregister(&iscsi_connection_class); transport_class_unregister(&iscsi_session_class); transport_class_unregister(&iscsi_host_class); diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 39e833260bd0..4b95c89c95c9 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -29,7 +29,6 @@ struct scsi_transport_template; struct iscsi_transport; struct Scsi_Host; -struct mempool_zone; struct iscsi_cls_conn; struct iscsi_conn; struct iscsi_cmd_task; @@ -157,9 +156,6 @@ struct iscsi_cls_conn { int active; /* must be accessed with the connlock */ struct device dev; /* sysfs transport/container device */ - struct mempool_zone *z_error; - struct mempool_zone *z_pdu; - struct list_head freequeue; }; #define iscsi_dev_to_conn(_dev) \ -- cgit v1.2.3 From 98644047916c24258fb47c3dab2bed8a44f53b83 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 16 Oct 2006 18:09:39 -0400 Subject: [SCSI] libiscsi: fix oops in connection create failure path If connection creation fails we end up calling list_del on a invalid struct. This then causes an oops. We are not acutally using the lists (old MCS code we thought might be useful elsewhere) so this patch just removes that code. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 38 ++++++++------------------------------ include/scsi/libiscsi.h | 3 --- 2 files changed, 8 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index c542d0e95e68..1000fe936791 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -778,6 +778,10 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) } conn = session->leadconn; + if (!conn) { + reason = FAILURE_SESSION_FREED; + goto fault; + } if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*))) { @@ -1377,7 +1381,6 @@ iscsi_session_setup(struct iscsi_transport *iscsit, } spin_lock_init(&session->lock); - INIT_LIST_HEAD(&session->connections); /* initialize immediate command pool */ if (iscsi_pool_init(&session->mgmtpool, session->mgmtpool_max, @@ -1580,16 +1583,11 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) kfree(conn->persistent_address); __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, sizeof(void*)); - list_del(&conn->item); - if (list_empty(&session->connections)) + if (session->leadconn == conn) { session->leadconn = NULL; - if (session->leadconn && session->leadconn == conn) - session->leadconn = container_of(session->connections.next, - struct iscsi_conn, item); - - if (session->leadconn == NULL) /* no connections exits.. reset sequencing */ session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; + } spin_unlock_bh(&session->lock); kfifo_free(conn->immqueue); @@ -1777,32 +1775,12 @@ int iscsi_conn_bind(struct iscsi_cls_session *cls_session, struct iscsi_cls_conn *cls_conn, int is_leading) { struct iscsi_session *session = class_to_transport_session(cls_session); - struct iscsi_conn *tmp = ERR_PTR(-EEXIST), *conn = cls_conn->dd_data; + struct iscsi_conn *conn = cls_conn->dd_data; - /* lookup for existing connection */ spin_lock_bh(&session->lock); - list_for_each_entry(tmp, &session->connections, item) { - if (tmp == conn) { - if (conn->c_stage != ISCSI_CONN_STOPPED || - conn->stop_stage == STOP_CONN_TERM) { - printk(KERN_ERR "iscsi: can't bind " - "non-stopped connection (%d:%d)\n", - conn->c_stage, conn->stop_stage); - spin_unlock_bh(&session->lock); - return -EIO; - } - break; - } - } - if (tmp != conn) { - /* bind new iSCSI connection to session */ - conn->session = session; - list_add(&conn->item, &session->connections); - } - spin_unlock_bh(&session->lock); - if (is_leading) session->leadconn = conn; + spin_unlock_bh(&session->lock); /* * Unblock xmitworker(), Login Phase will pass through. diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 401192e56e50..61eebec00a7b 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -136,7 +136,6 @@ struct iscsi_conn { /* control data */ int id; /* CID */ - struct list_head item; /* maintains list of conns */ int c_stage; /* connection state */ /* * Preallocated buffer for pdus that have data but do not @@ -235,10 +234,8 @@ struct iscsi_session { * - mgmtpool, * * - r2tpool */ int state; /* session state */ - struct list_head item; int age; /* counts session re-opens */ - struct list_head connections; /* list of connections */ int cmds_max; /* size of cmds array */ struct iscsi_cmd_task **cmds; /* Original Cmds arr */ struct iscsi_queue cmdpool; /* PDU's pool */ -- cgit v1.2.3 From cd529a46e17b43976d05c1e2ece2676ec7941cc8 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 16 Oct 2006 18:09:40 -0400 Subject: [SCSI] libiscsi: fix missed iscsi_task_put in xmit error path from bhalevy@gmail.com: It looks like change 652 to libiscsi.c added some dead code around line 670 if (rc) { spin_unlock_bh(&conn->session->lock); goto again; } since 5 lines above we goto again if (rc). It looks like the previous if (rc) should go away if we want to put the ctask before breaking out of the while loop with "goto again" (see following patch). Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1000fe936791..e3a2ec253cf1 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -661,8 +661,6 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) spin_unlock_bh(&conn->session->lock); rc = tt->xmit_cmd_task(conn, conn->ctask); - if (rc) - goto again; spin_lock_bh(&conn->session->lock); __iscsi_put_ctask(conn->ctask); -- cgit v1.2.3 From 5831c737f724aa6a655a908d202221f079f30036 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 16 Oct 2006 18:09:41 -0400 Subject: [SCSI] libiscsi: fix aen support We have been dropping the pdu. We should just send it to userspace and let it handle it. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index e3a2ec253cf1..f5a9560b357f 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -481,8 +481,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, break; case ISCSI_OP_ASYNC_EVENT: conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; - /* we need sth like iscsi_async_event_rsp() */ - rc = ISCSI_ERR_BAD_OPCODE; + if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) + rc = ISCSI_ERR_CONN_FAILED; break; default: rc = ISCSI_ERR_BAD_OPCODE; -- cgit v1.2.3 From b5072ea0910e5c8c79b8313e0ef70ca763983dbf Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 16 Oct 2006 18:09:42 -0400 Subject: [SCSI] libiscsi: fix logout pdu processing According to the iscsi RFC, we cannot send other requests if we have sent a logout pdu. This patch enforces this requirement by blocking the session and suspending the send thread. Userspace decides if we restart the connection or if we just free everything. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index f5a9560b357f..2865ebd557ef 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -578,6 +578,27 @@ void iscsi_conn_failure(struct iscsi_conn *conn, enum iscsi_err err) } EXPORT_SYMBOL_GPL(iscsi_conn_failure); +static int iscsi_xmit_imm_task(struct iscsi_conn *conn) +{ + struct iscsi_hdr *hdr = conn->mtask->hdr; + int rc, was_logout = 0; + + if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) { + conn->session->state = ISCSI_STATE_IN_RECOVERY; + iscsi_block_session(session_to_cls(conn->session)); + was_logout = 1; + } + rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); + if (rc) + return rc; + + if (was_logout) { + set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); + return -ENODATA; + } + return 0; +} + /** * iscsi_data_xmit - xmit any command into the scheduled connection * @conn: iscsi connection @@ -623,7 +644,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) conn->ctask = NULL; } if (conn->mtask) { - rc = tt->xmit_mgmt_task(conn, conn->mtask); + rc = iscsi_xmit_imm_task(conn); if (rc) goto again; /* done with this in-progress mtask */ @@ -638,7 +659,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) list_add_tail(&conn->mtask->running, &conn->mgmt_run_list); spin_unlock_bh(&conn->session->lock); - rc = tt->xmit_mgmt_task(conn, conn->mtask); + rc = iscsi_xmit_imm_task(conn); if (rc) goto again; } -- cgit v1.2.3 From cd00b7f5d814ba87b36371f122ce36ba4a88ba69 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 17 Oct 2006 09:32:06 -0400 Subject: [SCSI] qla1280 bus reset typo Fix typo in check of return value of qla1280_bus_reset() which would result in an adapter reset in addition to the bus reset. Signed-off-by: Jes Sorensen Signed-off-by: James Bottomley --- drivers/scsi/qla1280.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 2521d548dd59..16af5b79e587 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -931,11 +931,10 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action) case BUS_RESET: if (qla1280_verbose) - printk(KERN_INFO "qla1280(%ld:%d): Issuing BUS " - "DEVICE RESET\n", ha->host_no, bus); - if (qla1280_bus_reset(ha, bus == 0)) + printk(KERN_INFO "qla1280(%ld:%d): Issued bus " + "reset.\n", ha->host_no, bus); + if (qla1280_bus_reset(ha, bus) == 0) result = SUCCESS; - break; case ADAPTER_RESET: -- cgit v1.2.3 From 5a09e39810ae0465016c380962e12dd115779b87 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Fri, 20 Oct 2006 09:58:47 +0200 Subject: [SCSI] scsi_debug: support REPORT TARGET PORT GROUPS This patch adds support for REPORT TARGET PORT GROUPS. This is used eg for the multipathing priority callout to determine the path priority. With this patch multipath-tools can use the existing mpath_prio_alua callout to exercise the path priority grouping. Signed-off-by: Hannes Reinecke Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 141 +++++++++++++++++++++++++++++++++++++++++----- include/scsi/scsi.h | 3 + 2 files changed, 130 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 9c0f35820e3e..30ee3d72c021 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -52,7 +52,7 @@ #include "scsi_debug.h" #define SCSI_DEBUG_VERSION "1.80" -static const char * scsi_debug_version_date = "20060914"; +static const char * scsi_debug_version_date = "20061018"; /* Additional Sense Code (ASC) used */ #define NO_ADDITIONAL_SENSE 0x0 @@ -254,6 +254,8 @@ static int resp_requests(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip); static int resp_start_stop(struct scsi_cmnd * scp, struct sdebug_dev_info * devip); +static int resp_report_tgtpgs(struct scsi_cmnd * scp, + struct sdebug_dev_info * devip); static int resp_readcap(struct scsi_cmnd * SCpnt, struct sdebug_dev_info * devip); static int resp_readcap16(struct scsi_cmnd * SCpnt, @@ -287,9 +289,9 @@ static void __init sdebug_build_parts(unsigned char * ramp); static void __init init_all_queued(void); static void stop_all_queued(void); static int stop_queued_cmnd(struct scsi_cmnd * cmnd); -static int inquiry_evpd_83(unsigned char * arr, int target_dev_id, - int dev_id_num, const char * dev_id_str, - int dev_id_str_len); +static int inquiry_evpd_83(unsigned char * arr, int port_group_id, + int target_dev_id, int dev_id_num, + const char * dev_id_str, int dev_id_str_len); static int inquiry_evpd_88(unsigned char * arr, int target_dev_id); static int do_create_driverfs_files(void); static void do_remove_driverfs_files(void); @@ -422,6 +424,15 @@ int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done) } errsts = resp_readcap16(SCpnt, devip); break; + case MAINTENANCE_IN: + if (MI_REPORT_TARGET_PGS != cmd[1]) { + mk_sense_buffer(devip, ILLEGAL_REQUEST, + INVALID_OPCODE, 0); + errsts = check_condition_result; + break; + } + errsts = resp_report_tgtpgs(SCpnt, devip); + break; case READ_16: case READ_12: case READ_10: @@ -665,8 +676,9 @@ static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; static const char * inq_product_rev = "0004"; -static int inquiry_evpd_83(unsigned char * arr, int target_dev_id, - int dev_id_num, const char * dev_id_str, +static int inquiry_evpd_83(unsigned char * arr, int port_group_id, + int target_dev_id, int dev_id_num, + const char * dev_id_str, int dev_id_str_len) { int num, port_a; @@ -720,6 +732,15 @@ static int inquiry_evpd_83(unsigned char * arr, int target_dev_id, arr[num++] = (port_a >> 16) & 0xff; arr[num++] = (port_a >> 8) & 0xff; arr[num++] = port_a & 0xff; + /* NAA-5, Target port group identifier */ + arr[num++] = 0x61; /* proto=sas, binary */ + arr[num++] = 0x95; /* piv=1, target port group id */ + arr[num++] = 0x0; + arr[num++] = 0x4; + arr[num++] = 0; + arr[num++] = 0; + arr[num++] = (port_group_id >> 8) & 0xff; + arr[num++] = port_group_id & 0xff; /* NAA-5, Target device identifier */ arr[num++] = 0x61; /* proto=sas, binary */ arr[num++] = 0xa3; /* piv=1, target device, naa */ @@ -928,12 +949,12 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, struct sdebug_dev_info * devip) { unsigned char pq_pdt; - unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ]; + unsigned char * arr; unsigned char *cmd = (unsigned char *)scp->cmnd; - int alloc_len, n; + int alloc_len, n, ret; alloc_len = (cmd[3] << 8) + cmd[4]; - memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ); + arr = kzalloc(SDEBUG_MAX_INQ_ARR_SZ, GFP_KERNEL); if (devip->wlun) pq_pdt = 0x1e; /* present, wlun */ else if (scsi_debug_no_lun_0 && (0 == devip->lun)) @@ -944,12 +965,15 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, if (0x2 & cmd[1]) { /* CMDDT bit set */ mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + kfree(arr); return check_condition_result; } else if (0x1 & cmd[1]) { /* EVPD bit set */ - int lu_id_num, target_dev_id, len; + int lu_id_num, port_group_id, target_dev_id, len; char lu_id_str[6]; int host_no = devip->sdbg_host->shost->host_no; + port_group_id = (((host_no + 1) & 0x7f) << 8) + + (devip->channel & 0x7f); if (0 == scsi_debug_vpd_use_hostno) host_no = 0; lu_id_num = devip->wlun ? -1 : (((host_no + 1) * 2000) + @@ -977,8 +1001,9 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, memcpy(&arr[4], lu_id_str, len); } else if (0x83 == cmd[2]) { /* device identification */ arr[1] = cmd[2]; /*sanity */ - arr[3] = inquiry_evpd_83(&arr[4], target_dev_id, - lu_id_num, lu_id_str, len); + arr[3] = inquiry_evpd_83(&arr[4], port_group_id, + target_dev_id, lu_id_num, + lu_id_str, len); } else if (0x84 == cmd[2]) { /* Software interface ident. */ arr[1] = cmd[2]; /*sanity */ arr[3] = inquiry_evpd_84(&arr[4]); @@ -1012,17 +1037,22 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, /* Illegal request, invalid field in cdb */ mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + kfree(arr); return check_condition_result; } len = min(((arr[2] << 8) + arr[3]) + 4, alloc_len); - return fill_from_dev_buffer(scp, arr, + ret = fill_from_dev_buffer(scp, arr, min(len, SDEBUG_MAX_INQ_ARR_SZ)); + kfree(arr); + return ret; } /* drops through here for a standard inquiry */ arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0; /* Removable disk */ arr[2] = scsi_debug_scsi_level; arr[3] = 2; /* response_data_format==2 */ arr[4] = SDEBUG_LONG_INQ_SZ - 5; + if (0 == scsi_debug_vpd_use_hostno) + arr[5] = 0x10; /* claim: implicit TGPS */ arr[6] = 0x10; /* claim: MultiP */ /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */ arr[7] = 0xa; /* claim: LINKED + CMDQUE */ @@ -1039,8 +1069,10 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[n++] = 0x3; arr[n++] = 0x60; /* SSC-2 no version */ } arr[n++] = 0xc; arr[n++] = 0xf; /* SAS-1.1 rev 10 */ - return fill_from_dev_buffer(scp, arr, + ret = fill_from_dev_buffer(scp, arr, min(alloc_len, SDEBUG_LONG_INQ_SZ)); + kfree(arr); + return ret; } static int resp_requests(struct scsi_cmnd * scp, @@ -1171,6 +1203,87 @@ static int resp_readcap16(struct scsi_cmnd * scp, min(alloc_len, SDEBUG_READCAP16_ARR_SZ)); } +#define SDEBUG_MAX_TGTPGS_ARR_SZ 1412 + +static int resp_report_tgtpgs(struct scsi_cmnd * scp, + struct sdebug_dev_info * devip) +{ + unsigned char *cmd = (unsigned char *)scp->cmnd; + unsigned char * arr; + int host_no = devip->sdbg_host->shost->host_no; + int n, ret, alen, rlen; + int port_group_a, port_group_b, port_a, port_b; + + alen = ((cmd[6] << 24) + (cmd[7] << 16) + (cmd[8] << 8) + + cmd[9]); + + arr = kzalloc(SDEBUG_MAX_TGTPGS_ARR_SZ, GFP_KERNEL); + /* + * EVPD page 0x88 states we have two ports, one + * real and a fake port with no device connected. + * So we create two port groups with one port each + * and set the group with port B to unavailable. + */ + port_a = 0x1; /* relative port A */ + port_b = 0x2; /* relative port B */ + port_group_a = (((host_no + 1) & 0x7f) << 8) + + (devip->channel & 0x7f); + port_group_b = (((host_no + 1) & 0x7f) << 8) + + (devip->channel & 0x7f) + 0x80; + + /* + * The asymmetric access state is cycled according to the host_id. + */ + n = 4; + if (0 == scsi_debug_vpd_use_hostno) { + arr[n++] = host_no % 3; /* Asymm access state */ + arr[n++] = 0x0F; /* claim: all states are supported */ + } else { + arr[n++] = 0x0; /* Active/Optimized path */ + arr[n++] = 0x01; /* claim: only support active/optimized paths */ + } + arr[n++] = (port_group_a >> 8) & 0xff; + arr[n++] = port_group_a & 0xff; + arr[n++] = 0; /* Reserved */ + arr[n++] = 0; /* Status code */ + arr[n++] = 0; /* Vendor unique */ + arr[n++] = 0x1; /* One port per group */ + arr[n++] = 0; /* Reserved */ + arr[n++] = 0; /* Reserved */ + arr[n++] = (port_a >> 8) & 0xff; + arr[n++] = port_a & 0xff; + arr[n++] = 3; /* Port unavailable */ + arr[n++] = 0x08; /* claim: only unavailalbe paths are supported */ + arr[n++] = (port_group_b >> 8) & 0xff; + arr[n++] = port_group_b & 0xff; + arr[n++] = 0; /* Reserved */ + arr[n++] = 0; /* Status code */ + arr[n++] = 0; /* Vendor unique */ + arr[n++] = 0x1; /* One port per group */ + arr[n++] = 0; /* Reserved */ + arr[n++] = 0; /* Reserved */ + arr[n++] = (port_b >> 8) & 0xff; + arr[n++] = port_b & 0xff; + + rlen = n - 4; + arr[0] = (rlen >> 24) & 0xff; + arr[1] = (rlen >> 16) & 0xff; + arr[2] = (rlen >> 8) & 0xff; + arr[3] = rlen & 0xff; + + /* + * Return the smallest value of either + * - The allocated length + * - The constructed command length + * - The maximum array size + */ + rlen = min(alen,n); + ret = fill_from_dev_buffer(scp, arr, + min(rlen, SDEBUG_MAX_TGTPGS_ARR_SZ)); + kfree(arr); + return ret; +} + /* <> */ static int resp_err_recov_pg(unsigned char * p, int pcontrol, int target) diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 84a6d5fe0920..8a3f0bd0d45a 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -97,6 +97,7 @@ extern const unsigned char scsi_command_size[8]; #define PERSISTENT_RESERVE_IN 0x5e #define PERSISTENT_RESERVE_OUT 0x5f #define REPORT_LUNS 0xa0 +#define MAINTENANCE_IN 0xa3 #define MOVE_MEDIUM 0xa5 #define EXCHANGE_MEDIUM 0xa6 #define READ_12 0xa8 @@ -114,6 +115,8 @@ extern const unsigned char scsi_command_size[8]; #define SERVICE_ACTION_IN 0x9e /* values for service action in */ #define SAI_READ_CAPACITY_16 0x10 +/* values for maintenance in */ +#define MI_REPORT_TARGET_PGS 0x0a /* Values for T10/04-262r7 */ #define ATA_16 0x85 /* 16-byte pass-thru */ -- cgit v1.2.3 From 6d07cb71fdacc710fd9816cddb5c2df0f7bd96b4 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Fri, 20 Oct 2006 14:48:40 -0700 Subject: [SCSI] drivers/scsi: Handcrafted MIN/MAX macro removal Cleanups done to use min/max macros from kernel.h. Handcrafted MIN/MAX macros are changed to use macros in kernel.h [akpm@osdl.org: fix warning] Signed-off-by: Amol Lad Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 8 -------- drivers/scsi/aic7xxx/aic79xx_core.c | 22 +++++++++++----------- drivers/scsi/aic7xxx/aic79xx_osm.c | 7 ++++--- drivers/scsi/aic7xxx/aic7xxx.h | 8 -------- drivers/scsi/aic7xxx/aic7xxx_core.c | 18 +++++++++--------- drivers/scsi/aic7xxx/aic7xxx_osm.c | 4 ++-- 6 files changed, 26 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index df3346b5caf8..c58ac6a87306 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -53,14 +53,6 @@ struct ahd_platform_data; struct scb_platform_data; /****************************** Useful Macros *********************************/ -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - #ifndef TRUE #define TRUE 1 #endif diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 653818d2f802..6adcf7989ce7 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -2850,14 +2850,14 @@ ahd_devlimited_syncrate(struct ahd_softc *ahd, transinfo = &tinfo->goal; *ppr_options &= (transinfo->ppr_options|MSG_EXT_PPR_PCOMP_EN); if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { - maxsync = MAX(maxsync, AHD_SYNCRATE_ULTRA2); + maxsync = max(maxsync, (u_int)AHD_SYNCRATE_ULTRA2); *ppr_options &= ~MSG_EXT_PPR_DT_REQ; } if (transinfo->period == 0) { *period = 0; *ppr_options = 0; } else { - *period = MAX(*period, transinfo->period); + *period = max(*period, (u_int)transinfo->period); ahd_find_syncrate(ahd, period, ppr_options, maxsync); } } @@ -2924,12 +2924,12 @@ ahd_validate_offset(struct ahd_softc *ahd, maxoffset = MAX_OFFSET_PACED; } else maxoffset = MAX_OFFSET_NON_PACED; - *offset = MIN(*offset, maxoffset); + *offset = min(*offset, maxoffset); if (tinfo != NULL) { if (role == ROLE_TARGET) - *offset = MIN(*offset, tinfo->user.offset); + *offset = min(*offset, (u_int)tinfo->user.offset); else - *offset = MIN(*offset, tinfo->goal.offset); + *offset = min(*offset, (u_int)tinfo->goal.offset); } } @@ -2955,9 +2955,9 @@ ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, } if (tinfo != NULL) { if (role == ROLE_TARGET) - *bus_width = MIN(tinfo->user.width, *bus_width); + *bus_width = min((u_int)tinfo->user.width, *bus_width); else - *bus_width = MIN(tinfo->goal.width, *bus_width); + *bus_width = min((u_int)tinfo->goal.width, *bus_width); } } @@ -6057,9 +6057,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd) #endif } - newcount = MIN(scb_data->sense_left, scb_data->scbs_left); - newcount = MIN(newcount, scb_data->sgs_left); - newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); + newcount = min(scb_data->sense_left, scb_data->scbs_left); + newcount = min(newcount, scb_data->sgs_left); + newcount = min(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs)); for (i = 0; i < newcount; i++) { struct scb_platform_data *pdata; u_int col_tag; @@ -8668,7 +8668,7 @@ ahd_resolve_seqaddr(struct ahd_softc *ahd, u_int address) if (skip_addr > i) { int end_addr; - end_addr = MIN(address, skip_addr); + end_addr = min(address, skip_addr); address_offset += end_addr - i; i = skip_addr; } else { diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index d8d6687e20ad..77ef4d9b0e5f 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -1814,9 +1814,9 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, u_int sense_offset; if (scb->flags & SCB_SENSE) { - sense_size = MIN(sizeof(struct scsi_sense_data) + sense_size = min(sizeof(struct scsi_sense_data) - ahd_get_sense_residual(scb), - sizeof(cmd->sense_buffer)); + (u_long)sizeof(cmd->sense_buffer)); sense_offset = 0; } else { /* @@ -1825,7 +1825,8 @@ ahd_linux_handle_scsi_status(struct ahd_softc *ahd, */ siu = (struct scsi_status_iu_header *) scb->sense_data; - sense_size = MIN(scsi_4btoul(siu->sense_length), + sense_size = min_t(size_t, + scsi_4btoul(siu->sense_length), sizeof(cmd->sense_buffer)); sense_offset = SIU_SENSE_OFFSET(siu); } diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 62ff8c3dc2bb..4850820816e0 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -54,14 +54,6 @@ struct scb_platform_data; struct seeprom_descriptor; /****************************** Useful Macros *********************************/ -#ifndef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif - #ifndef TRUE #define TRUE 1 #endif diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 93e4e40944b6..46bd7bc2fa4d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -1671,7 +1671,7 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc, transinfo = &tinfo->goal; *ppr_options &= transinfo->ppr_options; if (transinfo->width == MSG_EXT_WDTR_BUS_8_BIT) { - maxsync = MAX(maxsync, AHC_SYNCRATE_ULTRA2); + maxsync = max(maxsync, (u_int)AHC_SYNCRATE_ULTRA2); *ppr_options &= ~MSG_EXT_PPR_DT_REQ; } if (transinfo->period == 0) { @@ -1679,7 +1679,7 @@ ahc_devlimited_syncrate(struct ahc_softc *ahc, *ppr_options = 0; return (NULL); } - *period = MAX(*period, transinfo->period); + *period = max(*period, (u_int)transinfo->period); return (ahc_find_syncrate(ahc, period, ppr_options, maxsync)); } @@ -1804,12 +1804,12 @@ ahc_validate_offset(struct ahc_softc *ahc, else maxoffset = MAX_OFFSET_8BIT; } - *offset = MIN(*offset, maxoffset); + *offset = min(*offset, maxoffset); if (tinfo != NULL) { if (role == ROLE_TARGET) - *offset = MIN(*offset, tinfo->user.offset); + *offset = min(*offset, (u_int)tinfo->user.offset); else - *offset = MIN(*offset, tinfo->goal.offset); + *offset = min(*offset, (u_int)tinfo->goal.offset); } } @@ -1835,9 +1835,9 @@ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, } if (tinfo != NULL) { if (role == ROLE_TARGET) - *bus_width = MIN(tinfo->user.width, *bus_width); + *bus_width = min((u_int)tinfo->user.width, *bus_width); else - *bus_width = MIN(tinfo->goal.width, *bus_width); + *bus_width = min((u_int)tinfo->goal.width, *bus_width); } } @@ -4406,7 +4406,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc) physaddr = sg_map->sg_physaddr; newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg))); - newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs)); + newcount = min(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs)); for (i = 0; i < newcount; i++) { struct scb_platform_data *pdata; #ifndef __linux__ @@ -6442,7 +6442,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) if (skip_addr > i) { int end_addr; - end_addr = MIN(address, skip_addr); + end_addr = min(address, skip_addr); address_offset += end_addr - i; i = skip_addr; } else { diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index ad8578e95937..8eb1211a7888 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -1876,9 +1876,9 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, if (scb->flags & SCB_SENSE) { u_int sense_size; - sense_size = MIN(sizeof(struct scsi_sense_data) + sense_size = min(sizeof(struct scsi_sense_data) - ahc_get_sense_residual(scb), - sizeof(cmd->sense_buffer)); + (u_long)sizeof(cmd->sense_buffer)); memcpy(cmd->sense_buffer, ahc_get_sense_buf(ahc, scb), sense_size); if (sense_size < sizeof(cmd->sense_buffer)) -- cgit v1.2.3 From 289fe5b1f99c5e61ed32796cbed0a1ecc3589041 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 20 Oct 2006 14:47:57 -0700 Subject: [SCSI] aic7xxx: cleanups - make needlessly global code static - #if 0 the following unused global functions: - aic79xx_core.c: ahd_print_scb - aic79xx_core.c: ahd_suspend - aic79xx_core.c: ahd_resume - aic79xx_core.c: ahd_dump_scbs - aic79xx_osm.c: ahd_softc_comp Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 53 ------- drivers/scsi/aic7xxx/aic79xx_core.c | 260 +++++++++++++++++++++------------ drivers/scsi/aic7xxx/aic79xx_inline.h | 30 ---- drivers/scsi/aic7xxx/aic79xx_osm.c | 2 +- drivers/scsi/aic7xxx/aic79xx_osm.h | 5 - drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 2 +- drivers/scsi/aic7xxx/aic79xx_pci.c | 7 +- drivers/scsi/aic7xxx/aic79xx_proc.c | 2 +- drivers/scsi/aic7xxx/aic7xxx.h | 2 - drivers/scsi/aic7xxx/aic7xxx_osm.c | 2 +- drivers/scsi/aic7xxx/aic7xxx_osm.h | 2 - drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 2 +- drivers/scsi/aic7xxx/aic7xxx_pci.c | 4 +- 13 files changed, 175 insertions(+), 198 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index c58ac6a87306..b19a07cb2ab2 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -964,8 +964,6 @@ int ahd_read_seeprom(struct ahd_softc *ahd, uint16_t *buf, int ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, u_int start_addr, u_int count); -int ahd_wait_seeprom(struct ahd_softc *ahd); -int ahd_verify_vpd_cksum(struct vpd_config *vpd); int ahd_verify_cksum(struct seeprom_config *sc); int ahd_acquire_seeprom(struct ahd_softc *ahd); void ahd_release_seeprom(struct ahd_softc *ahd); @@ -1312,8 +1310,6 @@ struct ahd_pci_identity { char *name; ahd_device_setup_t *setup; }; -extern struct ahd_pci_identity ahd_pci_ident_table []; -extern const u_int ahd_num_pci_devs; /***************************** VL/EISA Declarations ***************************/ struct aic7770_identity { @@ -1331,15 +1327,6 @@ extern const int ahd_num_aic7770_devs; /*************************** Function Declarations ****************************/ /******************************************************************************/ void ahd_reset_cmds_pending(struct ahd_softc *ahd); -u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); -void ahd_busy_tcl(struct ahd_softc *ahd, - u_int tcl, u_int busyid); -static __inline void ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl); -static __inline void -ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) -{ - ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); -} /***************************** PCI Front End *********************************/ struct ahd_pci_identity *ahd_find_pci_device(ahd_dev_softc_t); @@ -1348,7 +1335,6 @@ int ahd_pci_config(struct ahd_softc *, int ahd_pci_test_register_access(struct ahd_softc *); /************************** SCB and SCB queue management **********************/ -int ahd_probe_scbs(struct ahd_softc *); void ahd_qinfifo_requeue_tail(struct ahd_softc *ahd, struct scb *scb); int ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, @@ -1366,33 +1352,20 @@ int ahd_parse_vpddata(struct ahd_softc *ahd, int ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc); void ahd_intr_enable(struct ahd_softc *ahd, int enable); -void ahd_update_coalescing_values(struct ahd_softc *ahd, - u_int timer, - u_int maxcmds, - u_int mincmds); -void ahd_enable_coalescing(struct ahd_softc *ahd, - int enable); void ahd_pause_and_flushwork(struct ahd_softc *ahd); int ahd_suspend(struct ahd_softc *ahd); -int ahd_resume(struct ahd_softc *ahd); void ahd_set_unit(struct ahd_softc *, int); void ahd_set_name(struct ahd_softc *, char *); struct scb *ahd_get_scb(struct ahd_softc *ahd, u_int col_idx); void ahd_free_scb(struct ahd_softc *ahd, struct scb *scb); -void ahd_alloc_scbs(struct ahd_softc *ahd); void ahd_free(struct ahd_softc *ahd); int ahd_reset(struct ahd_softc *ahd, int reinit); -void ahd_shutdown(void *arg); int ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value); int ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value); -int ahd_wait_flexport(struct ahd_softc *ahd); /*************************** Interrupt Services *******************************/ -void ahd_pci_intr(struct ahd_softc *ahd); -void ahd_clear_intstat(struct ahd_softc *ahd); -void ahd_flush_qoutfifo(struct ahd_softc *ahd); void ahd_run_qoutfifo(struct ahd_softc *ahd); #ifdef AHD_TARGET_MODE void ahd_run_tqinfifo(struct ahd_softc *ahd, int paused); @@ -1401,7 +1374,6 @@ void ahd_handle_hwerrint(struct ahd_softc *ahd); void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat); void ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat); -void ahd_clear_critical_section(struct ahd_softc *ahd); /***************************** Error Recovery *********************************/ typedef enum { @@ -1418,23 +1390,9 @@ int ahd_search_disc_list(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, int stop_on_first, int remove, int save_state); -void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb); int ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset); -int ahd_abort_scbs(struct ahd_softc *ahd, int target, - char channel, int lun, u_int tag, - role_t role, uint32_t status); -void ahd_restart(struct ahd_softc *ahd); -void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo); -void ahd_handle_scb_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_handle_scsi_status(struct ahd_softc *ahd, - struct scb *scb); -void ahd_calc_residual(struct ahd_softc *ahd, - struct scb *scb); /*************************** Utility Functions ********************************/ -struct ahd_phase_table_entry* - ahd_lookup_phase_entry(int phase); void ahd_compile_devinfo(struct ahd_devinfo *devinfo, u_int our_id, u_int target, u_int lun, char channel, @@ -1442,14 +1400,6 @@ void ahd_compile_devinfo(struct ahd_devinfo *devinfo, /************************** Transfer Negotiation ******************************/ void ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, u_int *ppr_options, u_int maxsync); -void ahd_validate_offset(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int period, u_int *offset, - int wide, role_t role); -void ahd_validate_width(struct ahd_softc *ahd, - struct ahd_initiator_tinfo *tinfo, - u_int *bus_width, - role_t role); /* * Negotiation types. These are used to qualify if we should renegotiate * even if our goal and current transport parameters are identical. @@ -1520,10 +1470,8 @@ extern uint32_t ahd_debug; #define AHD_SHOW_INT_COALESCING 0x10000 #define AHD_DEBUG_SEQUENCER 0x20000 #endif -void ahd_print_scb(struct scb *scb); void ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo); -void ahd_dump_sglist(struct scb *scb); void ahd_dump_card_state(struct ahd_softc *ahd); int ahd_print_register(ahd_reg_parse_entry_t *table, u_int num_entries, @@ -1532,5 +1480,4 @@ int ahd_print_register(ahd_reg_parse_entry_t *table, u_int value, u_int *cur_column, u_int wrap_point); -void ahd_dump_scbs(struct ahd_softc *ahd); #endif /* _AIC79XX_H_ */ diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 6adcf7989ce7..7d53c6456d04 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -52,7 +52,7 @@ /***************************** Lookup Tables **********************************/ -char *ahd_chip_names[] = +static char *ahd_chip_names[] = { "NONE", "aic7901", @@ -237,10 +237,33 @@ static int ahd_handle_target_cmd(struct ahd_softc *ahd, struct target_cmd *cmd); #endif +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, + char channel, int lun, u_int tag, + role_t role, uint32_t status); +static void ahd_alloc_scbs(struct ahd_softc *ahd); +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, + u_int scbid); +static void ahd_calc_residual(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_clear_critical_section(struct ahd_softc *ahd); +static void ahd_clear_intstat(struct ahd_softc *ahd); +static void ahd_enable_coalescing(struct ahd_softc *ahd, + int enable); +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl); +static void ahd_freeze_devq(struct ahd_softc *ahd, + struct scb *scb); +static void ahd_handle_scb_status(struct ahd_softc *ahd, + struct scb *scb); +static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase); +static void ahd_shutdown(void *arg); +static void ahd_update_coalescing_values(struct ahd_softc *ahd, + u_int timer, + u_int maxcmds, + u_int mincmds); +static int ahd_verify_vpd_cksum(struct vpd_config *vpd); +static int ahd_wait_seeprom(struct ahd_softc *ahd); + /******************************** Private Inlines *****************************/ -static __inline void ahd_assert_atn(struct ahd_softc *ahd); -static __inline int ahd_currently_packetized(struct ahd_softc *ahd); -static __inline int ahd_set_active_fifo(struct ahd_softc *ahd); static __inline void ahd_assert_atn(struct ahd_softc *ahd) @@ -294,11 +317,44 @@ ahd_set_active_fifo(struct ahd_softc *ahd) } } +static __inline void +ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl) +{ + ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL); +} + +/* + * Determine whether the sequencer reported a residual + * for this SCB/transaction. + */ +static __inline void +ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_calc_residual(ahd, scb); +} + +static __inline void +ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) +{ + uint32_t sgptr; + + sgptr = ahd_le32toh(scb->hscb->sgptr); + if ((sgptr & SG_STATUS_VALID) != 0) + ahd_handle_scb_status(ahd, scb); + else + ahd_done(ahd, scb); +} + + /************************* Sequencer Execution Control ************************/ /* * Restart the sequencer program from address zero */ -void +static void ahd_restart(struct ahd_softc *ahd) { @@ -342,7 +398,7 @@ ahd_restart(struct ahd_softc *ahd) ahd_unpause(ahd); } -void +static void ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) { ahd_mode_state saved_modes; @@ -366,7 +422,7 @@ ahd_clear_fifo(struct ahd_softc *ahd, u_int fifo) * Flush and completed commands that are sitting in the command * complete queues down on the chip but have yet to be dma'ed back up. */ -void +static void ahd_flush_qoutfifo(struct ahd_softc *ahd) { struct scb *scb; @@ -905,6 +961,51 @@ ahd_handle_hwerrint(struct ahd_softc *ahd) ahd_free(ahd); } +#ifdef AHD_DEBUG +static void +ahd_dump_sglist(struct scb *scb) +{ + int i; + + if (scb->sg_count > 0) { + if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { + struct ahd_dma64_seg *sg_list; + + sg_list = (struct ahd_dma64_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint64_t addr; + uint32_t len; + + addr = ahd_le64toh(sg_list[i].addr); + len = ahd_le32toh(sg_list[i].len); + printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (uint32_t)((addr >> 32) & 0xFFFFFFFF), + (uint32_t)(addr & 0xFFFFFFFF), + sg_list[i].len & AHD_SG_LEN_MASK, + (sg_list[i].len & AHD_DMA_LAST_SEG) + ? " Last" : ""); + } + } else { + struct ahd_dma_seg *sg_list; + + sg_list = (struct ahd_dma_seg*)scb->sg_list; + for (i = 0; i < scb->sg_count; i++) { + uint32_t len; + + len = ahd_le32toh(sg_list[i].len); + printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", + i, + (len & AHD_SG_HIGH_ADDR_MASK) >> 24, + ahd_le32toh(sg_list[i].addr), + len & AHD_SG_LEN_MASK, + len & AHD_DMA_LAST_SEG ? " Last" : ""); + } + } + } +} +#endif /* AHD_DEBUG */ + void ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) { @@ -2523,7 +2624,7 @@ ahd_force_renegotiation(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) } #define AHD_MAX_STEPS 2000 -void +static void ahd_clear_critical_section(struct ahd_softc *ahd) { ahd_mode_state saved_modes; @@ -2646,7 +2747,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd) /* * Clear any pending interrupt status. */ -void +static void ahd_clear_intstat(struct ahd_softc *ahd) { AHD_ASSERT_MODES(ahd, ~(AHD_MODE_UNKNOWN_MSK|AHD_MODE_CFG_MSK), @@ -2677,6 +2778,8 @@ ahd_clear_intstat(struct ahd_softc *ahd) #ifdef AHD_DEBUG uint32_t ahd_debug = AHD_DEBUG_OPTS; #endif + +#if 0 void ahd_print_scb(struct scb *scb) { @@ -2701,49 +2804,7 @@ ahd_print_scb(struct scb *scb) SCB_GET_TAG(scb)); ahd_dump_sglist(scb); } - -void -ahd_dump_sglist(struct scb *scb) -{ - int i; - - if (scb->sg_count > 0) { - if ((scb->ahd_softc->flags & AHD_64BIT_ADDRESSING) != 0) { - struct ahd_dma64_seg *sg_list; - - sg_list = (struct ahd_dma64_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint64_t addr; - uint32_t len; - - addr = ahd_le64toh(sg_list[i].addr); - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (uint32_t)((addr >> 32) & 0xFFFFFFFF), - (uint32_t)(addr & 0xFFFFFFFF), - sg_list[i].len & AHD_SG_LEN_MASK, - (sg_list[i].len & AHD_DMA_LAST_SEG) - ? " Last" : ""); - } - } else { - struct ahd_dma_seg *sg_list; - - sg_list = (struct ahd_dma_seg*)scb->sg_list; - for (i = 0; i < scb->sg_count; i++) { - uint32_t len; - - len = ahd_le32toh(sg_list[i].len); - printf("sg[%d] - Addr 0x%x%x : Length %d%s\n", - i, - (len & AHD_SG_HIGH_ADDR_MASK) >> 24, - ahd_le32toh(sg_list[i].addr), - len & AHD_SG_LEN_MASK, - len & AHD_DMA_LAST_SEG ? " Last" : ""); - } - } - } -} +#endif /* 0 */ /************************* Transfer Negotiation *******************************/ /* @@ -2906,7 +2967,7 @@ ahd_find_syncrate(struct ahd_softc *ahd, u_int *period, * Truncate the given synchronous offset to a value the * current adapter type and syncrate are capable of. */ -void +static void ahd_validate_offset(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int period, u_int *offset, int wide, @@ -2937,7 +2998,7 @@ ahd_validate_offset(struct ahd_softc *ahd, * Truncate the given transfer width parameter to a value the * current adapter type is capable of. */ -void +static void ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, u_int *bus_width, role_t role) { @@ -3466,7 +3527,7 @@ ahd_print_devinfo(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) devinfo->target, devinfo->lun); } -struct ahd_phase_table_entry* +static struct ahd_phase_table_entry* ahd_lookup_phase_entry(int phase) { struct ahd_phase_table_entry *entry; @@ -5351,7 +5412,7 @@ ahd_free(struct ahd_softc *ahd) return; } -void +static void ahd_shutdown(void *arg) { struct ahd_softc *ahd; @@ -5480,7 +5541,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit) /* * Determine the number of SCBs available on the controller */ -int +static int ahd_probe_scbs(struct ahd_softc *ahd) { int i; @@ -5929,7 +5990,7 @@ ahd_free_scb(struct ahd_softc *ahd, struct scb *scb) ahd_platform_scb_free(ahd, scb); } -void +static void ahd_alloc_scbs(struct ahd_softc *ahd) { struct scb_data *scb_data; @@ -6982,7 +7043,7 @@ ahd_intr_enable(struct ahd_softc *ahd, int enable) ahd_outb(ahd, HCNTRL, hcntrl); } -void +static void ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, u_int mincmds) { @@ -7000,7 +7061,7 @@ ahd_update_coalescing_values(struct ahd_softc *ahd, u_int timer, u_int maxcmds, ahd_outb(ahd, INT_COALESCING_MINCMDS, -mincmds); } -void +static void ahd_enable_coalescing(struct ahd_softc *ahd, int enable) { @@ -7070,6 +7131,7 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd) ahd->flags &= ~AHD_ALL_INTERRUPTS; } +#if 0 int ahd_suspend(struct ahd_softc *ahd) { @@ -7083,7 +7145,9 @@ ahd_suspend(struct ahd_softc *ahd) ahd_shutdown(ahd); return (0); } +#endif /* 0 */ +#if 0 int ahd_resume(struct ahd_softc *ahd) { @@ -7093,6 +7157,7 @@ ahd_resume(struct ahd_softc *ahd) ahd_restart(ahd); return (0); } +#endif /* 0 */ /************************** Busy Target Table *********************************/ /* @@ -7125,7 +7190,7 @@ ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl) /* * Return the untagged transaction id for a given target/channel lun. */ -u_int +static u_int ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) { u_int scbid; @@ -7138,7 +7203,7 @@ ahd_find_busy_tcl(struct ahd_softc *ahd, u_int tcl) return (scbid); } -void +static void ahd_busy_tcl(struct ahd_softc *ahd, u_int tcl, u_int scbid) { u_int scb_offset; @@ -7186,7 +7251,7 @@ ahd_match_scb(struct ahd_softc *ahd, struct scb *scb, int target, return match; } -void +static void ahd_freeze_devq(struct ahd_softc *ahd, struct scb *scb) { int target; @@ -7690,7 +7755,7 @@ ahd_add_scb_to_free_list(struct ahd_softc *ahd, u_int scbid) * been modified from CAM_REQ_INPROG. This routine assumes that the sequencer * is paused before it is called. */ -int +static int ahd_abort_scbs(struct ahd_softc *ahd, int target, char channel, int lun, u_int tag, role_t role, uint32_t status) { @@ -8019,18 +8084,8 @@ ahd_stat_timer(void *arg) } /****************************** Status Processing *****************************/ -void -ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) -{ - if (scb->hscb->shared_data.istatus.scsi_status != 0) { - ahd_handle_scsi_status(ahd, scb); - } else { - ahd_calc_residual(ahd, scb); - ahd_done(ahd, scb); - } -} -void +static void ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; @@ -8238,10 +8293,21 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) } } +static void +ahd_handle_scb_status(struct ahd_softc *ahd, struct scb *scb) +{ + if (scb->hscb->shared_data.istatus.scsi_status != 0) { + ahd_handle_scsi_status(ahd, scb); + } else { + ahd_calc_residual(ahd, scb); + ahd_done(ahd, scb); + } +} + /* * Calculate the residual for a just completed SCB. */ -void +static void ahd_calc_residual(struct ahd_softc *ahd, struct scb *scb) { struct hardware_scb *hscb; @@ -9092,6 +9158,7 @@ ahd_dump_card_state(struct ahd_softc *ahd) ahd_unpause(ahd); } +#if 0 void ahd_dump_scbs(struct ahd_softc *ahd) { @@ -9117,6 +9184,7 @@ ahd_dump_scbs(struct ahd_softc *ahd) ahd_set_scbptr(ahd, saved_scb_index); ahd_restore_modes(ahd, saved_modes); } +#endif /* 0 */ /**************************** Flexport Logic **********************************/ /* @@ -9219,7 +9287,7 @@ ahd_write_seeprom(struct ahd_softc *ahd, uint16_t *buf, /* * Wait ~100us for the serial eeprom to satisfy our request. */ -int +static int ahd_wait_seeprom(struct ahd_softc *ahd) { int cnt; @@ -9237,7 +9305,7 @@ ahd_wait_seeprom(struct ahd_softc *ahd) * Validate the two checksums in the per_channel * vital product data struct. */ -int +static int ahd_verify_vpd_cksum(struct vpd_config *vpd) { int i; @@ -9316,6 +9384,24 @@ ahd_release_seeprom(struct ahd_softc *ahd) /* Currently a no-op */ } +/* + * Wait at most 2 seconds for flexport arbitration to succeed. + */ +static int +ahd_wait_flexport(struct ahd_softc *ahd) +{ + int cnt; + + AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); + cnt = 1000000 * 2 / 5; + while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) + ahd_delay(5); + + if (cnt == 0) + return (ETIMEDOUT); + return (0); +} + int ahd_write_flexport(struct ahd_softc *ahd, u_int addr, u_int value) { @@ -9357,24 +9443,6 @@ ahd_read_flexport(struct ahd_softc *ahd, u_int addr, uint8_t *value) return (0); } -/* - * Wait at most 2 seconds for flexport arbitration to succeed. - */ -int -ahd_wait_flexport(struct ahd_softc *ahd) -{ - int cnt; - - AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK); - cnt = 1000000 * 2 / 5; - while ((ahd_inb(ahd, BRDCTL) & FLXARBACK) == 0 && --cnt) - ahd_delay(5); - - if (cnt == 0) - return (ETIMEDOUT); - return (0); -} - /************************* Target Mode ****************************************/ #ifdef AHD_TARGET_MODE cam_status diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h index a3266e066c00..2ceb67f4af2a 100644 --- a/drivers/scsi/aic7xxx/aic79xx_inline.h +++ b/drivers/scsi/aic7xxx/aic79xx_inline.h @@ -418,10 +418,6 @@ ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index) } /*********************** Miscelaneous Support Functions ***********************/ -static __inline void ahd_complete_scb(struct ahd_softc *ahd, - struct scb *scb); -static __inline void ahd_update_residual(struct ahd_softc *ahd, - struct scb *scb); static __inline struct ahd_initiator_tinfo * ahd_fetch_transinfo(struct ahd_softc *ahd, char channel, u_int our_id, @@ -467,32 +463,6 @@ static __inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb); -static __inline void -ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_handle_scb_status(ahd, scb); - else - ahd_done(ahd, scb); -} - -/* - * Determine whether the sequencer reported a residual - * for this SCB/transaction. - */ -static __inline void -ahd_update_residual(struct ahd_softc *ahd, struct scb *scb) -{ - uint32_t sgptr; - - sgptr = ahd_le32toh(scb->hscb->sgptr); - if ((sgptr & SG_STATUS_VALID) != 0) - ahd_calc_residual(ahd, scb); -} - /* * Return pointers to the transfer negotiation information * for the specified our_id/remote_id pair. diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 77ef4d9b0e5f..5e13046d845b 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -293,7 +293,7 @@ static uint32_t aic79xx_seltime; * force all outstanding transactions to be serviced prior to a new * transaction. */ -uint32_t aic79xx_periodic_otag; +static uint32_t aic79xx_periodic_otag; /* Some storage boxes are using an LSI chip which has a bug making it * impossible to use aic79xx Rev B chip in 320 speeds. The following diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index fb3d4dd54413..3a67fc578d78 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -506,9 +506,6 @@ struct info_str { int pos; }; -void ahd_format_transinfo(struct info_str *info, - struct ahd_transinfo *tinfo); - /******************************** Locking *************************************/ static __inline void ahd_lockinit(struct ahd_softc *ahd) @@ -582,8 +579,6 @@ ahd_unlock(struct ahd_softc *ahd, unsigned long *flags) #define PCIXM_STATUS_MAXCRDS 0x1C00 /* Maximum Cumulative Read Size */ #define PCIXM_STATUS_RCVDSCEM 0x2000 /* Received a Split Comp w/Error msg */ -extern struct pci_driver aic79xx_pci_driver; - typedef enum { AHD_POWER_STATE_D0, diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 4b5354201807..2001fe890e71 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -82,7 +82,7 @@ static struct pci_device_id ahd_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahd_linux_pci_id_table); -struct pci_driver aic79xx_pci_driver = { +static struct pci_driver aic79xx_pci_driver = { .name = "aic79xx", .probe = ahd_linux_pci_dev_probe, .remove = ahd_linux_pci_dev_remove, diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c index 14850f31aafa..c07735819cd1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c @@ -97,7 +97,7 @@ static ahd_device_setup_t ahd_aic7901A_setup; static ahd_device_setup_t ahd_aic7902_setup; static ahd_device_setup_t ahd_aic790X_setup; -struct ahd_pci_identity ahd_pci_ident_table [] = +static struct ahd_pci_identity ahd_pci_ident_table [] = { /* aic7901 based controllers */ { @@ -201,7 +201,7 @@ struct ahd_pci_identity ahd_pci_ident_table [] = } }; -const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); +static const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table); #define DEVCONFIG 0x40 #define PCIXINITPAT 0x0000E000ul @@ -245,6 +245,7 @@ static int ahd_check_extport(struct ahd_softc *ahd); static void ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control); static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); +static void ahd_pci_intr(struct ahd_softc *ahd); struct ahd_pci_identity * ahd_find_pci_device(ahd_dev_softc_t pci) @@ -757,7 +758,7 @@ static const char *pci_status_strings[] = "%s: Address or Write Phase Parity Error Detected in %s.\n" }; -void +static void ahd_pci_intr(struct ahd_softc *ahd) { uint8_t pci_status[8]; diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index c5f0ee591509..6b28bebcbca0 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -136,7 +136,7 @@ copy_info(struct info_str *info, char *fmt, ...) return (len); } -void +static void ahd_format_transinfo(struct info_str *info, struct ahd_transinfo *tinfo) { u_int speed; diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 4850820816e0..5802f33324ce 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -1127,8 +1127,6 @@ struct ahc_pci_identity { char *name; ahc_device_setup_t *setup; }; -extern struct ahc_pci_identity ahc_pci_ident_table[]; -extern const u_int ahc_num_pci_devs; /***************************** VL/EISA Declarations ***************************/ struct aic7770_identity { diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 8eb1211a7888..ed85057152d5 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -328,7 +328,7 @@ static uint32_t aic7xxx_seltime; * force all outstanding transactions to be serviced prior to a new * transaction. */ -uint32_t aic7xxx_periodic_otag; +static uint32_t aic7xxx_periodic_otag; /* * Module information and settable options. diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index a87a4ce090df..a36b33868e0e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -533,8 +533,6 @@ ahc_unlock(struct ahc_softc *ahc, unsigned long *flags) #define PCIR_SUBVEND_0 0x2c #define PCIR_SUBDEV_0 0x2e -extern struct pci_driver aic7xxx_pci_driver; - typedef enum { AHC_POWER_STATE_D0, diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index d20ca514e9f3..ea5687df732d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -130,7 +130,7 @@ static struct pci_device_id ahc_linux_pci_id_table[] = { MODULE_DEVICE_TABLE(pci, ahc_linux_pci_id_table); -struct pci_driver aic7xxx_pci_driver = { +static struct pci_driver aic7xxx_pci_driver = { .name = "aic7xxx", .probe = ahc_linux_pci_dev_probe, .remove = ahc_linux_pci_dev_remove, diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c index 63cab2d74552..09c8172c9e5e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c @@ -168,7 +168,7 @@ static ahc_device_setup_t ahc_aha394XX_setup; static ahc_device_setup_t ahc_aha494XX_setup; static ahc_device_setup_t ahc_aha398XX_setup; -struct ahc_pci_identity ahc_pci_ident_table [] = +static struct ahc_pci_identity ahc_pci_ident_table [] = { /* aic7850 based controllers */ { @@ -559,7 +559,7 @@ struct ahc_pci_identity ahc_pci_ident_table [] = } }; -const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); +static const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); #define AHC_394X_SLOT_CHANNEL_A 4 #define AHC_394X_SLOT_CHANNEL_B 5 -- cgit v1.2.3 From ca3c3323931ef925497a9ffcb61c5eebe55f8e2b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 20 Oct 2006 14:48:07 -0700 Subject: [SCSI] aic79xx: make ahd_set_tags() static Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx.h | 5 ----- drivers/scsi/aic7xxx/aic79xx_core.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index b19a07cb2ab2..170a4344cbb2 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -1428,11 +1428,6 @@ typedef enum { AHD_QUEUE_TAGGED } ahd_queue_alg; -void ahd_set_tags(struct ahd_softc *ahd, - struct scsi_cmnd *cmd, - struct ahd_devinfo *devinfo, - ahd_queue_alg alg); - /**************************** Target Mode *************************************/ #ifdef AHD_TARGET_MODE void ahd_send_lstate_events(struct ahd_softc *, diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 7d53c6456d04..4c2b5a817111 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -3271,7 +3271,7 @@ ahd_set_width(struct ahd_softc *ahd, struct ahd_devinfo *devinfo, /* * Update the current state of tagged queuing for a given target. */ -void +static void ahd_set_tags(struct ahd_softc *ahd, struct scsi_cmnd *cmd, struct ahd_devinfo *devinfo, ahd_queue_alg alg) { -- cgit v1.2.3 From afc071e6281e4f2af4748b5ddc594334726a37cf Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 23 Oct 2006 21:47:13 -0700 Subject: [SCSI] lpfc: fix printk format warning Fix printk format warning: drivers/scsi/lpfc/lpfc_attr.c:597: warning: long long unsigned int format, uint64_t arg (arg 4) Signed-off-by: Randy Dunlap Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/lpfc/lpfc_attr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 9496e87c135e..2a4e02e7a392 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -594,7 +594,8 @@ lpfc_soft_wwpn_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata; - return snprintf(buf, PAGE_SIZE, "0x%llx\n", phba->cfg_soft_wwpn); + return snprintf(buf, PAGE_SIZE, "0x%llx\n", + (unsigned long long)phba->cfg_soft_wwpn); } -- cgit v1.2.3 From 8883c1f182fa88d2b8e0adb6ae90a42f67e5353e Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 23 Oct 2006 15:22:37 +0200 Subject: [SCSI] aic79xx: Fixup external device reset Whenever an external device is resetted we really have to take care to keep the channel in sync. Just notifying SCSI-ML and retry is not enough as we have to make sure the SCSI bus is not getting confused, either. So whenever we detect an external reset we rewrite the command to TUR, disable packetized command and notify the internal engine that an abort has happened. This way we trigger a proper bus reset sequence and all devices will be renegotiated properly. Kudos to Justin Gibbs and Luben Tuikov for this idea. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_core.c | 66 +++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 4c2b5a817111..07a86a30f676 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -1154,10 +1154,12 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) * If a target takes us into the command phase * assume that it has been externally reset and * has thus lost our previous packetized negotiation - * agreement. - * Revert to async/narrow transfers until we - * can renegotiate with the device and notify - * the OSM about the reset. + * agreement. Since we have not sent an identify + * message and may not have fully qualified the + * connection, we change our command to TUR, assert + * ATN and ABORT the task when we go to message in + * phase. The OSM will see the REQUEUE_REQUEST + * status and retry the command. */ scbid = ahd_get_scbptr(ahd); scb = ahd_lookup_scb(ahd, scbid); @@ -1184,7 +1186,28 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) ahd_set_syncrate(ahd, &devinfo, /*period*/0, /*offset*/0, /*ppr_options*/0, AHD_TRANS_ACTIVE, /*paused*/TRUE); - scb->flags |= SCB_EXTERNAL_RESET; + /* Hand-craft TUR command */ + ahd_outb(ahd, SCB_CDB_STORE, 0); + ahd_outb(ahd, SCB_CDB_STORE+1, 0); + ahd_outb(ahd, SCB_CDB_STORE+2, 0); + ahd_outb(ahd, SCB_CDB_STORE+3, 0); + ahd_outb(ahd, SCB_CDB_STORE+4, 0); + ahd_outb(ahd, SCB_CDB_STORE+5, 0); + ahd_outb(ahd, SCB_CDB_LEN, 6); + scb->hscb->control &= ~(TAG_ENB|SCB_TAG_TYPE); + scb->hscb->control |= MK_MESSAGE; + ahd_outb(ahd, SCB_CONTROL, scb->hscb->control); + ahd_outb(ahd, MSG_OUT, HOST_MSG); + ahd_outb(ahd, SAVED_SCSIID, scb->hscb->scsiid); + /* + * The lun is 0, regardless of the SCB's lun + * as we have not sent an identify message. + */ + ahd_outb(ahd, SAVED_LUN, 0); + ahd_outb(ahd, SEQ_FLAGS, 0); + ahd_assert_atn(ahd); + scb->flags &= ~SCB_PACKETIZED; + scb->flags |= SCB_ABORT|SCB_EXTERNAL_RESET; ahd_freeze_devq(ahd, scb); ahd_set_transaction_status(scb, CAM_REQUEUE_REQ); ahd_freeze_scb(scb); @@ -1620,8 +1643,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat) /* * Ignore external resets after a bus reset. */ - if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) + if (((status & SCSIRSTI) != 0) && (ahd->flags & AHD_BUS_RESET_ACTIVE)) { + ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); return; + } /* * Clear bus reset flag @@ -2301,6 +2326,22 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd) if (sent_msg == MSG_ABORT_TAG) tag = SCB_GET_TAG(scb); + if ((scb->flags & SCB_EXTERNAL_RESET) != 0) { + /* + * This abort is in response to an + * unexpected switch to command phase + * for a packetized connection. Since + * the identify message was never sent, + * "saved lun" is 0. We really want to + * abort only the SCB that encountered + * this error, which could have a different + * lun. The SCB will be retried so the OS + * will see the UA after renegotiating to + * packetized. + */ + tag = SCB_GET_TAG(scb); + saved_lun = scb->hscb->lun; + } found = ahd_abort_scbs(ahd, target, 'A', saved_lun, tag, ROLE_INITIATOR, CAM_REQ_ABORTED); @@ -7984,6 +8025,11 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) ahd_clear_fifo(ahd, 0); ahd_clear_fifo(ahd, 1); + /* + * Clear SCSI interrupt status + */ + ahd_outb(ahd, CLRSINT1, CLRSCSIRSTI); + /* * Reenable selections */ @@ -8017,10 +8063,6 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) } } #endif - /* Notify the XPT that a bus reset occurred */ - ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, AC_BUS_RESET); - /* * Revert to async/narrow transfers until we renegotiate. */ @@ -8042,6 +8084,10 @@ ahd_reset_channel(struct ahd_softc *ahd, char channel, int initiate_reset) } } + /* Notify the XPT that a bus reset occurred */ + ahd_send_async(ahd, devinfo.channel, CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD, AC_BUS_RESET); + ahd_restart(ahd); return (found); -- cgit v1.2.3 From 843822ad631889596d67716e6edbcde608aeba81 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 23 Oct 2006 15:24:23 +0200 Subject: [SCSI] aic79xx: set precompensation aic79xx has a special 'iocell' chip which handles the precompensation. If it's set via DV we should make sure to set the chip correctly, too. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 5e13046d845b..e7a32f8e1a5c 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2636,8 +2636,22 @@ static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp) pcomp ? "Enable" : "Disable"); #endif - if (pcomp) + if (pcomp) { + uint8_t precomp; + + if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) { + struct ahd_linux_iocell_opts *iocell_opts; + + iocell_opts = &aic79xx_iocell_info[ahd->unit]; + precomp = iocell_opts->precomp; + } else { + precomp = AIC79XX_DEFAULT_PRECOMP; + } ppr_options |= MSG_EXT_PPR_PCOMP_EN; + AHD_SET_PRECOMP(ahd, precomp); + } else { + AHD_SET_PRECOMP(ahd, 0); + } ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0, starget->channel + 'A', ROLE_INITIATOR); -- cgit v1.2.3 From 9080063f523b09af63234a21816c825133d48c44 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 23 Oct 2006 15:25:36 +0200 Subject: [SCSI] aic7xxx: Remove slave_destroy This is a cross-port from aic79xx; we still hit the occasional BUG_ON in slave_destroy. And again we don't really need the slave_destroy callback nor the ahc_linux_target structure at all. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic7xxx.h | 1 + drivers/scsi/aic7xxx/aic7xxx_core.c | 22 +++++++------ drivers/scsi/aic7xxx/aic7xxx_osm.c | 65 +++++++------------------------------ drivers/scsi/aic7xxx/aic7xxx_osm.h | 11 ++----- drivers/scsi/aic7xxx/aic7xxx_proc.c | 10 +++--- 5 files changed, 31 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h index 5802f33324ce..954c7c24501d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx.h +++ b/drivers/scsi/aic7xxx/aic7xxx.h @@ -1279,6 +1279,7 @@ typedef enum { } ahc_queue_alg; void ahc_set_tags(struct ahc_softc *ahc, + struct scsi_cmnd *cmd, struct ahc_devinfo *devinfo, ahc_queue_alg alg); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 46bd7bc2fa4d..50ef785224de 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -1986,7 +1986,7 @@ ahc_set_syncrate(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, tinfo->curr.ppr_options = ppr_options; ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); + CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { if (offset != 0) { printf("%s: target %d synchronous at %sMHz%s, " @@ -2056,7 +2056,7 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, tinfo->curr.width = width; ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_TRANSFER_NEG, NULL); + CAM_LUN_WILDCARD, AC_TRANSFER_NEG); if (bootverbose) { printf("%s: target %d using %dbit transfers\n", ahc_name(ahc), devinfo->target, @@ -2074,12 +2074,14 @@ ahc_set_width(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, * Update the current state of tagged queuing for a given target. */ void -ahc_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - ahc_queue_alg alg) +ahc_set_tags(struct ahc_softc *ahc, struct scsi_cmnd *cmd, + struct ahc_devinfo *devinfo, ahc_queue_alg alg) { - ahc_platform_set_tags(ahc, devinfo, alg); + struct scsi_device *sdev = cmd->device; + + ahc_platform_set_tags(ahc, sdev, devinfo, alg); ahc_send_async(ahc, devinfo->channel, devinfo->target, - devinfo->lun, AC_TRANSFER_NEG, &alg); + devinfo->lun, AC_TRANSFER_NEG); } /* @@ -3489,7 +3491,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) printf("(%s:%c:%d:%d): refuses tagged commands. " "Performing non-tagged I/O\n", ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun); - ahc_set_tags(ahc, devinfo, AHC_QUEUE_NONE); + ahc_set_tags(ahc, scb->io_ctx, devinfo, AHC_QUEUE_NONE); mask = ~0x23; } else { printf("(%s:%c:%d:%d): refuses %s tagged commands. " @@ -3497,7 +3499,7 @@ ahc_handle_msg_reject(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) ahc_name(ahc), devinfo->channel, devinfo->target, devinfo->lun, tag_type == MSG_ORDERED_TASK ? "ordered" : "head of queue"); - ahc_set_tags(ahc, devinfo, AHC_QUEUE_BASIC); + ahc_set_tags(ahc, scb->io_ctx, devinfo, AHC_QUEUE_BASIC); mask = ~0x03; } @@ -3763,7 +3765,7 @@ ahc_handle_devreset(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, if (status != CAM_SEL_TIMEOUT) ahc_send_async(ahc, devinfo->channel, devinfo->target, - CAM_LUN_WILDCARD, AC_SENT_BDR, NULL); + CAM_LUN_WILDCARD, AC_SENT_BDR); if (message != NULL && (verbose_level <= bootverbose)) @@ -6018,7 +6020,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset) #endif /* Notify the XPT that a bus reset occurred */ ahc_send_async(ahc, devinfo.channel, CAM_TARGET_WILDCARD, - CAM_LUN_WILDCARD, AC_BUS_RESET, NULL); + CAM_LUN_WILDCARD, AC_BUS_RESET); /* * Revert to async/narrow transfers until we renegotiate. diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index ed85057152d5..660f26e23a38 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -512,7 +512,6 @@ ahc_linux_target_alloc(struct scsi_target *starget) struct seeprom_config *sc = ahc->seep_config; unsigned long flags; struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget); - struct ahc_linux_target *targ = scsi_transport_target_data(starget); unsigned short scsirate; struct ahc_devinfo devinfo; struct ahc_initiator_tinfo *tinfo; @@ -533,7 +532,6 @@ ahc_linux_target_alloc(struct scsi_target *starget) BUG_ON(*ahc_targp != NULL); *ahc_targp = starget; - memset(targ, 0, sizeof(*targ)); if (sc) { int maxsync = AHC_SYNCRATE_DT; @@ -594,14 +592,11 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) struct ahc_softc *ahc = *((struct ahc_softc **)sdev->host->hostdata); struct scsi_target *starget = sdev->sdev_target; - struct ahc_linux_target *targ = scsi_transport_target_data(starget); struct ahc_linux_device *dev; if (bootverbose) printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id); - BUG_ON(targ->sdev[sdev->lun] != NULL); - dev = scsi_transport_device_data(sdev); memset(dev, 0, sizeof(*dev)); @@ -618,8 +613,6 @@ ahc_linux_slave_alloc(struct scsi_device *sdev) */ dev->maxtags = 0; - targ->sdev[sdev->lun] = sdev; - spi_period(starget) = 0; return 0; @@ -644,22 +637,6 @@ ahc_linux_slave_configure(struct scsi_device *sdev) return 0; } -static void -ahc_linux_slave_destroy(struct scsi_device *sdev) -{ - struct ahc_softc *ahc; - struct ahc_linux_device *dev = scsi_transport_device_data(sdev); - struct ahc_linux_target *targ = scsi_transport_target_data(sdev->sdev_target); - - ahc = *((struct ahc_softc **)sdev->host->hostdata); - if (bootverbose) - printf("%s: Slave Destroy %d\n", ahc_name(ahc), sdev->id); - - BUG_ON(dev->active); - - targ->sdev[sdev->lun] = NULL; -} - #if defined(__i386__) /* * Return the disk geometry for the given SCSI device. @@ -782,7 +759,6 @@ struct scsi_host_template aic7xxx_driver_template = { .use_clustering = ENABLE_CLUSTERING, .slave_alloc = ahc_linux_slave_alloc, .slave_configure = ahc_linux_slave_configure, - .slave_destroy = ahc_linux_slave_destroy, .target_alloc = ahc_linux_target_alloc, .target_destroy = ahc_linux_target_destroy, }; @@ -1204,21 +1180,13 @@ void ahc_platform_free(struct ahc_softc *ahc) { struct scsi_target *starget; - int i, j; + int i; if (ahc->platform_data != NULL) { /* destroy all of the device and target objects */ for (i = 0; i < AHC_NUM_TARGETS; i++) { starget = ahc->platform_data->starget[i]; if (starget != NULL) { - for (j = 0; j < AHC_NUM_LUNS; j++) { - struct ahc_linux_target *targ = - scsi_transport_target_data(starget); - - if (targ->sdev[j] == NULL) - continue; - targ->sdev[j] = NULL; - } ahc->platform_data->starget[i] = NULL; } } @@ -1252,24 +1220,13 @@ ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb) } void -ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo, - ahc_queue_alg alg) +ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, + struct ahc_devinfo *devinfo, ahc_queue_alg alg) { - struct scsi_target *starget; - struct ahc_linux_target *targ; struct ahc_linux_device *dev; - struct scsi_device *sdev; - u_int target_offset; int was_queuing; int now_queuing; - target_offset = devinfo->target; - if (devinfo->channel != 'A') - target_offset += 8; - starget = ahc->platform_data->starget[target_offset]; - targ = scsi_transport_target_data(starget); - BUG_ON(targ == NULL); - sdev = targ->sdev[devinfo->lun]; if (sdev == NULL) return; dev = scsi_transport_device_data(sdev); @@ -1402,11 +1359,15 @@ ahc_linux_device_queue_depth(struct scsi_device *sdev) tags = ahc_linux_user_tagdepth(ahc, &devinfo); if (tags != 0 && sdev->tagged_supported != 0) { - ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED); + ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_TAGGED); + ahc_send_async(ahc, devinfo.channel, devinfo.target, + devinfo.lun, AC_TRANSFER_NEG); ahc_print_devinfo(ahc, &devinfo); printf("Tagged Queuing enabled. Depth %d\n", tags); } else { - ahc_set_tags(ahc, &devinfo, AHC_QUEUE_NONE); + ahc_platform_set_tags(ahc, sdev, &devinfo, AHC_QUEUE_NONE); + ahc_send_async(ahc, devinfo.channel, devinfo.target, + devinfo.lun, AC_TRANSFER_NEG); } } @@ -1630,7 +1591,7 @@ ahc_platform_flushwork(struct ahc_softc *ahc) void ahc_send_async(struct ahc_softc *ahc, char channel, - u_int target, u_int lun, ac_code code, void *arg) + u_int target, u_int lun, ac_code code) { switch (code) { case AC_TRANSFER_NEG: @@ -1947,7 +1908,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, } ahc_set_transaction_status(scb, CAM_REQUEUE_REQ); ahc_set_scsi_status(scb, SCSI_STATUS_OK); - ahc_platform_set_tags(ahc, &devinfo, + ahc_platform_set_tags(ahc, sdev, &devinfo, (dev->flags & AHC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; @@ -1958,7 +1919,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc, */ dev->openings = 1; ahc_set_scsi_status(scb, SCSI_STATUS_BUSY); - ahc_platform_set_tags(ahc, &devinfo, + ahc_platform_set_tags(ahc, sdev, &devinfo, (dev->flags & AHC_DEV_Q_BASIC) ? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED); break; @@ -2600,8 +2561,6 @@ ahc_linux_init(void) if (!ahc_linux_transport_template) return -ENODEV; - scsi_transport_reserve_target(ahc_linux_transport_template, - sizeof(struct ahc_linux_target)); scsi_transport_reserve_device(ahc_linux_transport_template, sizeof(struct ahc_linux_device)); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index a36b33868e0e..85ae5d836fa4 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -256,7 +256,6 @@ typedef enum { AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */ } ahc_linux_dev_flags; -struct ahc_linux_target; struct ahc_linux_device { /* * The number of transactions currently @@ -329,12 +328,6 @@ struct ahc_linux_device { #define AHC_OTAG_THRESH 500 }; -struct ahc_linux_target { - struct scsi_device *sdev[AHC_NUM_LUNS]; - struct ahc_transinfo last_tinfo; - struct ahc_softc *ahc; -}; - /********************* Definitions Required by the Core ***********************/ /* * Number of SG segments we require. So long as the S/G segments for @@ -822,7 +815,7 @@ ahc_freeze_scb(struct scb *scb) } } -void ahc_platform_set_tags(struct ahc_softc *ahc, +void ahc_platform_set_tags(struct ahc_softc *ahc, struct scsi_device *sdev, struct ahc_devinfo *devinfo, ahc_queue_alg); int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel, int lun, u_int tag, @@ -832,7 +825,7 @@ irqreturn_t void ahc_platform_flushwork(struct ahc_softc *ahc); void ahc_done(struct ahc_softc*, struct scb*); void ahc_send_async(struct ahc_softc *, char channel, - u_int target, u_int lun, ac_code, void *); + u_int target, u_int lun, ac_code); void ahc_print_path(struct ahc_softc *, struct scb *); void ahc_platform_dump_card_state(struct ahc_softc *ahc); diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 5914b4aa4a8f..99e5443e7535 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -182,7 +182,6 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, u_int our_id, char channel, u_int target_id, u_int target_offset) { - struct ahc_linux_target *targ; struct scsi_target *starget; struct ahc_initiator_tinfo *tinfo; struct ahc_tmode_tstate *tstate; @@ -198,7 +197,6 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, starget = ahc->platform_data->starget[target_offset]; if (!starget) return; - targ = scsi_transport_target_data(starget); copy_info(info, "\tGoal: "); ahc_format_transinfo(info, &tinfo->goal); @@ -208,7 +206,7 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info, for (lun = 0; lun < AHC_NUM_LUNS; lun++) { struct scsi_device *sdev; - sdev = targ->sdev[lun]; + sdev = scsi_device_lookup_by_target(starget, lun); if (sdev == NULL) continue; @@ -383,11 +381,11 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start, } copy_info(&info, "\n"); - max_targ = 15; + max_targ = 16; if ((ahc->features & (AHC_WIDE|AHC_TWIN)) == 0) - max_targ = 7; + max_targ = 8; - for (i = 0; i <= max_targ; i++) { + for (i = 0; i < max_targ; i++) { u_int our_id; u_int target_id; char channel; -- cgit v1.2.3 From d6b9ccbbeb625674891f797119f06512d27fc905 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 23 Oct 2006 15:26:37 +0200 Subject: [SCSI] aic79xx: Print out signalling This is a cross-port of a similar patch for aic7xxx; only it's a bit simpler here as we don't support HVD and all controller actually implement this register. I hope. Signed-off-by: Hannes Reinecke Signed-off-by: James Bottomley --- drivers/scsi/aic7xxx/aic79xx_osm.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index e7a32f8e1a5c..9bfcca5ede08 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2694,7 +2694,25 @@ static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold) ahd_unlock(ahd, &flags); } +static void ahd_linux_get_signalling(struct Scsi_Host *shost) +{ + struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata; + unsigned long flags; + u8 mode; + ahd_lock(ahd, &flags); + ahd_pause(ahd); + mode = ahd_inb(ahd, SBLKCTL); + ahd_unpause(ahd); + ahd_unlock(ahd, &flags); + + if (mode & ENAB40) + spi_signalling(shost) = SPI_SIGNAL_LVD; + else if (mode & ENAB20) + spi_signalling(shost) = SPI_SIGNAL_SE; + else + spi_signalling(shost) = SPI_SIGNAL_UNKNOWN; +} static struct spi_function_template ahd_linux_transport_functions = { .set_offset = ahd_linux_set_offset, @@ -2719,6 +2737,7 @@ static struct spi_function_template ahd_linux_transport_functions = { .show_pcomp_en = 1, .set_hold_mcs = ahd_linux_set_hold_mcs, .show_hold_mcs = 1, + .get_signalling = ahd_linux_get_signalling, }; static int __init -- cgit v1.2.3 From 1fbece150a230d0ab447cfb2fc4df10fb89f0d8c Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 1 Jul 2006 13:39:55 -0700 Subject: [PATCH] pcmcia: at91_cf update More correct AT91 CF wakeup logic ... only enable/disable the IRQ wakeup capability, not the IRQ itself. That way the we know that the IRQ will be disabled correctly, in suspend/resume logic instead of ARM IRQ code. Most of the pin multiplexing setup has moved to the devices.c setup code. Signed-off-by: David Brownell Signed-off-by: Andrew Victor Signed-off-by: Dominik Brodowski --- drivers/pcmcia/at91_cf.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 7f5df9a9f393..f8db6e342cbb 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -241,12 +241,6 @@ static int __init at91_cf_probe(struct platform_device *pdev) csa = at91_sys_read(AT91_EBI_CSA); at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); - /* force poweron defaults for these pins ... */ - (void) at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ - (void) at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ - (void) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ - (void) at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ - /* nWAIT is _not_ a default setting */ (void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ @@ -322,6 +316,7 @@ fail1: if (board->irq_pin) free_irq(board->irq_pin, cf); fail0a: + device_init_wakeup(&pdev->dev, 0); free_irq(board->det_pin, cf); device_init_wakeup(&pdev->dev, 0); fail0: @@ -360,26 +355,20 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg) struct at91_cf_data *board = cf->board; pcmcia_socket_dev_suspend(&pdev->dev, mesg); - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(&pdev->dev)) { enable_irq_wake(board->det_pin); - else { + if (board->irq_pin) + enable_irq_wake(board->irq_pin); + } else { disable_irq_wake(board->det_pin); - disable_irq(board->det_pin); + if (board->irq_pin) + disable_irq_wake(board->irq_pin); } - if (board->irq_pin) - disable_irq(board->irq_pin); return 0; } static int at91_cf_resume(struct platform_device *pdev) { - struct at91_cf_socket *cf = platform_get_drvdata(pdev); - struct at91_cf_data *board = cf->board; - - if (board->irq_pin) - enable_irq(board->irq_pin); - if (!device_may_wakeup(&pdev->dev)) - enable_irq(board->det_pin); pcmcia_socket_dev_resume(&pdev->dev); return 0; } -- cgit v1.2.3 From 01918d16c837485ceba92d48fb734cf520e61144 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Sun, 2 Jul 2006 21:21:51 +0200 Subject: [PATCH] pcmcia: add more IDs to hostap_cs.c As a replacement for the broad manufactor/card ID match we commented out because of conflicts with pcnet_cs, add two product ID matches. Signed-off-by: Dominik Brodowski --- drivers/net/wireless/hostap/hostap_cs.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 686d895116de..f63909e4bc32 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -887,6 +887,13 @@ static struct pcmcia_device_id hostap_cs_ids[] = { PCMCIA_DEVICE_PROD_ID123( "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", 0xc7b8df9d, 0x1700d087, 0x4b74baa0), + PCMCIA_DEVICE_PROD_ID123( + "Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", + "Ver. 1.00", + 0x5cd01705, 0x4271660f, 0x9d08ee12), + PCMCIA_DEVICE_PROD_ID123( + "corega", "WL PCCL-11", "ISL37300P", + 0xa21501a, 0x59868926, 0xc9049a39), PCMCIA_DEVICE_NULL }; MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); -- cgit v1.2.3 From 4708b5faf7c53bb4128d34267bdfe4b8c74b488a Mon Sep 17 00:00:00 2001 From: Kaustav Majumdar Date: Fri, 20 Oct 2006 14:44:09 -0700 Subject: [PATCH] pcmcia: update alloc_io_space for conflict checking for multifunction PC card Some PCMCIA cards do not mention specific IO addresses in the CIS. In that case, inside the alloc_io_space function, conflicts are detected (the function returns 1) for the second function of a multifunction card unless the length of IO address range required is greater than 0x100. The following patch will remove this conflict checking for a PCMCIA function which had not mentioned any specific IO address to be mapped from. The patch is tested for Linux kernel 2.6.15.4 and works fine in the above case and is as suggested by Dave Hinds. Signed-off-by: Kaustav Majumdar Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index 74cebd424032..b9201c2ec38b 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -95,7 +95,7 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base, * potential conflicts, just the most obvious ones. */ for (i = 0; i < MAX_IO_WIN; i++) - if ((s->io[i].res) && + if ((s->io[i].res) && *base && ((s->io[i].res->start & (align-1)) == *base)) return 1; for (i = 0; i < MAX_IO_WIN; i++) { -- cgit v1.2.3 From ace7d4772cf056d9b13b51bd496a8be968774592 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 20 Oct 2006 14:44:12 -0700 Subject: [PATCH] pcmcia/ds: driver layer error checking Check driver layer return values in pcmcia/ds.c Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 74b3124e8247..af392bfee5a6 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1292,10 +1292,22 @@ struct bus_type pcmcia_bus_type = { static int __init init_pcmcia_bus(void) { + int ret; + spin_lock_init(&pcmcia_dev_list_lock); - bus_register(&pcmcia_bus_type); - class_interface_register(&pcmcia_bus_interface); + ret = bus_register(&pcmcia_bus_type); + if (ret < 0) { + printk(KERN_WARNING "pcmcia: bus_register error: %d\n", ret); + return ret; + } + ret = class_interface_register(&pcmcia_bus_interface); + if (ret < 0) { + printk(KERN_WARNING + "pcmcia: class_interface_register error: %d\n", ret); + bus_unregister(&pcmcia_bus_type); + return ret; + } pcmcia_setup_ioctl(); -- cgit v1.2.3 From f237de58b13bf65ba2f7fab896daacb92ae7ddef Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 20 Oct 2006 14:44:13 -0700 Subject: [PATCH] CONFIG_PM=n slim: drivers/pcmcia/* Remove some code which is unneeded if CONFIG_PM=n. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/i82092.c | 4 ++++ drivers/pcmcia/pd6729.c | 4 ++++ drivers/pcmcia/yenta_socket.c | 6 ++++-- 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index 82715f448957..d316d956f3b1 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -41,6 +41,7 @@ static struct pci_device_id i82092aa_pci_ids[] = { }; MODULE_DEVICE_TABLE(pci, i82092aa_pci_ids); +#ifdef CONFIG_PM static int i82092aa_socket_suspend (struct pci_dev *dev, pm_message_t state) { return pcmcia_socket_dev_suspend(&dev->dev, state); @@ -50,14 +51,17 @@ static int i82092aa_socket_resume (struct pci_dev *dev) { return pcmcia_socket_dev_resume(&dev->dev); } +#endif static struct pci_driver i82092aa_pci_drv = { .name = "i82092aa", .id_table = i82092aa_pci_ids, .probe = i82092aa_pci_probe, .remove = __devexit_p(i82092aa_pci_remove), +#ifdef CONFIG_PM .suspend = i82092aa_socket_suspend, .resume = i82092aa_socket_resume, +#endif }; diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index c83a0a6b158f..a70f97fdbbdd 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -755,6 +755,7 @@ static void __devexit pd6729_pci_remove(struct pci_dev *dev) kfree(socket); } +#ifdef CONFIG_PM static int pd6729_socket_suspend(struct pci_dev *dev, pm_message_t state) { return pcmcia_socket_dev_suspend(&dev->dev, state); @@ -764,6 +765,7 @@ static int pd6729_socket_resume(struct pci_dev *dev) { return pcmcia_socket_dev_resume(&dev->dev); } +#endif static struct pci_device_id pd6729_pci_ids[] = { { @@ -781,8 +783,10 @@ static struct pci_driver pd6729_pci_drv = { .id_table = pd6729_pci_ids, .probe = pd6729_pci_probe, .remove = __devexit_p(pd6729_pci_remove), +#ifdef CONFIG_PM .suspend = pd6729_socket_suspend, .resume = pd6729_socket_resume, +#endif }; static int pd6729_module_init(void) diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 26229d9da762..9ced52ab7d14 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1213,7 +1213,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i return ret; } - +#ifdef CONFIG_PM static int yenta_dev_suspend (struct pci_dev *dev, pm_message_t state) { struct yenta_socket *socket = pci_get_drvdata(dev); @@ -1262,7 +1262,7 @@ static int yenta_dev_resume (struct pci_dev *dev) return pcmcia_socket_dev_resume(&dev->dev); } - +#endif #define CB_ID(vend,dev,type) \ { \ @@ -1359,8 +1359,10 @@ static struct pci_driver yenta_cardbus_driver = { .id_table = yenta_table, .probe = yenta_probe, .remove = __devexit_p(yenta_close), +#ifdef CONFIG_PM .suspend = yenta_dev_suspend, .resume = yenta_dev_resume, +#endif }; -- cgit v1.2.3 From f465ce176fb2f1778a04fc3fcb2b8aa564901419 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 20 Oct 2006 14:44:13 -0700 Subject: [PATCH] i82092: wire up errors from pci_register_driver() debugging goo removed to not leave assymetry in it after possible "leave" removal. Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/i82092.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c index d316d956f3b1..c2ea07aa7a12 100644 --- a/drivers/pcmcia/i82092.c +++ b/drivers/pcmcia/i82092.c @@ -709,10 +709,7 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_ static int i82092aa_module_init(void) { - enter("i82092aa_module_init"); - pci_register_driver(&i82092aa_pci_drv); - leave("i82092aa_module_init"); - return 0; + return pci_register_driver(&i82092aa_pci_drv); } static void i82092aa_module_exit(void) -- cgit v1.2.3 From a230a6785dd5af84b8b043a64d8df8adc81f3724 Mon Sep 17 00:00:00 2001 From: Om Narasimhan Date: Fri, 20 Oct 2006 14:44:15 -0700 Subject: [PATCH] pcmcia: au1000_generic fix The previous code did something like, if (error) goto out_err; .... do { struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); out_err: flush_scheduled_work(); ops->hw_shutdown(skt); i--; } while (i > 0) ..... - On the error path, skt would not contain a valid value for the first iteration (skt is masked by uninitialized automatic skt) - Does not do hw_shutdown() for 0th element of PCMCIA_SOCKET Signed-off-by: Om Narasimhan Cc: "Yoichi Yuasa" Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/au1000_generic.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index d5dd0ce65536..5387de6216fb 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -351,6 +351,7 @@ struct skt_dev_info { int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr) { struct skt_dev_info *sinfo; + struct au1000_pcmcia_socket *skt; int ret, i; sinfo = kzalloc(sizeof(struct skt_dev_info), GFP_KERNEL); @@ -365,7 +366,7 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, * Initialise the per-socket structure. */ for (i = 0; i < nr; i++) { - struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); + skt = PCMCIA_SOCKET(i); memset(skt, 0, sizeof(*skt)); skt->socket.resource_ops = &pccard_static_ops; @@ -438,17 +439,19 @@ int au1x00_pcmcia_socket_probe(struct device *dev, struct pcmcia_low_level *ops, dev_set_drvdata(dev, sinfo); return 0; - do { - struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); + +out_err: + flush_scheduled_work(); + ops->hw_shutdown(skt); + while (i-- > 0) { + skt = PCMCIA_SOCKET(i); del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); -out_err: flush_scheduled_work(); ops->hw_shutdown(skt); - i--; - } while (i > 0); + } kfree(sinfo); out: return ret; -- cgit v1.2.3 From 3efa9970bd0ac731302224ab9243693e91bc4bea Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Fri, 20 Oct 2006 14:44:18 -0700 Subject: [PATCH] ioremap balanced with iounmap for drivers/pcmcia ioremap must be balanced by an iounmap and failing to do so can result in a memory leak. Signed-off-by: Amol Lad Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/at91_cf.c | 3 ++- drivers/pcmcia/au1000_generic.c | 10 ++++++++++ drivers/pcmcia/m8xx_pcmcia.c | 12 ++++++++---- drivers/pcmcia/omap_cf.c | 3 ++- 4 files changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index f8db6e342cbb..3bcb7dc32995 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -310,9 +310,10 @@ static int __init at91_cf_probe(struct platform_device *pdev) return 0; fail2: - iounmap((void __iomem *) cf->socket.io_offset); release_mem_region(io->start, io->end + 1 - io->start); fail1: + if (cf->socket.io_offset) + iounmap((void __iomem *) cf->socket.io_offset); if (board->irq_pin) free_irq(board->irq_pin, cf); fail0a: diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index 5387de6216fb..551bde5d9430 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -449,6 +449,16 @@ out_err: del_timer_sync(&skt->poll_timer); pcmcia_unregister_socket(&skt->socket); flush_scheduled_work(); + if (i == 0) { + iounmap(skt->virt_io + (u32)mips_io_port_base); + skt->virt_io = NULL; + } +#ifndef CONFIG_MIPS_XXS1500 + else { + iounmap(skt->virt_io + (u32)mips_io_port_base); + skt->virt_io = NULL; + } +#endif ops->hw_shutdown(skt); } diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index e070a2896769..3b72be880401 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -427,7 +427,7 @@ static int voltage_set(int slot, int vcc, int vpp) reg |= BCSR1_PCCVCC1; break; default: - return 1; + goto out_unmap; } switch(vpp) { @@ -438,15 +438,15 @@ static int voltage_set(int slot, int vcc, int vpp) if(vcc == vpp) reg |= BCSR1_PCCVPP1; else - return 1; + goto out_unmap; break; case 120: if ((vcc == 33) || (vcc == 50)) reg |= BCSR1_PCCVPP0; else - return 1; + goto out_unmap; default: - return 1; + goto out_unmap; } /* first, turn off all power */ @@ -457,6 +457,10 @@ static int voltage_set(int slot, int vcc, int vpp) iounmap(bcsr_io); return 0; + +out_unmap: + iounmap(bcsr_io); + return 1; } #define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c index c8e838c69766..06bf7f48836e 100644 --- a/drivers/pcmcia/omap_cf.c +++ b/drivers/pcmcia/omap_cf.c @@ -309,9 +309,10 @@ static int __devinit omap_cf_probe(struct device *dev) return 0; fail2: - iounmap((void __iomem *) cf->socket.io_offset); release_mem_region(cf->phys_cf, SZ_8K); fail1: + if (cf->socket.io_offset) + iounmap((void __iomem *) cf->socket.io_offset); free_irq(irq, cf); fail0: kfree(cf); -- cgit v1.2.3 From 26aaa3c202fb3bec8d6c6619122442d476f55658 Mon Sep 17 00:00:00 2001 From: Jonathan McDowell Date: Fri, 20 Oct 2006 14:44:19 -0700 Subject: [PATCH] Export soc_common_drv_pcmcia_remove to allow modular PCMCIA. Allow a modular sa1100_cs. Signed-off-by: Jonathan McDowell Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/soc_common.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 3627e52e0c27..e433704e026a 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -824,3 +824,4 @@ int soc_common_drv_pcmcia_remove(struct device *dev) return 0; } +EXPORT_SYMBOL(soc_common_drv_pcmcia_remove); -- cgit v1.2.3 From 4deb7c1ed2b622b565c5330b475adc5a6cea30da Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 20 Oct 2006 14:44:23 -0700 Subject: [PATCH] PCMCIA: handle sysfs, PCI errors Handle sysfs and PCI errors correctly. Signed-off-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Dominik Brodowski --- drivers/pcmcia/pcmcia_ioctl.c | 11 ++++++++--- drivers/pcmcia/yenta_socket.c | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 9ad18e62658d..310ede575caa 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -128,9 +128,12 @@ static int proc_read_drivers(char *buf, char **start, off_t pos, int count, int *eof, void *data) { char *p = buf; + int rc; - bus_for_each_drv(&pcmcia_bus_type, NULL, - (void *) &p, proc_read_drivers_callback); + rc = bus_for_each_drv(&pcmcia_bus_type, NULL, + (void *) &p, proc_read_drivers_callback); + if (rc < 0) + return rc; return (p - buf); } @@ -269,8 +272,10 @@ rescan: * Prevent this racing with a card insertion. */ mutex_lock(&s->skt_mutex); - bus_rescan_devices(&pcmcia_bus_type); + ret = bus_rescan_devices(&pcmcia_bus_type); mutex_unlock(&s->skt_mutex); + if (ret) + goto err_put_module; /* check whether the driver indeed matched. I don't care if this * is racy or not, because it can only happen on cardmgr access diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index 9ced52ab7d14..da471bddc972 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -1197,8 +1197,12 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i ret = pcmcia_register_socket(&socket->socket); if (ret == 0) { /* Add the yenta register attributes */ - device_create_file(&dev->dev, &dev_attr_yenta_registers); - goto out; + ret = device_create_file(&dev->dev, &dev_attr_yenta_registers); + if (ret == 0) + goto out; + + /* error path... */ + pcmcia_unregister_socket(&socket->socket); } unmap: @@ -1248,12 +1252,18 @@ static int yenta_dev_resume (struct pci_dev *dev) struct yenta_socket *socket = pci_get_drvdata(dev); if (socket) { + int rc; + pci_set_power_state(dev, 0); /* FIXME: pci_restore_state needs to have a better interface */ pci_restore_state(dev); pci_write_config_dword(dev, 16*4, socket->saved_state[0]); pci_write_config_dword(dev, 17*4, socket->saved_state[1]); - pci_enable_device(dev); + + rc = pci_enable_device(dev); + if (rc) + return rc; + pci_set_master(dev); if (socket->type && socket->type->restore_state) -- cgit v1.2.3 From f901b8c46fa9748b9d6836e9b158cf7be89447f1 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Wed, 25 Oct 2006 19:56:55 -0400 Subject: [PATCH] PCMCIA: fix __must_check warnings Fix the remaining __must_check warnings in the PCMCIA core. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/ds.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index af392bfee5a6..0f701921c13e 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -717,6 +717,7 @@ static int pcmcia_requery(struct device *dev, void * _data) static void pcmcia_bus_rescan(struct pcmcia_socket *skt) { int no_devices=0; + int ret = 0; unsigned long flags; /* must be called with skt_mutex held */ @@ -729,7 +730,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) * missing resource information or other trouble, we need to * do this now. */ if (no_devices) { - int ret = pcmcia_card_add(skt); + ret = pcmcia_card_add(skt); if (ret) return; } @@ -741,7 +742,9 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt) /* we re-scan all devices, not just the ones connected to this * socket. This does not matter, though. */ - bus_rescan_devices(&pcmcia_bus_type); + ret = bus_rescan_devices(&pcmcia_bus_type); + if (ret) + printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n"); } static inline int pcmcia_devmatch(struct pcmcia_device *dev, @@ -1001,6 +1004,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pcmcia_device *p_dev = to_pcmcia_dev(dev); + int ret; if (!count) return -EINVAL; @@ -1009,7 +1013,10 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, p_dev->allow_func_id_match = 1; mutex_unlock(&p_dev->socket->skt_mutex); - bus_rescan_devices(&pcmcia_bus_type); + ret = bus_rescan_devices(&pcmcia_bus_type); + if (ret) + printk(KERN_INFO "pcmcia: bus_rescan_devices failed after " + "allowing func_id matches\n"); return count; } -- cgit v1.2.3 From f5ef9d11fd255b30b455d18f8d721bc44cd1296b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 27 Oct 2006 01:03:31 -0700 Subject: [SPARC]: Fix bus_id[] string overflow. dp->path_component_name can be larger than ->bus_id[] so use a different naming scheme for this stuff. Noticed by Jurij Smakov. Signed-off-by: David S. Miller --- arch/sparc/kernel/ebus.c | 8 ++++---- arch/sparc/kernel/of_device.c | 2 +- arch/sparc64/kernel/ebus.c | 8 ++++---- arch/sparc64/kernel/isa.c | 8 ++++---- arch/sparc64/kernel/of_device.c | 2 +- drivers/sbus/sbus.c | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c index 75ac24d229b1..ba58c3a061fd 100644 --- a/arch/sparc/kernel/ebus.c +++ b/arch/sparc/kernel/ebus.c @@ -237,12 +237,12 @@ void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *d dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; - strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); + sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dev->ofdev.dev.bus_id); + dp->path_component_name); if ((dp = dp->child) != NULL) { dev->children = (struct linux_ebus_child *) @@ -332,12 +332,12 @@ void __init ebus_init(void) ebus->ofdev.node = dp; ebus->ofdev.dev.parent = &pdev->dev; ebus->ofdev.dev.bus = &ebus_bus_type; - strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); + sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); /* Register with core */ if (of_device_register(&ebus->ofdev) != 0) printk(KERN_DEBUG "ebus: device registration error for %s!\n", - ebus->ofdev.dev.bus_id); + dp->path_component_name); nd = dp->child; diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 74bef2a2d37f..46200c43ffb1 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -651,7 +651,7 @@ build_resources: if (!parent) strcpy(op->dev.bus_id, "root"); else - strcpy(op->dev.bus_id, dp->path_component_name); + sprintf(op->dev.bus_id, "%08x", dp->node); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 2df25c2b4071..35bf895fdeee 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c @@ -389,12 +389,12 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; - strcpy(dev->ofdev.dev.bus_id, dp->path_component_name); + sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) printk(KERN_DEBUG "ebus: device registration error for %s!\n", - dev->ofdev.dev.bus_id); + dp->path_component_name); dp = dp->child; if (dp) { @@ -494,12 +494,12 @@ void __init ebus_init(void) ebus->ofdev.node = dp; ebus->ofdev.dev.parent = &pdev->dev; ebus->ofdev.dev.bus = &ebus_bus_type; - strcpy(ebus->ofdev.dev.bus_id, dp->path_component_name); + sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); /* Register with core */ if (of_device_register(&ebus->ofdev) != 0) printk(KERN_DEBUG "ebus: device registration error for %s!\n", - ebus->ofdev.dev.bus_id); + dp->path_component_name); child = dp->child; diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 0f3aec72ef5f..f028e68b23f2 100644 --- a/arch/sparc64/kernel/isa.c +++ b/arch/sparc64/kernel/isa.c @@ -115,12 +115,12 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br) isa_dev->ofdev.node = dp; isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev; isa_dev->ofdev.dev.bus = &isa_bus_type; - strcpy(isa_dev->ofdev.dev.bus_id, dp->path_component_name); + sprintf(isa_dev->ofdev.dev.bus_id, "isa[%08x]", dp->node); /* Register with core */ if (of_device_register(&isa_dev->ofdev) != 0) { printk(KERN_DEBUG "isa: device registration error for %s!\n", - isa_dev->ofdev.dev.bus_id); + dp->path_component_name); kfree(isa_dev); goto next_sibling; } @@ -191,12 +191,12 @@ void __init isa_init(void) isa_br->ofdev.node = dp; isa_br->ofdev.dev.parent = &pdev->dev; isa_br->ofdev.dev.bus = &isa_bus_type; - strcpy(isa_br->ofdev.dev.bus_id, dp->path_component_name); + sprintf(isa_br->ofdev.dev.bus_id, "isa%d", index); /* Register with core */ if (of_device_register(&isa_br->ofdev) != 0) { printk(KERN_DEBUG "isa: device registration error for %s!\n", - isa_br->ofdev.dev.bus_id); + dp->path_component_name); kfree(isa_br); return; } diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 983ca5f485cf..8cc14fc6b6f1 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -861,7 +861,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, if (!parent) strcpy(op->dev.bus_id, "root"); else - sprintf(op->dev.bus_id, "%s@%08x", dp->name, dp->node); + sprintf(op->dev.bus_id, "%08x", dp->node); if (of_device_register(op)) { printk("%s: Could not register of device.\n", diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 935952ef88f1..98fcbb3d5560 100644 --- a/drivers/sbus/sbus.c +++ b/drivers/sbus/sbus.c @@ -61,11 +61,11 @@ static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sde else sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; sdev->ofdev.dev.bus = &sbus_bus_type; - strcpy(sdev->ofdev.dev.bus_id, dp->path_component_name); + sprintf(sdev->ofdev.dev.bus_id, "sbus[%08x]", dp->node); if (of_device_register(&sdev->ofdev) != 0) printk(KERN_DEBUG "sbus: device registration error for %s!\n", - sdev->ofdev.dev.bus_id); + dp->path_component_name); } static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) -- cgit v1.2.3 From c2b1449bd1fd73103ed5ff1a28d8f7cbc8a01b52 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 27 Oct 2006 12:39:17 +0200 Subject: [S390] cio: css_probe_device() must be called enabled. Move css_probe_device() behind giving up the lock for the old subchannel in css_evaluate_known_subchannel() so we aren't disabled when we call it. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/css.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index a2dee5bf5a17..ad7f7e1c0163 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -271,10 +271,6 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) /* Reset intparm to zeroes. */ sch->schib.pmcw.intparm = 0; cio_modify(sch); - - /* Probe if necessary. */ - if (action == UNREGISTER_PROBE) - ret = css_probe_device(sch->schid); break; case REPROBE: device_trigger_reprobe(sch); @@ -283,6 +279,9 @@ static int css_evaluate_known_subchannel(struct subchannel *sch, int slow) break; } spin_unlock_irqrestore(&sch->lock, flags); + /* Probe if necessary. */ + if (action == UNREGISTER_PROBE) + ret = css_probe_device(sch->schid); return ret; } -- cgit v1.2.3 From f3b017d8c9915cbaa8bab178dde1bd9dbbf5012c Mon Sep 17 00:00:00 2001 From: Ralph Wuerthner Date: Fri, 27 Oct 2006 12:39:26 +0200 Subject: [S390] Improve AP bus device removal. Added a call to device_unregister() in ap_scan_bus() to actively remove unavailable AP bus devices with every bus scan. Previously devices were only removed in ap_queue_message() or __ap_poll_all(). Signed-off-by: Ralph Wuerthner Signed-off-by: Martin Schwidefsky --- drivers/s390/crypto/ap_bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index c5ccd20b110c..79d89c368919 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -739,11 +739,16 @@ static void ap_scan_bus(void *data) dev = bus_find_device(&ap_bus_type, NULL, (void *)(unsigned long)qid, __ap_scan_bus); + rc = ap_query_queue(qid, &queue_depth, &device_type); + if (dev && rc) { + put_device(dev); + device_unregister(dev); + continue; + } if (dev) { put_device(dev); continue; } - rc = ap_query_queue(qid, &queue_depth, &device_type); if (rc) continue; rc = ap_init_queue(qid); -- cgit v1.2.3 From 3c9da7ba049d11caccc219576a3a23404aa2fc50 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 27 Oct 2006 12:39:33 +0200 Subject: [S390] cio: Make ccw_device_register() static. ccw_device_register() is only called from io_subchannel_register() and io_subchannel_probe() and will never be called for possible non-io subchannels. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 3 +-- drivers/s390/cio/device.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 94bdd4d8a4c9..39c98f940507 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -532,8 +532,7 @@ device_remove_files(struct device *dev) /* this is a simple abstraction for device_register that sets the * correct bus type and adds the bus specific files */ -int -ccw_device_register(struct ccw_device *cdev) +static int ccw_device_register(struct ccw_device *cdev) { struct device *dev = &cdev->dev; int ret; diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index c6140cc97a80..9233b5c0bcc8 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -78,7 +78,6 @@ void io_subchannel_recog_done(struct ccw_device *cdev); int ccw_device_cancel_halt_clear(struct ccw_device *); -int ccw_device_register(struct ccw_device *); void ccw_device_do_unreg_rereg(void *); void ccw_device_call_sch_unregister(void *); -- cgit v1.2.3 From 35ae61a0f43ebbabc3cb4345136ca529fc4d6700 Mon Sep 17 00:00:00 2001 From: MUNEDA Takahiro Date: Wed, 25 Oct 2006 11:44:57 -0700 Subject: acpiphp: fix latch status pci_hotplug.h says: * @latch_status: if the latch (if any) is open or closed (1/0) However, acpiphp returns opposite value. This patch fixes this issue. I tested this patch on my ia64 machine that has some apciphp based hotplug slots. Signed-off-by: MUNEDA Takahiro Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index c44311ac2fd3..16167b016266 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1807,8 +1807,8 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot) /* - * latch closed: 1 - * latch open: 0 + * latch open: 1 + * latch closed: 0 */ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) { @@ -1816,7 +1816,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) sta = get_slot_status(slot); - return (sta & ACPI_STA_SHOW_IN_UI) ? 1 : 0; + return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; } -- cgit v1.2.3 From 6b5c76b8e2ff204fa8d7201acce461188873bf2b Mon Sep 17 00:00:00 2001 From: Eiichiro Oiwa Date: Mon, 23 Oct 2006 15:14:07 +0900 Subject: PCI: fix pci_fixup_video as it blows up on sparc64 This reverts much of the original pci_fixup_video change and makes it work for all arches that need it. fixed, and tested on x86, x86_64 and IA64 dig. Signed-off-by: Eiichiro Oiwa Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/fixup.c | 55 ++++++++++++++++++++++++++++++++++++++++ arch/ia64/pci/Makefile | 2 +- arch/ia64/pci/fixup.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/pci/quirks.c | 46 --------------------------------- drivers/pci/rom.c | 5 ++-- 5 files changed, 128 insertions(+), 49 deletions(-) create mode 100644 arch/ia64/pci/fixup.c (limited to 'drivers') diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index 908b410f4c93..c1949ff38d61 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -342,6 +342,61 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_r DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk ); +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + */ + +static void __devinit pci_fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 config; + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + + /* + * From information provided by + * "David Miller" + * The bridge control register is valid for PCI header + * type BRIDGE, or CARDBUS. Host to PCI controllers use + * PCI header type NORMAL. + */ + if (bridge + &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) + ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, + &config); + if (!(config & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pci_read_config_word(pdev, PCI_COMMAND, &config); + if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); + /* * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A. * diff --git a/arch/ia64/pci/Makefile b/arch/ia64/pci/Makefile index e66889e6922a..fb14dc520d2d 100644 --- a/arch/ia64/pci/Makefile +++ b/arch/ia64/pci/Makefile @@ -1,4 +1,4 @@ # # Makefile for the ia64-specific parts of the pci bus # -obj-y := pci.o +obj-y := pci.o fixup.o diff --git a/arch/ia64/pci/fixup.c b/arch/ia64/pci/fixup.c new file mode 100644 index 000000000000..245dc1fedc24 --- /dev/null +++ b/arch/ia64/pci/fixup.c @@ -0,0 +1,69 @@ +/* + * Exceptions for specific devices. Usually work-arounds for fatal design flaws. + * Derived from fixup.c of i386 tree. + */ + +#include +#include + +#include + +/* + * Fixup to mark boot BIOS video selected by BIOS before it changes + * + * From information provided by "Jon Smirl" + * + * The standard boot ROM sequence for an x86 machine uses the BIOS + * to select an initial video card for boot display. This boot video + * card will have it's BIOS copied to C0000 in system RAM. + * IORESOURCE_ROM_SHADOW is used to associate the boot video + * card with this copy. On laptops this copy has to be used since + * the main ROM may be compressed or combined with another image. + * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW + * is marked here since the boot video device will be the only enabled + * video device at this point. + */ + +static void __devinit pci_fixup_video(struct pci_dev *pdev) +{ + struct pci_dev *bridge; + struct pci_bus *bus; + u16 config; + + if ((strcmp(platform_name, "dig") != 0) + && (strcmp(platform_name, "hpzx1") != 0)) + return; + /* Maybe, this machine supports legacy memory map. */ + + if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) + return; + + /* Is VGA routed to us? */ + bus = pdev->bus; + while (bus) { + bridge = bus->self; + + /* + * From information provided by + * "David Miller" + * The bridge control register is valid for PCI header + * type BRIDGE, or CARDBUS. Host to PCI controllers use + * PCI header type NORMAL. + */ + if (bridge + &&((bridge->hdr_type == PCI_HEADER_TYPE_BRIDGE) + ||(bridge->hdr_type == PCI_HEADER_TYPE_CARDBUS))) { + pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, + &config); + if (!(config & PCI_BRIDGE_CTL_VGA)) + return; + } + bus = bus->parent; + } + pci_read_config_word(pdev, PCI_COMMAND, &config); + if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { + pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; + printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index e8a7f1b1b2bc..687ab4a0c6c6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1619,52 +1619,6 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); -/* - * Fixup to mark boot BIOS video selected by BIOS before it changes - * - * From information provided by "Jon Smirl" - * - * The standard boot ROM sequence for an x86 machine uses the BIOS - * to select an initial video card for boot display. This boot video - * card will have it's BIOS copied to C0000 in system RAM. - * IORESOURCE_ROM_SHADOW is used to associate the boot video - * card with this copy. On laptops this copy has to be used since - * the main ROM may be compressed or combined with another image. - * See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW - * is marked here since the boot video device will be the only enabled - * video device at this point. - */ - -static void __devinit fixup_video(struct pci_dev *pdev) -{ - struct pci_dev *bridge; - struct pci_bus *bus; - u16 config; - - if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA) - return; - - /* Is VGA routed to us? */ - bus = pdev->bus; - while (bus) { - bridge = bus->self; - if (bridge) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, - &config); - if (!(config & PCI_BRIDGE_CTL_VGA)) - return; - } - bus = bus->parent; - } - pci_read_config_word(pdev, PCI_COMMAND, &config); - if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { - pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW; - printk(KERN_DEBUG "Boot video device is %s\n", pci_name(pdev)); - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_video); - - static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { while (f < end) { diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 43e4a49f2cc4..e1dcefc69bb4 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -72,8 +72,9 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) int last_image; /* - * IORESOURCE_ROM_SHADOW set if the VGA enable bit of the Bridge Control - * register is set for embedded VGA. + * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy + * memory map if the VGA enable bit of the Bridge Control register is + * set for embedded VGA. */ if (res->flags & IORESOURCE_ROM_SHADOW) { /* primary video rom always starts here */ -- cgit v1.2.3 From 2449e06a5696b7af1c8a369b04c97f3b139cf3bb Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Fri, 20 Oct 2006 14:45:32 -0700 Subject: PCI: reset pci device state to unknown state for resume Considering below scenario: 1.Unload a PCI device's driver, the device ->current remains in PCI_D0. 2.Do suspend/resume circle. After that, BIOS puts the device to D3. 3.Reload the device driver. The calling pci_set_power_state in the driver can't change the state to D0, as set_power_state thinks the device is already in D0. A bug is reported at http://bugzilla.kernel.org/show_bug.cgi?id=6024 Pat attached a patch at http://marc.theaimsgroup.com/?l=linux-pci&m=114049761428561&w=2 for this issue, but it's lost. As pci_set_power_state can handle D3 -> D0 correctly (restore config space), I simplified Patrick's patch. Signed-off-by: Shaohua Li Cc: Patrick Mochel Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index b1c0c707d96c..194f1d21d3d7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -264,6 +264,13 @@ static int pci_device_remove(struct device * dev) pci_dev->driver = NULL; } + /* + * If the device is still on, set the power state as "unknown", + * since it might change by the next time we load the driver. + */ + if (pci_dev->current_state == PCI_D0) + pci_dev->current_state = PCI_UNKNOWN; + /* * We would love to complain here if pci_dev->is_enabled is set, that * the driver should have called pci_disable_device(), but the @@ -288,6 +295,12 @@ static int pci_device_suspend(struct device * dev, pm_message_t state) suspend_report_result(drv->suspend, i); } else { pci_save_state(pci_dev); + /* + * mark its power state as "unknown", since we don't know if + * e.g. the BIOS will change its device state when we suspend. + */ + if (pci_dev->current_state == PCI_D0) + pci_dev->current_state = PCI_UNKNOWN; } return i; } -- cgit v1.2.3 From 3560cc5ec3488b20d927f7160a21a0df1d1fda20 Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Fri, 20 Oct 2006 14:45:36 -0700 Subject: PCI: Remove quirk_via_abnormal_poweroff My K8T800 mobo resumes fine from suspend to ram with and without patch applied against 2.6.18. quirk_via_abnormal_poweroff makes some boards not boot 2.6.18, so IMO patch should go to head, 2.6.18.2 and everywhere "ACPI: ACPICA 20060623" has been applied. Remove quirk_via_abnormal_poweroff Obsoleted by "ACPI: ACPICA 20060623": Implemented support for "ignored" bits in the ACPI registers. According to the ACPI specification, these bits should be preserved when writing the registers via a read/modify/write cycle. There are 3 bits preserved in this manner: PM1_CONTROL[0] (SCI_EN), PM1_CONTROL[9], and PM1_STATUS[11]. http://bugzilla.kernel.org/show_bug.cgi?id=3691 Signed-off-by: Karsten Wiese Cc: Bob Moore Cc: "Brown, Len" Acked-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/quirks.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 687ab4a0c6c6..204b1c8e972b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -714,33 +714,6 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id ); -#ifdef CONFIG_ACPI_SLEEP - -/* - * Some VIA systems boot with the abnormal status flag set. This can cause - * the BIOS to re-POST the system on resume rather than passing control - * back to the OS. Clear the flag on boot - */ -static void __devinit quirk_via_abnormal_poweroff(struct pci_dev *dev) -{ - u32 reg; - - acpi_hw_register_read(ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS, - ®); - - if (reg & 0x800) { - printk("Clearing abnormal poweroff flag\n"); - acpi_hw_register_write(ACPI_MTX_DO_NOT_LOCK, - ACPI_REGISTER_PM1_STATUS, - (u16)0x800); - } -} - -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_via_abnormal_poweroff); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_abnormal_poweroff); - -#endif - /* * CardBus controllers have a legacy base address that enables them * to respond as i82365 pcmcia controllers. We don't want them to -- cgit v1.2.3 From 735a7ffb739b6efeaeb1e720306ba308eaaeb20e Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 27 Oct 2006 11:42:37 -0700 Subject: [PATCH] drivers: wait for threaded probes between initcall levels The multithreaded-probing code has a problem: after one initcall level (eg, core_initcall) has been processed, we will then start processing the next level (postcore_initcall) while the kernel threads which are handling core_initcall are still executing. This breaks the guarantees which the layered initcalls previously gave us. IOW, we want to be multithreaded _within_ an initcall level, but not between different levels. Fix that up by causing the probing code to wait for all outstanding probes at one level to complete before we start processing the next level. Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/dd.c | 30 ++++++++++++++++++++++++++++++ include/asm-generic/vmlinux.lds.h | 9 ++++++++- include/linux/init.h | 28 +++++++++++++++++++--------- 3 files changed, 57 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index db01b95a47a5..c5d6bb4290ad 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "base.h" #include "power/power.h" @@ -70,6 +71,8 @@ struct stupid_thread_structure { }; static atomic_t probe_count = ATOMIC_INIT(0); +static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); + static int really_probe(void *void_data) { struct stupid_thread_structure *data = void_data; @@ -121,6 +124,7 @@ probe_failed: done: kfree(data); atomic_dec(&probe_count); + wake_up(&probe_waitqueue); return ret; } @@ -337,6 +341,32 @@ void driver_detach(struct device_driver * drv) } } +#ifdef CONFIG_PCI_MULTITHREAD_PROBE +static int __init wait_for_probes(void) +{ + DEFINE_WAIT(wait); + + printk(KERN_INFO "%s: waiting for %d threads\n", __FUNCTION__, + atomic_read(&probe_count)); + if (!atomic_read(&probe_count)) + return 0; + while (atomic_read(&probe_count)) { + prepare_to_wait(&probe_waitqueue, &wait, TASK_UNINTERRUPTIBLE); + if (atomic_read(&probe_count)) + schedule(); + } + finish_wait(&probe_waitqueue, &wait); + return 0; +} + +core_initcall_sync(wait_for_probes); +postcore_initcall_sync(wait_for_probes); +arch_initcall_sync(wait_for_probes); +subsys_initcall_sync(wait_for_probes); +fs_initcall_sync(wait_for_probes); +device_initcall_sync(wait_for_probes); +late_initcall_sync(wait_for_probes); +#endif EXPORT_SYMBOL_GPL(device_bind_driver); EXPORT_SYMBOL_GPL(device_release_driver); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index e3e83bcaf710..9d873163a7ab 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -216,10 +216,17 @@ #define INITCALLS \ *(.initcall1.init) \ + *(.initcall1s.init) \ *(.initcall2.init) \ + *(.initcall2s.init) \ *(.initcall3.init) \ + *(.initcall3s.init) \ *(.initcall4.init) \ + *(.initcall4s.init) \ *(.initcall5.init) \ + *(.initcall5s.init) \ *(.initcall6.init) \ - *(.initcall7.init) + *(.initcall6s.init) \ + *(.initcall7.init) \ + *(.initcall7s.init) diff --git a/include/linux/init.h b/include/linux/init.h index e92b1455d7af..ff40ea118e3a 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -84,19 +84,29 @@ extern void setup_arch(char **); * by link order. * For backwards compatibility, initcall() puts the call in * the device init subsection. + * + * The `id' arg to __define_initcall() is needed so that multiple initcalls + * can point at the same handler without causing duplicate-symbol build errors. */ -#define __define_initcall(level,fn) \ - static initcall_t __initcall_##fn __attribute_used__ \ +#define __define_initcall(level,fn,id) \ + static initcall_t __initcall_##fn##id __attribute_used__ \ __attribute__((__section__(".initcall" level ".init"))) = fn -#define core_initcall(fn) __define_initcall("1",fn) -#define postcore_initcall(fn) __define_initcall("2",fn) -#define arch_initcall(fn) __define_initcall("3",fn) -#define subsys_initcall(fn) __define_initcall("4",fn) -#define fs_initcall(fn) __define_initcall("5",fn) -#define device_initcall(fn) __define_initcall("6",fn) -#define late_initcall(fn) __define_initcall("7",fn) +#define core_initcall(fn) __define_initcall("1",fn,1) +#define core_initcall_sync(fn) __define_initcall("1s",fn,1s) +#define postcore_initcall(fn) __define_initcall("2",fn,2) +#define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s) +#define arch_initcall(fn) __define_initcall("3",fn,3) +#define arch_initcall_sync(fn) __define_initcall("3s",fn,3s) +#define subsys_initcall(fn) __define_initcall("4",fn,4) +#define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s) +#define fs_initcall(fn) __define_initcall("5",fn,5) +#define fs_initcall_sync(fn) __define_initcall("5s",fn,5s) +#define device_initcall(fn) __define_initcall("6",fn,6) +#define device_initcall_sync(fn) __define_initcall("6s",fn,6s) +#define late_initcall(fn) __define_initcall("7",fn,7) +#define late_initcall_sync(fn) __define_initcall("7s",fn,7s) #define __initcall(fn) device_initcall(fn) -- cgit v1.2.3 From efbfe96c5d839c367249bf1cd53249716450c0a2 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Fri, 27 Oct 2006 23:24:47 +0200 Subject: [PATCH] silence 'make xmldocs' warning by adding missing description of 'raw' in nand_base.c:1485 Add description of 'raw' in comments for drivers/mtd/nand/nand_base.c::nand_write_page_syndrome() so 'make xmldocs' will not spew a warning at us. Signed-off-by: Jesper Juhl Acked-by: Thomas Gleixner Signed-off-by: Linus Torvalds --- drivers/mtd/nand/nand_base.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index baece61169f4..41bfcae1fbf4 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1479,6 +1479,7 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, * @buf: the data to write * @page: page number to write * @cached: cached programming + * @raw: use _raw version of write_page */ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int page, int cached, int raw) -- cgit v1.2.3 From 2b6e845986347ef86729e8651908af3e8a8441f5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 28 Oct 2006 10:38:30 -0700 Subject: [PATCH] md: fix bug where spares don't always get rebuilt properly when they become live If save_raid_disk is >= 0, then the device could be a device that is already in sync that is being re-added. So we need to default this value to -1. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 7daa7b1e145f..c40ce9f9cc9b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2003,6 +2003,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi kobject_init(&rdev->kobj); rdev->desc_nr = -1; + rdev->saved_raid_disk = -1; rdev->flags = 0; rdev->data_offset = 0; rdev->sb_events = 0; -- cgit v1.2.3 From 01ab5662f573fe3a6bcefa200f15ab3069cec8a3 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 28 Oct 2006 10:38:30 -0700 Subject: [PATCH] md: simplify checking of available size when resizing an array When "mdadm --grow --size=xxx" is used to resize an array (use more or less of each device), we check the new siza against the available space in each device. We already have that number recorded in rdev->size, so calculating it is pointless (and wrong in one obscure case). Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index c40ce9f9cc9b..50ab4a936e30 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4045,11 +4045,8 @@ static int update_size(mddev_t *mddev, unsigned long size) return -EBUSY; ITERATE_RDEV(mddev,rdev,tmp) { sector_t avail; - if (rdev->sb_offset > rdev->data_offset) - avail = (rdev->sb_offset*2) - rdev->data_offset; - else - avail = get_capacity(rdev->bdev->bd_disk) - - rdev->data_offset; + avail = rdev->size * 2; + if (fit && (size == 0 || size > avail/2)) size = avail/2; if (avail < ((sector_t)size << 1)) -- cgit v1.2.3 From 750a8f3e8f64654a584e54038c2c8db380813c79 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 28 Oct 2006 10:38:31 -0700 Subject: [PATCH] md: fix up maintenance of ->degraded in multipath A recent fix which made sure ->degraded was initialised properly exposed a second bug - ->degraded wasn't been updated when drives failed or were hot-added. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/multipath.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index a6260f0e3b9e..14da37fee37b 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -277,6 +277,7 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) set_bit(Faulty, &rdev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags); conf->working_disks--; + mddev->degraded++; printk(KERN_ALERT "multipath: IO failure on %s," " disabling IO path. \n Operation continuing" " on %d IO paths.\n", @@ -336,6 +337,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); conf->working_disks++; + mddev->degraded--; rdev->raid_disk = path; set_bit(In_sync, &rdev->flags); rcu_assign_pointer(p->rdev, rdev); -- cgit v1.2.3 From 969b755aadf7bcf3df5991a127a103acd0145a52 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Oct 2006 10:38:32 -0700 Subject: [PATCH] md: fix printk format warnings, seen on powerpc64: drivers/md/raid1.c:1479: warning: long long unsigned int format, long unsigned int arg (arg 4) drivers/md/raid10.c:1475: warning: long long unsigned int format, long unsigned int arg (arg 4) Signed-off-by: Randy Dunlap Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid1.c | 4 ++-- drivers/md/raid10.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index dc9d2def0270..656fae912fe3 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1474,8 +1474,8 @@ static void fix_read_error(conf_t *conf, int read_disk, "raid1:%s: read error corrected " "(%d sectors at %llu on %s)\n", mdname(mddev), s, - (unsigned long long)sect + - rdev->data_offset, + (unsigned long long)(sect + + rdev->data_offset), bdevname(rdev->bdev, b)); } } diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 74f17a9a6ebb..7492d6033ac6 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1470,8 +1470,8 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) "raid10:%s: read error corrected" " (%d sectors at %llu on %s)\n", mdname(mddev), s, - (unsigned long long)sect+ - rdev->data_offset, + (unsigned long long)(sect+ + rdev->data_offset), bdevname(rdev->bdev, b)); rdev_dec_pending(rdev, mddev); -- cgit v1.2.3 From 760fe9ad1692361770bb56fa5c69cf6b3354858c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Oct 2006 10:38:39 -0700 Subject: [PATCH] ioc4: fix printk format warning Fix printk format warning: drivers/misc/ioc4.c:213: warning: long long int format, u64 arg (arg 3) Signed-off-by: Randy Dunlap Acked-by: Brent Casavant Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/ioc4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/ioc4.c b/drivers/misc/ioc4.c index 79354bbbbd6a..b995a15b7526 100644 --- a/drivers/misc/ioc4.c +++ b/drivers/misc/ioc4.c @@ -210,8 +210,8 @@ ioc4_clock_calibrate(struct ioc4_driver_data *idd) do_div(ns, IOC4_EXTINT_COUNT_DIVISOR); printk(KERN_DEBUG - "IOC4 %s: PCI clock is %lld ns.\n", - pci_name(idd->idd_pdev), ns); + "IOC4 %s: PCI clock is %llu ns.\n", + pci_name(idd->idd_pdev), (unsigned long long)ns); } /* Remember results. We store the extint clock period rather -- cgit v1.2.3 From 7b92aadfdae85ef837db343be38d4172115be72b Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Oct 2006 10:38:40 -0700 Subject: [PATCH] cciss: fix printk format warning Fix printk format warnings: drivers/block/cciss.c:2000: warning: long long int format, long unsigned int arg (arg 2) drivers/block/cciss.c:2035: warning: long long int format, long unsigned int arg (arg 2) Signed-off-by: Randy Dunlap Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index bc6602606fb5..6ffe2b2bdacc 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1992,8 +1992,8 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, *block_size = BLOCK_SIZE; } if (*total_size != (__u32) 0) - printk(KERN_INFO " blocks= %lld block_size= %d\n", - *total_size, *block_size); + printk(KERN_INFO " blocks= %llu block_size= %d\n", + (unsigned long long)*total_size, *block_size); kfree(buf); return; } @@ -2027,8 +2027,8 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, *total_size = 0; *block_size = BLOCK_SIZE; } - printk(KERN_INFO " blocks= %lld block_size= %d\n", - *total_size, *block_size); + printk(KERN_INFO " blocks= %llu block_size= %d\n", + (unsigned long long)*total_size, *block_size); kfree(buf); return; } -- cgit v1.2.3 From eba6cd671427df295c10b54ee69cd5de419d38fe Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 28 Oct 2006 10:38:55 -0700 Subject: [PATCH] move SYS_HYPERVISOR inside the Generic Driver menu Put SYS_HYPERVISOR inside the Generic Driver Config menu where it should be. Otherwise xconfig displays it as a dangling (lost) menu item under Device Drivers, all by itself (when all options are displayed). Signed-off-by: Randy Dunlap Cc: Cc: Martin Schwidefsky Cc: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 0b4e22436935..1429f3a2629e 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -37,8 +37,8 @@ config DEBUG_DRIVER If you are unsure about this, say N here. -endmenu - config SYS_HYPERVISOR bool default n + +endmenu -- cgit v1.2.3 From c333526f489044be2b93085720eb898f0037b346 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 28 Oct 2006 10:38:57 -0700 Subject: [PATCH] JMB 368 PATA detection The Jmicron JMB368 is PATA only so has the PATA on function zero. Don't therefore skip function zero on this device when probing Signed-off-by: Alan Cox Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/generic.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index ad418ce882ca..e72ab36a5494 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -247,8 +247,10 @@ static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_devi (!(PCI_FUNC(dev->devfn) & 1))) goto out; - if (dev->vendor == PCI_VENDOR_ID_JMICRON && PCI_FUNC(dev->devfn) != 1) - goto out; + if (dev->vendor == PCI_VENDOR_ID_JMICRON) { + if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1) + goto out; + } if (dev->vendor != PCI_VENDOR_ID_JMICRON) { pci_read_config_word(dev, PCI_COMMAND, &command); -- cgit v1.2.3 From fd0c5eca447254682a8372bc73b6bdcc16bf6777 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 27 Oct 2006 17:20:42 -0700 Subject: [WATCHDOG] config.h removal config.h got removed Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/char/watchdog/pc87413_wdt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pc87413_wdt.c b/drivers/char/watchdog/pc87413_wdt.c index bd7727ba1ad9..1d447e32af41 100644 --- a/drivers/char/watchdog/pc87413_wdt.c +++ b/drivers/char/watchdog/pc87413_wdt.c @@ -18,7 +18,6 @@ * Release 1.1 */ -#include #include #include #include -- cgit v1.2.3 From 84b5abe69ff600a559e1a1fa29f1edad707d4e2f Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 28 Oct 2006 22:30:17 +0100 Subject: [ARM] Fix i2c-pxa slave mode support i2c-pxa times out when trying to enable slave mode due to an incorrect test. Also, check that i2c->slave is non-NULL before dereferencing it. Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 81050d3c9b21..c95a6c154165 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -272,7 +272,8 @@ static int i2c_pxa_wait_slave(struct pxa_i2c *i2c) dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", __func__, (long)jiffies, ISR, ICR, IBMR); - if ((ISR & (ISR_UB|ISR_IBB|ISR_SAD)) == ISR_SAD || + if ((ISR & (ISR_UB|ISR_IBB)) == 0 || + (ISR & ISR_SAD) != 0 || (ICR & ICR_SCLE) == 0) { if (i2c_debug > 1) dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); @@ -492,7 +493,10 @@ static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) if (isr & ISR_BED) { /* what should we do here? */ } else { - int ret = i2c->slave->read(i2c->slave->data); + int ret = 0; + + if (i2c->slave != NULL) + ret = i2c->slave->read(i2c->slave->data); IDBR = ret; ICR |= ICR_TB; /* allow next byte */ -- cgit v1.2.3 From 9468613b2bb0a386af563953b613efc6c77bd8c1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 28 Oct 2006 22:42:56 +0100 Subject: [ARM] Fix suspend oops caused by PXA2xx PCMCIA driver The PXA2xx PCMCIA driver was registering a device_driver with the platform_bus_type. Unfortunately, this causes data outside the device_driver structure to be dereferenced as if it were a platform_driver structure, causing an oops. Convert the PXA2xx core driver to use the proper platform_driver structure. Signed-off-by: Russell King --- drivers/pcmcia/pxa2xx_base.c | 41 +++++++++++++++++++++++++++++------------ drivers/pcmcia/pxa2xx_base.h | 2 +- drivers/pcmcia/pxa2xx_lubbock.c | 2 +- 3 files changed, 31 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index b3518131ea0d..dca9f8549b32 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -166,7 +166,7 @@ pxa2xx_pcmcia_frequency_change(struct soc_pcmcia_socket *skt, } #endif -int pxa2xx_drv_pcmcia_probe(struct device *dev) +int __pxa2xx_drv_pcmcia_probe(struct device *dev) { int ret; struct pcmcia_low_level *ops; @@ -203,35 +203,52 @@ int pxa2xx_drv_pcmcia_probe(struct device *dev) return ret; } -EXPORT_SYMBOL(pxa2xx_drv_pcmcia_probe); +EXPORT_SYMBOL(__pxa2xx_drv_pcmcia_probe); -static int pxa2xx_drv_pcmcia_resume(struct device *dev) + +static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev) +{ + return __pxa2xx_drv_pcmcia_probe(&dev->dev); +} + +static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev) +{ + return soc_common_drv_pcmcia_remove(&dev->dev); +} + +static int pxa2xx_drv_pcmcia_suspend(struct platform_device *dev, pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int pxa2xx_drv_pcmcia_resume(struct platform_device *dev) { - struct pcmcia_low_level *ops = dev->platform_data; + struct pcmcia_low_level *ops = dev->dev.platform_data; int nr = ops ? ops->nr : 0; MECR = nr > 1 ? MECR_CIT | MECR_NOS : (nr > 0 ? MECR_CIT : 0); - return pcmcia_socket_dev_resume(dev); + return pcmcia_socket_dev_resume(&dev->dev); } -static struct device_driver pxa2xx_pcmcia_driver = { +static struct platform_driver pxa2xx_pcmcia_driver = { .probe = pxa2xx_drv_pcmcia_probe, - .remove = soc_common_drv_pcmcia_remove, - .suspend = pcmcia_socket_dev_suspend, + .remove = pxa2xx_drv_pcmcia_remove, + .suspend = pxa2xx_drv_pcmcia_suspend, .resume = pxa2xx_drv_pcmcia_resume, - .name = "pxa2xx-pcmcia", - .bus = &platform_bus_type, + .driver = { + .name = "pxa2xx-pcmcia", + }, }; static int __init pxa2xx_pcmcia_init(void) { - return driver_register(&pxa2xx_pcmcia_driver); + return platform_driver_register(&pxa2xx_pcmcia_driver); } static void __exit pxa2xx_pcmcia_exit(void) { - driver_unregister(&pxa2xx_pcmcia_driver); + platform_driver_unregister(&pxa2xx_pcmcia_driver); } fs_initcall(pxa2xx_pcmcia_init); diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h index e46cff345d47..235d681652c3 100644 --- a/drivers/pcmcia/pxa2xx_base.h +++ b/drivers/pcmcia/pxa2xx_base.h @@ -1,3 +1,3 @@ /* temporary measure */ -extern int pxa2xx_drv_pcmcia_probe(struct device *); +extern int __pxa2xx_drv_pcmcia_probe(struct device *); diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index fd1f691c7c2c..a92f11143c43 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c @@ -260,7 +260,7 @@ int __init pcmcia_lubbock_init(struct sa1111_dev *sadev) lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); sadev->dev.platform_data = &lubbock_pcmcia_ops; - ret = pxa2xx_drv_pcmcia_probe(&sadev->dev); + ret = __pxa2xx_drv_pcmcia_probe(&sadev->dev); } return ret; -- cgit v1.2.3 From 58c6570add83e30c0905885171fbffc134441165 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 29 Oct 2006 03:43:19 +0900 Subject: [WATCHDOG] sc1200wdt.c pnp unregister fix. If no devices found or invalid parameter is specified, scl200wdt_pnp_driver is left unregistered. It breaks global list of pnp drivers. Signed-off-by: Akinobu Mita Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/char/watchdog/sc1200wdt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index d8d0f28e0acf..e3239833e4b0 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -392,7 +392,7 @@ static int __init sc1200wdt_init(void) if (io == -1) { printk(KERN_ERR PFX "io parameter must be specified\n"); ret = -EINVAL; - goto out_clean; + goto out_pnp; } #if defined CONFIG_PNP @@ -405,7 +405,7 @@ static int __init sc1200wdt_init(void) if (!request_region(io, io_len, SC1200_MODULE_NAME)) { printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); ret = -EBUSY; - goto out_clean; + goto out_pnp; } ret = sc1200wdt_probe(); @@ -435,6 +435,11 @@ out_rbt: out_io: release_region(io, io_len); +out_pnp: +#if defined CONFIG_PNP + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); +#endif goto out_clean; } -- cgit v1.2.3 From 346f5c7ee7fa4ebee0e4c96415a7e59716bfa1d0 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sun, 29 Oct 2006 19:52:49 +0100 Subject: ieee1394: ohci1394: revert fail on error in suspend Some errors during preparation for suspended state can be skipped with a warning instead of a failure of the whole suspend transition, notably an error in pci_set_power_state. Signed-off-by: Stefan Richter --- drivers/ieee1394/ohci1394.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index dea13525df88..6e8ea9110c46 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c @@ -3552,12 +3552,21 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) { int err; + printk(KERN_INFO "%s does not fully support suspend and resume yet\n", + OHCI1394_DRIVER_NAME); + err = pci_save_state(pdev); - if (err) - goto out; + if (err) { + printk(KERN_ERR "%s: pci_save_state failed with %d\n", + OHCI1394_DRIVER_NAME, err); + return err; + } err = pci_set_power_state(pdev, pci_choose_state(pdev, state)); +#ifdef OHCI1394_DEBUG if (err) - goto out; + printk(KERN_DEBUG "%s: pci_set_power_state failed with %d\n", + OHCI1394_DRIVER_NAME, err); +#endif /* OHCI1394_DEBUG */ /* PowerMac suspend code comes last */ #ifdef CONFIG_PPC_PMAC @@ -3570,8 +3579,8 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state) pmac_call_feature(PMAC_FTR_1394_ENABLE, of_node, 0, 0); } #endif /* CONFIG_PPC_PMAC */ -out: - return err; + + return 0; } #endif /* CONFIG_PM */ -- cgit v1.2.3 From 150ed8ed63b96d7f93ef7e6081797aa0df2b1abd Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 29 Oct 2006 03:43:19 +0900 Subject: [WATCHDOG] sc1200wdt.c pnp unregister fix. If no devices found or invalid parameter is specified, scl200wdt_pnp_driver is left unregistered. It breaks global list of pnp drivers. Signed-off-by: Akinobu Mita Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/char/watchdog/sc1200wdt.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c index d8d0f28e0acf..e3239833e4b0 100644 --- a/drivers/char/watchdog/sc1200wdt.c +++ b/drivers/char/watchdog/sc1200wdt.c @@ -392,7 +392,7 @@ static int __init sc1200wdt_init(void) if (io == -1) { printk(KERN_ERR PFX "io parameter must be specified\n"); ret = -EINVAL; - goto out_clean; + goto out_pnp; } #if defined CONFIG_PNP @@ -405,7 +405,7 @@ static int __init sc1200wdt_init(void) if (!request_region(io, io_len, SC1200_MODULE_NAME)) { printk(KERN_ERR PFX "Unable to register IO port %#x\n", io); ret = -EBUSY; - goto out_clean; + goto out_pnp; } ret = sc1200wdt_probe(); @@ -435,6 +435,11 @@ out_rbt: out_io: release_region(io, io_len); +out_pnp: +#if defined CONFIG_PNP + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); +#endif goto out_clean; } -- cgit v1.2.3 From 209ad53bc19667a128d9c51beba873a5c62bff6e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 29 Oct 2006 17:31:49 -0800 Subject: Revert "r8169: mac address change support" This reverts commit a2b98a697fa4e7564f78905b83db122824916cf9. As per Guennadi Liakhovetski, the mac address change support code breaks some normal uses (_without_ any address changes), and until it's all sorted out, we're better off without it. Says Francois: "Go revert it. Despite what I claimed, I can not find a third-party confirmation by email that it works elsewhere. It would probably be enough to remove the call to __rtl8169_set_mac_addr() in rtl8169_hw_start() though." See also http://bugzilla.kernel.org/show_bug.cgi?id=6032 Cc: Guennadi Liakhovetski Acked-by: Francois Romieu Signed-off-by: Linus Torvalds --- drivers/net/r8169.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index d132fe7d475e..27f90b2139c0 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1397,41 +1397,6 @@ static void rtl8169_netpoll(struct net_device *dev) } #endif -static void __rtl8169_set_mac_addr(struct net_device *dev, void __iomem *ioaddr) -{ - unsigned int i, j; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - for (i = 0; i < 2; i++) { - __le32 l = 0; - - for (j = 0; j < 4; j++) { - l <<= 8; - l |= dev->dev_addr[4*i + j]; - } - RTL_W32(MAC0 + 4*i, cpu_to_be32(l)); - } - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_mac_addr(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - if (netif_running(dev)) { - spin_lock_irq(&tp->lock); - __rtl8169_set_mac_addr(dev, tp->mmio_addr); - spin_unlock_irq(&tp->lock); - } - return 0; -} - static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, void __iomem *ioaddr) { @@ -1681,7 +1646,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->stop = rtl8169_close; dev->tx_timeout = rtl8169_tx_timeout; dev->set_multicast_list = rtl8169_set_rx_mode; - dev->set_mac_address = rtl8169_set_mac_addr; dev->watchdog_timeo = RTL8169_TX_TIMEOUT; dev->irq = pdev->irq; dev->base_addr = (unsigned long) ioaddr; @@ -1929,8 +1893,6 @@ rtl8169_hw_start(struct net_device *dev) /* Enable all known interrupts by setting the interrupt mask. */ RTL_W16(IntrMask, rtl8169_intr_mask); - __rtl8169_set_mac_addr(dev, ioaddr); - netif_start_queue(dev); } -- cgit v1.2.3 From 37af6560f7978c60791b5f3df17ce8b3e97f2d6e Mon Sep 17 00:00:00 2001 From: Christophe Saout Date: Mon, 30 Oct 2006 20:39:08 +0100 Subject: [PATCH] Fix dmsetup table output change Fix dm-crypt after the block cipher API changes to correctly return the backwards compatible cipher-chainmode[-ivmode] format for "dmsetup table". Signed-off-by: Christophe Saout Cc: Alasdair G Kergon Cc: Herbert Xu Signed-off-by: Linus Torvalds diff linux-2.6.19-rc3.orig/drivers/md/dm-crypt.c linux-2.6.19-rc3/drivers/md/dm-crypt.c --- drivers/md/dm-crypt.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a625576fdeeb..08a40f4e4f60 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -915,8 +915,6 @@ static int crypt_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) { struct crypt_config *cc = (struct crypt_config *) ti->private; - const char *cipher; - const char *chainmode = NULL; unsigned int sz = 0; switch (type) { @@ -925,14 +923,11 @@ static int crypt_status(struct dm_target *ti, status_type_t type, break; case STATUSTYPE_TABLE: - cipher = crypto_blkcipher_name(cc->tfm); - - chainmode = cc->chainmode; - if (cc->iv_mode) - DMEMIT("%s-%s-%s ", cipher, chainmode, cc->iv_mode); + DMEMIT("%s-%s-%s ", cc->cipher, cc->chainmode, + cc->iv_mode); else - DMEMIT("%s-%s ", cipher, chainmode); + DMEMIT("%s-%s ", cc->cipher, cc->chainmode); if (cc->key_size > 0) { if ((maxlen - sz) < ((cc->key_size << 1) + 1)) -- cgit v1.2.3 From a5a89bae0449634fdb7aa7cdb1c5ba154e4a789b Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 29 Oct 2006 22:46:33 -0800 Subject: [PATCH] ioc4_serial: irq flags fix Use the correct type for the CPU flags. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/ioc4_serial.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index ff4fa25f9fd1..711bd1511439 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -921,7 +921,7 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir) { struct ioc4_port *port = (struct ioc4_port *)arg; struct hooks *hooks = port->ip_hooks; - unsigned int flags; + unsigned long flags; spin_lock_irqsave(&port->ip_lock, flags); @@ -1834,7 +1834,7 @@ static void handle_intr(void *arg, uint32_t sio_ir) struct ioc4_port *port = (struct ioc4_port *)arg; struct hooks *hooks = port->ip_hooks; unsigned int rx_high_rd_aborted = 0; - unsigned int flags; + unsigned long flags; struct uart_port *the_port; int loop_counter; -- cgit v1.2.3 From 70812522b847bdb8fabee963191734f5fa3143f3 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 29 Oct 2006 22:46:35 -0800 Subject: [PATCH] isdn/gigaset: avoid cs->dev null pointer dereference When gigaset_initbcs() is called, cs->dev is not initialized yet. If dev_alloc_skb() failed in this function, NULL poinster dereference will happen at dev_warn(). Cc: Kai Germaschewski Cc: Hansjoerg Lipp Cc: Tilman Schmidt Acked-by: Karsten Keil Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index aca165d43aa0..d8d256dadddf 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -616,7 +616,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else { - dev_warn(cs->dev, "could not allocate skb\n"); + gig_dbg(DEBUG_INIT, "could not allocate skb\n"); bcs->inputstate |= INS_skip_frame; } -- cgit v1.2.3 From 7259f0d05d595b73ef312a082e628627c6414969 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sun, 29 Oct 2006 22:46:36 -0800 Subject: [PATCH] lockdep: annotate DECLARE_WAIT_QUEUE_HEAD kernel: INFO: trying to register non-static key. kernel: the code is fine but needs lockdep annotation. kernel: turning off the locking correctness validator. kernel: [] show_trace_log_lvl+0x58/0x16a kernel: [] show_trace+0xd/0x10 kernel: [] dump_stack+0x19/0x1b kernel: [] __lock_acquire+0xf0/0x90d kernel: [] lock_acquire+0x4b/0x6b kernel: [] _spin_lock_irqsave+0x22/0x32 kernel: [] prepare_to_wait+0x17/0x4b kernel: [] lpfc_do_work+0xdd/0xcc2 [lpfc] kernel: [] kthread+0xc3/0xf2 kernel: [] kernel_thread_helper+0x5/0xb Another case of non-static lockdep keys; duplicate the paradigm set by DECLARE_COMPLETION_ONSTACK and introduce DECLARE_WAIT_QUEUE_HEAD_ONSTACK. Signed-off-by: Peter Zijlstra Cc: Greg KH Cc: Markus Lidel Acked-by: Ingo Molnar Cc: Arjan van de Ven Cc: James Bottomley Cc: Marcel Holtmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/bluetooth/bluecard_cs.c | 2 +- drivers/message/i2o/exec-osm.c | 2 +- drivers/scsi/dpt/dpti_i2o.h | 2 +- drivers/scsi/imm.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 4 ++-- drivers/scsi/ppa.c | 2 +- drivers/usb/net/usbnet.c | 2 +- include/linux/wait.h | 9 +++++++++ 9 files changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 845b8680032a..cbc07250b898 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -282,7 +282,7 @@ static void bluecard_write_wakeup(bluecard_info_t *info) clear_bit(ready_bit, &(info->tx_state)); if (bt_cb(skb)->pkt_type & 0x80) { - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); DEFINE_WAIT(wait); unsigned char baud_reg; diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index 01a5a702b037..a2350640384b 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -124,7 +124,7 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait) int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg, unsigned long timeout, struct i2o_dma *dma) { - DECLARE_WAIT_QUEUE_HEAD(wq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq); struct i2o_exec_wait *wait; static u32 tcntxt = 0x80000000; unsigned long flags; diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h index b3fa7ed71faf..5a49216fe4cf 100644 --- a/drivers/scsi/dpt/dpti_i2o.h +++ b/drivers/scsi/dpt/dpti_i2o.h @@ -49,7 +49,7 @@ #include typedef wait_queue_head_t adpt_wait_queue_head_t; -#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD(wait) +#define ADPT_DECLARE_WAIT_QUEUE_HEAD(wait) DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait) typedef wait_queue_t adpt_wait_queue_t; /* diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 2d95ac9c32c1..e31f6122106f 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -1153,7 +1153,7 @@ static int __imm_attach(struct parport *pb) { struct Scsi_Host *host; imm_struct *dev; - DECLARE_WAIT_QUEUE_HEAD(waiting); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting); DEFINE_WAIT(wait); int ports; int modes, ppb; diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d586c3d3b0d0..19c79a0549a7 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -305,7 +305,7 @@ lpfc_do_work(void *p) { struct lpfc_hba *phba = p; int rc; - DECLARE_WAIT_QUEUE_HEAD(work_waitq); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(work_waitq); set_user_nice(current, -20); phba->work_wait = &work_waitq; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 24a1779b9af4..582f5ea4e84e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2983,7 +2983,7 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba, struct lpfc_iocbq * prspiocbq, uint32_t timeout) { - DECLARE_WAIT_QUEUE_HEAD(done_q); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); long timeleft, timeout_req = 0; int retval = IOCB_SUCCESS; uint32_t creg_val; @@ -3061,7 +3061,7 @@ int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq, uint32_t timeout) { - DECLARE_WAIT_QUEUE_HEAD(done_q); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); DECLARE_WAITQUEUE(wq_entry, current); uint32_t timeleft = 0; int retval; diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index b0eba39f208a..89a2a9f11e41 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -1012,7 +1012,7 @@ static LIST_HEAD(ppa_hosts); static int __ppa_attach(struct parport *pb) { struct Scsi_Host *host; - DECLARE_WAIT_QUEUE_HEAD(waiting); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waiting); DEFINE_WAIT(wait); ppa_struct *dev; int ports; diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index cf3d20eb781c..40873635d80e 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -554,7 +554,7 @@ static int usbnet_stop (struct net_device *net) { struct usbnet *dev = netdev_priv(net); int temp; - DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); + DECLARE_WAIT_QUEUE_HEAD_ONSTACK (unlink_wakeup); DECLARE_WAITQUEUE (wait, current); netif_stop_queue (net); diff --git a/include/linux/wait.h b/include/linux/wait.h index b3b9048421d8..e820d00e1383 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -79,6 +79,15 @@ struct task_struct; extern void init_waitqueue_head(wait_queue_head_t *q); +#ifdef CONFIG_LOCKDEP +# define __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) \ + ({ init_waitqueue_head(&name); name; }) +# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) \ + wait_queue_head_t name = __WAIT_QUEUE_HEAD_INIT_ONSTACK(name) +#else +# define DECLARE_WAIT_QUEUE_HEAD_ONSTACK(name) DECLARE_WAIT_QUEUE_HEAD(name) +#endif + static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p) { q->flags = 0; -- cgit v1.2.3 From 2b52c9590d5ad2fb67b720ec12018dd2cf061480 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Sun, 29 Oct 2006 22:46:44 -0800 Subject: [PATCH] drivers/ide/pci/generic.c: add missing newline to the all-generic-ide message Signed-off-by: Sergey Vlasov Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c index e72ab36a5494..9f306880491a 100644 --- a/drivers/ide/pci/generic.c +++ b/drivers/ide/pci/generic.c @@ -48,7 +48,7 @@ static int ide_generic_all; /* Set to claim all devices */ static int __init ide_generic_all_on(char *unused) { ide_generic_all = 1; - printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers."); + printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n"); return 1; } __setup("all-generic-ide", ide_generic_all_on); -- cgit v1.2.3 From d458fd82c9bb536e4a582955e88554a02a92bf78 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 26 Oct 2006 17:15:20 -0700 Subject: [NET] sealevel: uses arp_broken_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Wed, 25 Oct 2006 18:03:13 +0200 Toralf Förster wrote: > WARNING: "arp_broken_ops" [drivers/net/wan/sealevel.ko] undefined! > make[1]: *** [__modpost] Error 1 > make: *** [modules] Error 2 > > Here's the config: ... > # CONFIG_INET is not set > CONFIG_SEALEVEL_4021=m Sealevel uses arp_broken_ops so it needs to depend on INET. Signed-off-by: Randy Dunlap Signed-off-by: David S. Miller --- drivers/net/wan/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 58b7efbb0750..b5d0d7fb647a 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -127,7 +127,7 @@ config LANMEDIA # There is no way to detect a Sealevel board. Force it modular config SEALEVEL_4021 tristate "Sealevel Systems 4021 support" - depends on WAN && ISA && m && ISA_DMA_API + depends on WAN && ISA && m && ISA_DMA_API && INET help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. -- cgit v1.2.3 From c20e3945c761502b9d5d73ef0ff5f1a84b3a717e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 29 Oct 2006 16:14:55 -0800 Subject: [ETH1394]: Fix unaligned accesses. Several u64 objects are derefernced in situations where the pointer is not guarenteed to be aligned correctly. Use get_unaligned() as needed. Thanks to Will Simoneau for lots of testing and debugging help. Signed-off-by: David S. Miller Acked-by: Stefan Richter --- drivers/ieee1394/eth1394.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 8a7b8fab6238..31e5cc49d61a 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c @@ -64,6 +64,7 @@ #include #include #include +#include #include #include "config_roms.h" @@ -491,7 +492,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) int i; struct eth1394_priv *priv = netdev_priv(dev); struct hpsb_host *host = priv->host; - u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); + u64 guid = get_unaligned((u64*)&(host->csr.rom->bus_info_data[3])); u16 maxpayload = 1 << (host->csr.max_rec + 1); int max_speed = IEEE1394_SPEED_MAX; @@ -514,8 +515,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) ETHER1394_GASP_OVERHEAD))); /* Set our hardware address while we're at it */ - *(u64*)dev->dev_addr = guid; - *(u64*)dev->broadcast = ~0x0ULL; + memcpy(dev->dev_addr, &guid, sizeof(u64)); + memset(dev->broadcast, 0xff, sizeof(u64)); } spin_unlock_irqrestore (&priv->lock, flags); @@ -894,6 +895,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, u16 maxpayload; struct eth1394_node_ref *node; struct eth1394_node_info *node_info; + __be64 guid; /* Sanity check. MacOSX seems to be sending us 131 in this * field (atleast on my Panther G5). Not sure why. */ @@ -902,8 +904,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); + guid = get_unaligned(&arp1394->s_uniq_id); node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(arp1394->s_uniq_id)); + be64_to_cpu(guid)); if (!node) { return 0; } @@ -931,10 +934,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, arp_ptr += arp->ar_pln; /* skip over sender IP addr */ if (arp->ar_op == htons(ARPOP_REQUEST)) - /* just set ARP req target unique ID to 0 */ - *((u64*)arp_ptr) = 0; + memset(arp_ptr, 0, sizeof(u64)); else - *((u64*)arp_ptr) = *((u64*)dev->dev_addr); + memcpy(arp_ptr, dev->dev_addr, sizeof(u64)); } /* Now add the ethernet header. */ @@ -1675,8 +1677,10 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) priv->bc_dgl++; } else { + __be64 guid = get_unaligned((u64 *)eth->h_dest); + node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(*(u64*)eth->h_dest)); + be64_to_cpu(guid)); if (!node) { ret = -EAGAIN; goto fail; -- cgit v1.2.3 From 1aea7e00f6b83d32d359aeb8d670f1f7aaa88d55 Mon Sep 17 00:00:00 2001 From: Kristoffer Ericson Date: Tue, 31 Oct 2006 11:47:27 +0900 Subject: video: Fix include in hp680_bl. The hp6xx.h header moved location, causing the build to fail, fix it up. Signed-off-by: Kristoffer Ericson Signed-off-by: Paul Mundt --- drivers/video/backlight/hp680_bl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c index fe1488374f62..e3993213d10e 100644 --- a/drivers/video/backlight/hp680_bl.c +++ b/drivers/video/backlight/hp680_bl.c @@ -19,7 +19,7 @@ #include #include -#include +#include #include #define HP680_MAX_INTENSITY 255 -- cgit v1.2.3 From 2e7a7426282bfa2d7dff6eddc5485af8c79a68f3 Mon Sep 17 00:00:00 2001 From: Erez Zilber Date: Sun, 22 Oct 2006 10:28:38 +0200 Subject: IB/iser: Start connection after enabling iSER When a connection is started (a new connection or a recovered one), iSER should prepare its resources for full-featured mode and only then notify the iSCSI layer that it is ready to start queueing commands. Signed-off-by: Erez Zilber Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/iser/iscsi_iser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index eb6f98d82289..9b2041e25d59 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -363,11 +363,11 @@ iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn) struct iscsi_conn *conn = cls_conn->dd_data; int err; - err = iscsi_conn_start(cls_conn); + err = iser_conn_set_full_featured_mode(conn); if (err) return err; - return iser_conn_set_full_featured_mode(conn); + return iscsi_conn_start(cls_conn); } static struct iscsi_transport iscsi_iser_transport; -- cgit v1.2.3 From 255d0c14b3757e8bd85add874e4dca4c3621b39e Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Tue, 24 Oct 2006 13:22:28 -0700 Subject: RDMA/cma: rdma_bind_addr() leaks a cma_dev reference count rdma_bind_addr() leaks a cma_dev reference count in failure case. Signed-off-by: Krishna Kumar Signed-off-by: Sean Hefty --- drivers/infiniband/core/cma.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9ae4f3a67c70..d8ca3c1368b5 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1762,22 +1762,29 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr) if (!cma_any_addr(addr)) { ret = rdma_translate_ip(addr, &id->route.addr.dev_addr); - if (!ret) { - mutex_lock(&lock); - ret = cma_acquire_dev(id_priv); - mutex_unlock(&lock); - } if (ret) - goto err; + goto err1; + + mutex_lock(&lock); + ret = cma_acquire_dev(id_priv); + mutex_unlock(&lock); + if (ret) + goto err1; } memcpy(&id->route.addr.src_addr, addr, ip_addr_size(addr)); ret = cma_get_port(id_priv); if (ret) - goto err; + goto err2; return 0; -err: +err2: + if (!cma_any_addr(addr)) { + mutex_lock(&lock); + cma_detach_from_dev(id_priv); + mutex_unlock(&lock); + } +err1: cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE); return ret; } -- cgit v1.2.3 From 04d03bc576f244bfa9692452aab83fa357ac0d57 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 25 Oct 2006 15:28:08 +1000 Subject: IB/ehca: Fix eHCA driver compilation for uniprocessor The eHCA driver does not compile for a uniprocessor configuration (CONFIG_SMP=n), due to H_SUCCESS and other symbols being undefined. This fixes it. Signed-off-by: Paul Mackerras Acked-by: Hoang-Nam Nguyen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_tools.h | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index 809da3ef706b..973c4b591545 100644 --- a/drivers/infiniband/hw/ehca/ehca_tools.h +++ b/drivers/infiniband/hw/ehca/ehca_tools.h @@ -63,6 +63,7 @@ #include #include #include +#include extern int ehca_debug_level; -- cgit v1.2.3 From 8de94ce19dd3c6fc6e9d9658da11cf3d76841ee5 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Fri, 27 Oct 2006 17:28:35 -0500 Subject: IB/amso1100: Use dma_alloc_coherent() instead of kmalloc/dma_map_single The Ammasso driver needs to use dma_alloc_coherent() for allocating memory that will be used by the HW for dma. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_alloc.c | 13 ++++---- drivers/infiniband/hw/amso1100/c2_cq.c | 18 ++++------- drivers/infiniband/hw/amso1100/c2_rnic.c | 52 +++++++++++++------------------ 3 files changed, 33 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_alloc.c b/drivers/infiniband/hw/amso1100/c2_alloc.c index 028a60bbfca9..0315f99e4191 100644 --- a/drivers/infiniband/hw/amso1100/c2_alloc.c +++ b/drivers/infiniband/hw/amso1100/c2_alloc.c @@ -42,13 +42,14 @@ static int c2_alloc_mqsp_chunk(struct c2_dev *c2dev, gfp_t gfp_mask, { int i; struct sp_chunk *new_head; + dma_addr_t dma_addr; - new_head = (struct sp_chunk *) __get_free_page(gfp_mask); + new_head = dma_alloc_coherent(&c2dev->pcidev->dev, PAGE_SIZE, + &dma_addr, gfp_mask); if (new_head == NULL) return -ENOMEM; - new_head->dma_addr = dma_map_single(c2dev->ibdev.dma_device, new_head, - PAGE_SIZE, DMA_FROM_DEVICE); + new_head->dma_addr = dma_addr; pci_unmap_addr_set(new_head, mapping, new_head->dma_addr); new_head->next = NULL; @@ -80,10 +81,8 @@ void c2_free_mqsp_pool(struct c2_dev *c2dev, struct sp_chunk *root) while (root) { next = root->next; - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(root, mapping), PAGE_SIZE, - DMA_FROM_DEVICE); - __free_page((struct page *) root); + dma_free_coherent(&c2dev->pcidev->dev, PAGE_SIZE, root, + pci_unmap_addr(root, mapping)); root = next; } } diff --git a/drivers/infiniband/hw/amso1100/c2_cq.c b/drivers/infiniband/hw/amso1100/c2_cq.c index 9d7bcc5ade93..05c9154d46f4 100644 --- a/drivers/infiniband/hw/amso1100/c2_cq.c +++ b/drivers/infiniband/hw/amso1100/c2_cq.c @@ -246,20 +246,17 @@ int c2_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify) static void c2_free_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq) { - - dma_unmap_single(c2dev->ibdev.dma_device, pci_unmap_addr(mq, mapping), - mq->q_size * mq->msg_size, DMA_FROM_DEVICE); - free_pages((unsigned long) mq->msg_pool.host, - get_order(mq->q_size * mq->msg_size)); + dma_free_coherent(&c2dev->pcidev->dev, mq->q_size * mq->msg_size, + mq->msg_pool.host, pci_unmap_addr(mq, mapping)); } static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, int q_size, int msg_size) { - unsigned long pool_start; + u8 *pool_start; - pool_start = __get_free_pages(GFP_KERNEL, - get_order(q_size * msg_size)); + pool_start = dma_alloc_coherent(&c2dev->pcidev->dev, q_size * msg_size, + &mq->host_dma, GFP_KERNEL); if (!pool_start) return -ENOMEM; @@ -267,13 +264,10 @@ static int c2_alloc_cq_buf(struct c2_dev *c2dev, struct c2_mq *mq, int q_size, 0, /* index (currently unknown) */ q_size, msg_size, - (u8 *) pool_start, + pool_start, NULL, /* peer (currently unknown) */ C2_MQ_HOST_TARGET); - mq->host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)pool_start, - q_size * msg_size, DMA_FROM_DEVICE); pci_unmap_addr_set(mq, mapping, mq->host_dma); return 0; diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 30409e179606..030238d335ed 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -517,14 +517,12 @@ int c2_rnic_init(struct c2_dev *c2dev) /* Initialize the Verbs Reply Queue */ qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_QSIZE)); msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q1_MSGSIZE)); - q1_pages = kmalloc(qsize * msgsize, GFP_KERNEL); + q1_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize, + &c2dev->rep_vq.host_dma, GFP_KERNEL); if (!q1_pages) { err = -ENOMEM; goto bail1; } - c2dev->rep_vq.host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)q1_pages, qsize * msgsize, - DMA_FROM_DEVICE); pci_unmap_addr_set(&c2dev->rep_vq, mapping, c2dev->rep_vq.host_dma); pr_debug("%s rep_vq va %p dma %llx\n", __FUNCTION__, q1_pages, (unsigned long long) c2dev->rep_vq.host_dma); @@ -540,14 +538,12 @@ int c2_rnic_init(struct c2_dev *c2dev) /* Initialize the Asynchronus Event Queue */ qsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_QSIZE)); msgsize = be32_to_cpu(readl(mmio_regs + C2_REGS_Q2_MSGSIZE)); - q2_pages = kmalloc(qsize * msgsize, GFP_KERNEL); + q2_pages = dma_alloc_coherent(&c2dev->pcidev->dev, qsize * msgsize, + &c2dev->aeq.host_dma, GFP_KERNEL); if (!q2_pages) { err = -ENOMEM; goto bail2; } - c2dev->aeq.host_dma = dma_map_single(c2dev->ibdev.dma_device, - (void *)q2_pages, qsize * msgsize, - DMA_FROM_DEVICE); pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma); pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q1_pages, (unsigned long long) c2dev->rep_vq.host_dma); @@ -597,17 +593,13 @@ int c2_rnic_init(struct c2_dev *c2dev) bail4: vq_term(c2dev); bail3: - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->aeq, mapping), - c2dev->aeq.q_size * c2dev->aeq.msg_size, - DMA_FROM_DEVICE); - kfree(q2_pages); + dma_free_coherent(&c2dev->pcidev->dev, + c2dev->aeq.q_size * c2dev->aeq.msg_size, + q2_pages, pci_unmap_addr(&c2dev->aeq, mapping)); bail2: - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->rep_vq, mapping), - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - DMA_FROM_DEVICE); - kfree(q1_pages); + dma_free_coherent(&c2dev->pcidev->dev, + c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, + q1_pages, pci_unmap_addr(&c2dev->rep_vq, mapping)); bail1: c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); bail0: @@ -640,19 +632,17 @@ void c2_rnic_term(struct c2_dev *c2dev) /* Free the verbs request allocator */ vq_term(c2dev); - /* Unmap and free the asynchronus event queue */ - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->aeq, mapping), - c2dev->aeq.q_size * c2dev->aeq.msg_size, - DMA_FROM_DEVICE); - kfree(c2dev->aeq.msg_pool.host); - - /* Unmap and free the verbs reply queue */ - dma_unmap_single(c2dev->ibdev.dma_device, - pci_unmap_addr(&c2dev->rep_vq, mapping), - c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, - DMA_FROM_DEVICE); - kfree(c2dev->rep_vq.msg_pool.host); + /* Free the asynchronus event queue */ + dma_free_coherent(&c2dev->pcidev->dev, + c2dev->aeq.q_size * c2dev->aeq.msg_size, + c2dev->aeq.msg_pool.host, + pci_unmap_addr(&c2dev->aeq, mapping)); + + /* Free the verbs reply queue */ + dma_free_coherent(&c2dev->pcidev->dev, + c2dev->rep_vq.q_size * c2dev->rep_vq.msg_size, + c2dev->rep_vq.msg_pool.host, + pci_unmap_addr(&c2dev->rep_vq, mapping)); /* Free the MQ shared pointer pool */ c2_free_mqsp_pool(c2dev, c2dev->kern_mqsp_pool); -- cgit v1.2.3 From d7b748d63c908a0a85099ce546594192ae0926f6 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Mon, 30 Oct 2006 20:52:53 -0800 Subject: IB/amso1100: Fix incorrect pr_debug() pr_debug() was printing the wrong stuff. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_rnic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 030238d335ed..21d9612a56cc 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -545,8 +545,8 @@ int c2_rnic_init(struct c2_dev *c2dev) goto bail2; } pci_unmap_addr_set(&c2dev->aeq, mapping, c2dev->aeq.host_dma); - pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q1_pages, - (unsigned long long) c2dev->rep_vq.host_dma); + pr_debug("%s aeq va %p dma %llx\n", __FUNCTION__, q2_pages, + (unsigned long long) c2dev->aeq.host_dma); c2_mq_rep_init(&c2dev->aeq, 2, qsize, -- cgit v1.2.3 From 0b26c88f29ad8bcf91a2ea8f25a36f2028ebabea Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Wed, 25 Oct 2006 12:54:20 +0200 Subject: IB/uverbs: Return sq_draining value in query_qp response Return the sq_draining value back to user space for query_qp instead of the en_sqd_async notify value, which is valid only for modify_qp. For query_qp, the draining status should returned. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/core/uverbs_cmd.c | 2 +- include/rdma/ib_user_verbs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index b72c7f69ca90..743247ec065e 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -1214,7 +1214,7 @@ ssize_t ib_uverbs_query_qp(struct ib_uverbs_file *file, resp.qp_access_flags = attr->qp_access_flags; resp.pkey_index = attr->pkey_index; resp.alt_pkey_index = attr->alt_pkey_index; - resp.en_sqd_async_notify = attr->en_sqd_async_notify; + resp.sq_draining = attr->sq_draining; resp.max_rd_atomic = attr->max_rd_atomic; resp.max_dest_rd_atomic = attr->max_dest_rd_atomic; resp.min_rnr_timer = attr->min_rnr_timer; diff --git a/include/rdma/ib_user_verbs.h b/include/rdma/ib_user_verbs.h index db1b814b62cc..64a721fcbc1c 100644 --- a/include/rdma/ib_user_verbs.h +++ b/include/rdma/ib_user_verbs.h @@ -458,7 +458,7 @@ struct ib_uverbs_query_qp_resp { __u8 cur_qp_state; __u8 path_mtu; __u8 path_mig_state; - __u8 en_sqd_async_notify; + __u8 sq_draining; __u8 max_rd_atomic; __u8 max_dest_rd_atomic; __u8 min_rnr_timer; -- cgit v1.2.3 From 80fc115d461031dc66bb7f31b8c84868e370fea6 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 30 Oct 2006 20:41:11 -0800 Subject: [PATCH] SCSI: ISCSI build failure SCSI_QLA_ISCSI needs to depend on NET to prevent build (link) failures that are caused by selecting SCSI_ISCSI_ATTRS. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- drivers/scsi/qla4xxx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla4xxx/Kconfig b/drivers/scsi/qla4xxx/Kconfig index 08a07f0b8d94..69cbff3f57cf 100644 --- a/drivers/scsi/qla4xxx/Kconfig +++ b/drivers/scsi/qla4xxx/Kconfig @@ -1,6 +1,6 @@ config SCSI_QLA_ISCSI tristate "QLogic ISP4XXX host adapter family support" - depends on PCI && SCSI + depends on PCI && SCSI && NET select SCSI_ISCSI_ATTRS ---help--- This driver supports the QLogic 40xx (ISP4XXX) iSCSI host -- cgit v1.2.3 From 68586b67ab1a2fd618f79e29a06f10ae886f4b46 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Mon, 30 Oct 2006 16:31:52 +0200 Subject: IB/mthca: Fix MAD extended header format for MAD_IFC firmware command Several fields in an incoming MAD extended info header were passed into the MAD_IFC firmware command at incorrect offsets (mostly off by 4 bytes). As the result, the HCA will fail to generate traps in which this info is needed (e.g. traps which include the GRH of the incoming packet), in violation of the IB spec. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_cmd.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 99a94d710935..768df7265b81 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -1820,11 +1820,11 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, #define MAD_IFC_BOX_SIZE 0x400 #define MAD_IFC_MY_QPN_OFFSET 0x100 -#define MAD_IFC_RQPN_OFFSET 0x104 -#define MAD_IFC_SL_OFFSET 0x108 -#define MAD_IFC_G_PATH_OFFSET 0x109 -#define MAD_IFC_RLID_OFFSET 0x10a -#define MAD_IFC_PKEY_OFFSET 0x10e +#define MAD_IFC_RQPN_OFFSET 0x108 +#define MAD_IFC_SL_OFFSET 0x10c +#define MAD_IFC_G_PATH_OFFSET 0x10d +#define MAD_IFC_RLID_OFFSET 0x10e +#define MAD_IFC_PKEY_OFFSET 0x112 #define MAD_IFC_GRH_OFFSET 0x140 inmailbox = mthca_alloc_mailbox(dev, GFP_KERNEL); @@ -1862,7 +1862,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, val = in_wc->dlid_path_bits | (in_wc->wc_flags & IB_WC_GRH ? 0x80 : 0); - MTHCA_PUT(inbox, val, MAD_IFC_GRH_OFFSET); + MTHCA_PUT(inbox, val, MAD_IFC_G_PATH_OFFSET); MTHCA_PUT(inbox, in_wc->slid, MAD_IFC_RLID_OFFSET); MTHCA_PUT(inbox, in_wc->pkey_index, MAD_IFC_PKEY_OFFSET); @@ -1870,7 +1870,7 @@ int mthca_MAD_IFC(struct mthca_dev *dev, int ignore_mkey, int ignore_bkey, if (in_grh) memcpy(inbox + MAD_IFC_GRH_OFFSET, in_grh, 40); - op_modifier |= 0x10; + op_modifier |= 0x4; in_modifier |= in_wc->slid << 16; } -- cgit v1.2.3 From c21e6d65f70d64b359a37545592f39e28074864e Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 31 Oct 2006 13:41:59 +0000 Subject: [MIPS] Sort out missuse of __init for prom_getcmdline() Signed-off-by: Ralf Baechle --- arch/mips/au1000/common/prom.c | 2 +- arch/mips/au1000/common/setup.c | 2 +- drivers/net/au1000_eth.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c index b4b010a2fe36..6fce60af005d 100644 --- a/arch/mips/au1000/common/prom.c +++ b/arch/mips/au1000/common/prom.c @@ -47,7 +47,7 @@ extern int prom_argc; extern char **prom_argv, **prom_envp; -char * prom_getcmdline(void) +char * __init_or_module prom_getcmdline(void) { return &(arcs_cmdline[0]); } diff --git a/arch/mips/au1000/common/setup.c b/arch/mips/au1000/common/setup.c index 377ae0d8ff00..919172db560c 100644 --- a/arch/mips/au1000/common/setup.c +++ b/arch/mips/au1000/common/setup.c @@ -43,7 +43,7 @@ #include #include -extern char * __init prom_getcmdline(void); +extern char * prom_getcmdline(void); extern void __init board_setup(void); extern void au1000_restart(char *); extern void au1000_halt(void); diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 4873dc610d22..7db3c8af0894 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -102,7 +102,7 @@ static void enable_mac(struct net_device *, int); // externs extern int get_ethernet_addr(char *ethernet_addr); extern void str2eaddr(unsigned char *ea, unsigned char *str); -extern char * __init prom_getcmdline(void); +extern char * prom_getcmdline(void); /* * Theory of operation -- cgit v1.2.3 From 2d38caba5fd148976f54930782e8209fa45879a0 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Oct 2006 19:52:31 +0100 Subject: [PATCH] ep93xx_eth: fix RX/TXstatus ring full handling Ray Lehtiniemi reported that an incoming UDP packet flood can lock up the ep93xx ethernet driver. Herbert Valerio Riedel noted that due to the way ep93xx_eth manages the RX/TXstatus rings, it cannot distinguish a full ring from an empty one, and correctly suggested that this was likely to be causing this lockup to occur. Instead of looking at the hardware's RX/TXstatus ring write pointers to determine when to stop reading from those rings, we should just check every individual RX/TXstatus descriptor's valid bit instead, since there is no other way to distinguish an empty ring from a full ring, and if there is a descriptor waiting, we take the hit of reading the descriptor from memory anyway. Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/arm/ep93xx_eth.c | 35 +++++++++-------------------------- 1 file changed, 9 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 127561c782fd..2fc8b2a1a023 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -193,12 +193,9 @@ static struct net_device_stats *ep93xx_get_stats(struct net_device *dev) static int ep93xx_rx(struct net_device *dev, int *budget) { struct ep93xx_priv *ep = netdev_priv(dev); - int tail_offset; int rx_done; int processed; - tail_offset = rdl(ep, REG_RXSTSQCURADD) - ep->descs_dma_addr; - rx_done = 0; processed = 0; while (*budget > 0) { @@ -211,28 +208,23 @@ static int ep93xx_rx(struct net_device *dev, int *budget) entry = ep->rx_pointer; rstat = ep->descs->rstat + entry; - if ((void *)rstat - (void *)ep->descs == tail_offset) { + + rstat0 = rstat->rstat0; + rstat1 = rstat->rstat1; + if (!(rstat0 & RSTAT0_RFP) || !(rstat1 & RSTAT1_RFP)) { rx_done = 1; break; } - rstat0 = rstat->rstat0; - rstat1 = rstat->rstat1; rstat->rstat0 = 0; rstat->rstat1 = 0; - if (!(rstat0 & RSTAT0_RFP)) - printk(KERN_CRIT "ep93xx_rx: buffer not done " - " %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_EOF)) printk(KERN_CRIT "ep93xx_rx: not end-of-frame " " %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_EOB)) printk(KERN_CRIT "ep93xx_rx: not end-of-buffer " " %.8x %.8x\n", rstat0, rstat1); - if (!(rstat1 & RSTAT1_RFP)) - printk(KERN_CRIT "ep93xx_rx: buffer1 not done " - " %.8x %.8x\n", rstat0, rstat1); if ((rstat1 & RSTAT1_BUFFER_INDEX) >> 16 != entry) printk(KERN_CRIT "ep93xx_rx: entry mismatch " " %.8x %.8x\n", rstat0, rstat1); @@ -301,13 +293,8 @@ err: static int ep93xx_have_more_rx(struct ep93xx_priv *ep) { - struct ep93xx_rstat *rstat; - int tail_offset; - - rstat = ep->descs->rstat + ep->rx_pointer; - tail_offset = rdl(ep, REG_RXSTSQCURADD) - ep->descs_dma_addr; - - return !((void *)rstat - (void *)ep->descs == tail_offset); + struct ep93xx_rstat *rstat = ep->descs->rstat + ep->rx_pointer; + return !!((rstat->rstat0 & RSTAT0_RFP) && (rstat->rstat1 & RSTAT1_RFP)); } static int ep93xx_poll(struct net_device *dev, int *budget) @@ -379,10 +366,8 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) static void ep93xx_tx_complete(struct net_device *dev) { struct ep93xx_priv *ep = netdev_priv(dev); - int tail_offset; int wake; - tail_offset = rdl(ep, REG_TXSTSQCURADD) - ep->descs_dma_addr; wake = 0; spin_lock(&ep->tx_pending_lock); @@ -393,15 +378,13 @@ static void ep93xx_tx_complete(struct net_device *dev) entry = ep->tx_clean_pointer; tstat = ep->descs->tstat + entry; - if ((void *)tstat - (void *)ep->descs == tail_offset) - break; tstat0 = tstat->tstat0; + if (!(tstat0 & TSTAT0_TXFP)) + break; + tstat->tstat0 = 0; - if (!(tstat0 & TSTAT0_TXFP)) - printk(KERN_CRIT "ep93xx_tx_complete: buffer not done " - " %.8x\n", tstat0); if (tstat0 & TSTAT0_FA) printk(KERN_CRIT "ep93xx_tx_complete: frame aborted " " %.8x\n", tstat0); -- cgit v1.2.3 From 79c356f44b26da9fe357ed1a11e7faec4fd94e13 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Oct 2006 19:52:54 +0100 Subject: [PATCH] ep93xx_eth: fix unlikely(x) > y test Fix unlikely(x) > y test in ep93xx_eth. Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/arm/ep93xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 2fc8b2a1a023..90d77ec48fb6 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -334,7 +334,7 @@ static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev) struct ep93xx_priv *ep = netdev_priv(dev); int entry; - if (unlikely(skb->len) > MAX_PKT_SIZE) { + if (unlikely(skb->len > MAX_PKT_SIZE)) { ep->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; -- cgit v1.2.3 From 06f0015ace46ce9d313ec02d6b13c47c8e795a6c Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 30 Oct 2006 19:54:08 +0100 Subject: [PATCH] ep93xx_eth: don't report RX errors Flooding the console with error messages for every RX FIFO overrun, checksum error and framing error isn't very sensible. Each of these errors can occur during normal operation, so stop printk'ing error messages for RX errors at all. Signed-off-by: Lennert Buytenhek Signed-off-by: Jeff Garzik --- drivers/net/arm/ep93xx_eth.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 90d77ec48fb6..8ebd68e2af98 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c @@ -230,9 +230,6 @@ static int ep93xx_rx(struct net_device *dev, int *budget) " %.8x %.8x\n", rstat0, rstat1); if (!(rstat0 & RSTAT0_RWE)) { - printk(KERN_NOTICE "ep93xx_rx: receive error " - " %.8x %.8x\n", rstat0, rstat1); - ep->stats.rx_errors++; if (rstat0 & RSTAT0_OE) ep->stats.rx_fifo_errors++; -- cgit v1.2.3 From 9d4df9e0fadfc84cd826e0f7e946691b4d7baee5 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 29 Oct 2006 03:52:14 +0900 Subject: [PATCH] tokenring: fix module_init error handling - Call platform_driver_unregister() before return when no cards found. (fixes data corruption when no cards found) - Check platform_device_register_simple() return value Cc: Jeff Garzik Cc: Mike Phillips Signed-off-by: Akinobu Mita drivers/net/tokenring/proteon.c | 9 +++++++-- drivers/net/tokenring/skisa.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) Signed-off-by: Jeff Garzik --- drivers/net/tokenring/proteon.c | 9 +++++++-- drivers/net/tokenring/skisa.c | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c index 4f756960db2a..cb7dbb63c9d9 100644 --- a/drivers/net/tokenring/proteon.c +++ b/drivers/net/tokenring/proteon.c @@ -370,6 +370,10 @@ static int __init proteon_init(void) dev->dma = dma[i]; pdev = platform_device_register_simple("proteon", i, NULL, 0); + if (IS_ERR(pdev)) { + free_netdev(dev); + continue; + } err = setup_card(dev, &pdev->dev); if (!err) { proteon_dev[i] = pdev; @@ -385,9 +389,10 @@ static int __init proteon_init(void) /* Probe for cards. */ if (num == 0) { printk(KERN_NOTICE "proteon.c: No cards found.\n"); - return (-ENODEV); + platform_driver_unregister(&proteon_driver); + return -ENODEV; } - return (0); + return 0; } static void __exit proteon_cleanup(void) diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c index d6ba41cf3110..33afea31d87b 100644 --- a/drivers/net/tokenring/skisa.c +++ b/drivers/net/tokenring/skisa.c @@ -380,6 +380,10 @@ static int __init sk_isa_init(void) dev->dma = dma[i]; pdev = platform_device_register_simple("skisa", i, NULL, 0); + if (IS_ERR(pdev)) { + free_netdev(dev); + continue; + } err = setup_card(dev, &pdev->dev); if (!err) { sk_isa_dev[i] = pdev; @@ -395,9 +399,10 @@ static int __init sk_isa_init(void) /* Probe for cards. */ if (num == 0) { printk(KERN_NOTICE "skisa.c: No cards found.\n"); - return (-ENODEV); + platform_driver_unregister(&sk_isa_driver); + return -ENODEV; } - return (0); + return 0; } static void __exit sk_isa_cleanup(void) -- cgit v1.2.3 From 09669585b5d0cfdebe28250d442693b3baac66a2 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sun, 29 Oct 2006 03:47:12 +0900 Subject: [PATCH] n2: fix confusing error code modprobe n2 with no parameters or no such devices will get confusing error message. # modprobe n2 ... Kernel does not have module support This patch replaces return code from -ENOSYS to -EINVAL. Cc: Jeff Garzik Cc: Krzysztof Halasa Signed-off-by: Akinobu Mita drivers/net/wan/n2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) Signed-off-by: Jeff Garzik --- drivers/net/wan/n2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c index dcf46add3adf..5c322dfb79f6 100644 --- a/drivers/net/wan/n2.c +++ b/drivers/net/wan/n2.c @@ -500,7 +500,7 @@ static int __init n2_init(void) #ifdef MODULE printk(KERN_INFO "n2: no card initialized\n"); #endif - return -ENOSYS; /* no parameters specified, abort */ + return -EINVAL; /* no parameters specified, abort */ } printk(KERN_INFO "%s\n", version); @@ -538,11 +538,11 @@ static int __init n2_init(void) n2_run(io, irq, ram, valid[0], valid[1]); if (*hw == '\x0') - return first_card ? 0 : -ENOSYS; + return first_card ? 0 : -EINVAL; }while(*hw++ == ':'); printk(KERN_ERR "n2: invalid hardware parameters\n"); - return first_card ? 0 : -ENOSYS; + return first_card ? 0 : -EINVAL; } -- cgit v1.2.3 From f479b322a0949d540b45aea645793058b0c50be5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 27 Oct 2006 10:22:10 -0700 Subject: [PATCH] sky2: not experimental The sky2 driver is no longer in experimental state. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e38846eb51fa..28c17d1ca5cb 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2112,7 +2112,7 @@ config SKGE config SKY2 tristate "SysKonnect Yukon2 support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + depends on PCI select CRC32 ---help--- This driver supports Gigabit Ethernet adapters based on the @@ -2120,8 +2120,8 @@ config SKY2 Marvell 88E8021/88E8022/88E8035/88E8036/88E8038/88E8050/88E8052/ 88E8053/88E8055/88E8061/88E8062, SysKonnect SK-9E21D/SK-9S21 - This driver does not support the original Yukon chipset: a seperate - driver, skge, is provided for Yukon-based adapters. + There is companion driver for the older Marvell Yukon and + Genesis based adapters: skge. To compile this driver as a module, choose M here: the module will be called sky2. This is recommended. -- cgit v1.2.3 From 1e7bed081968c42469bd02842b4190a115008221 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 26 Oct 2006 22:51:33 +0200 Subject: [PATCH] myri10ge: ServerWorks HT2000 PCI id is already defined in pci_ids.h No need to keep defining PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE in the driver code since it is now defined in pci_ids.h. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index fdbb0d7213b0..806081b59733 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2416,7 +2416,6 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) * firmware image, and set tx.boundary to 4KB. */ -#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 #define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 #define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa -- cgit v1.2.3 From 1e1675ccf758cbb4303ab052d58405cda6c745a7 Mon Sep 17 00:00:00 2001 From: Jan-Bernd Themann Date: Wed, 25 Oct 2006 13:11:42 +0200 Subject: [PATCH] ehea: kzalloc GFP_ATOMIC fix This patch fixes kzalloc parameters (GFP_ATOMIC instead of GFP_KERNEL) Signed-off-by: Jan-Bernd Themann Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index eb7d44de59ff..4538c99733fd 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -586,8 +586,8 @@ int ehea_sense_port_attr(struct ehea_port *port) u64 hret; struct hcp_ehea_port_cb0 *cb0; - cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (!cb0) { + cb0 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); /* May be called via */ + if (!cb0) { /* ehea_neq_tasklet() */ ehea_error("no mem for cb0"); ret = -ENOMEM; goto out; @@ -765,8 +765,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe) if (EHEA_BMASK_GET(NEQE_PORT_UP, eqe)) { if (!netif_carrier_ok(port->netdev)) { - ret = ehea_sense_port_attr( - port); + ret = ehea_sense_port_attr(port); if (ret) { ehea_error("failed resensing port " "attributes"); @@ -1502,7 +1501,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable) if ((enable && port->promisc) || (!enable && !port->promisc)) return; - cb7 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb7 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); if (!cb7) { ehea_error("no mem for cb7"); goto out; @@ -1606,7 +1605,7 @@ static void ehea_add_multicast_entry(struct ehea_port* port, u8* mc_mac_addr) struct ehea_mc_list *ehea_mcl_entry; u64 hret; - ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_KERNEL); + ehea_mcl_entry = kzalloc(sizeof(*ehea_mcl_entry), GFP_ATOMIC); if (!ehea_mcl_entry) { ehea_error("no mem for mcl_entry"); return; -- cgit v1.2.3 From 2ceaac755423cb93c1bb2f59ebd1a06f027ac095 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 30 Oct 2006 14:19:25 -0800 Subject: [PATCH] net s2io: return on NULL dev_alloc_skb() Checks for NULL dev_alloc_skb() and returns on true to avoid subsequent dereference. Cc: Jeff Garzik Cc: Christoph Hellwig Signed-off-by: David Rientjes Signed-off-by: Jeff Garzik --- drivers/net/s2io.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index a231ab7d28dd..33569ec9dbfc 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -5985,6 +5985,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, ((RxD3_t*)rxdp)->Buffer1_ptr = *temp1; } else { *skb = dev_alloc_skb(size); + if (!(*skb)) { + DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n", + dev->name); + return -ENOMEM; + } ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2 = pci_map_single(sp->pdev, (*skb)->data, dev->mtu + 4, @@ -6007,7 +6012,11 @@ static int set_rxd_buffer_pointer(nic_t *sp, RxD_t *rxdp, buffAdd_t *ba, ((RxD3_t*)rxdp)->Buffer2_ptr = *temp2; } else { *skb = dev_alloc_skb(size); - + if (!(*skb)) { + DBG_PRINT(ERR_DBG, "%s: dev_alloc_skb failed\n", + dev->name); + return -ENOMEM; + } ((RxD3_t*)rxdp)->Buffer0_ptr = *temp0 = pci_map_single(sp->pdev, ba->ba_0, BUF0_LEN, PCI_DMA_FROMDEVICE); -- cgit v1.2.3 From 798b6b19d7a4b6e1ea5340ec8b3b92811e05b81b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 22 Oct 2006 20:16:57 -0700 Subject: [PATCH] skge, sky2, et all. gplv2 only I don't want my code to downgraded to GPLv3 because of cut-n-pasted the comments. These files which I hold copyright on were started before it was clear what GPLv3 was going to be. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/irda/stir4200.c | 3 +-- drivers/net/skge.c | 3 +-- drivers/net/sky2.c | 3 +-- net/sched/sch_netem.c | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c index be8a66e702b0..3b4c47875935 100644 --- a/drivers/net/irda/stir4200.c +++ b/drivers/net/irda/stir4200.c @@ -15,8 +15,7 @@ * * 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. +* the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/drivers/net/skge.c b/drivers/net/skge.c index e7e414928f89..b2949035f66a 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -11,8 +11,7 @@ * * 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. + * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 95efdb5bbbe1..53171f62b267 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -10,8 +10,7 @@ * * 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. + * the Free Software Foundation; either version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ef8874babf6a..0441876aa1e7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -4,7 +4,7 @@ * 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. + * 2 of the License. * * Many of the algorithms and ideas for this came from * NIST Net which is not copyrighted. -- cgit v1.2.3 From 0ca43235b34c92278fa903297acef37198ec3e26 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 18 Oct 2006 13:39:28 -0700 Subject: [PATCH] sky2: netpoll on dual port cards The sky2 driver uses a single NAPI poll routine for both ports on dual ported cards (because there is a single IRQ and status ring). Netpoll makes assumptions about the relationship between network device and NAPI that aren't correct on the second port, this will cause the port to never clear work. Most systems, just have single port, so not a big issue. The easy fix is just make the second port, not netpoll capable. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 53171f62b267..16616f5440d0 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3238,7 +3238,11 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, dev->poll = sky2_poll; dev->weight = NAPI_WEIGHT; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = sky2_netpoll; + /* Network console (only works on port 0) + * because netpoll makes assumptions about NAPI + */ + if (port == 0) + dev->poll_controller = sky2_netpoll; #endif sky2 = netdev_priv(dev); -- cgit v1.2.3 From cf0e812f0e90ee496af072b136e8bd02770387e6 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 27 Oct 2006 19:08:47 -0700 Subject: [PATCH] sata_sis: fix flags handling for the secondary port sis_init_one() modifies probe_ent->port_flags after allocating and initializing it using ata_pci_init_native_mode(). This makes port_flags for the secondary port (probe_ent->pinfo2->flags) go out of sync resulting in misdetection of device due to incorrectly initialized SCR access flag. This patch make probe_ent alloc/init happen after the final port flags value is determined. This is fragile but probe_ent and all the related mess are scheduled to go away soon for exactly this reason. We just need to hold everything together till then. This has been spotted and diagnosed and tested by Patrick McHardy. Signed-off-by: Tejun Heo Cc: Patric McHardy Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/sata_sis.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 0738f52463a9..9d1235ba06b1 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -240,7 +240,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) struct ata_probe_ent *probe_ent = NULL; int rc; u32 genctl; - struct ata_port_info *ppi[2]; + struct ata_port_info pi = sis_port_info, *ppi[2] = { &pi, &pi }; int pci_dev_busy = 0; u8 pmr; u8 port2_start; @@ -265,27 +265,20 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) if (rc) goto err_out_regions; - ppi[0] = ppi[1] = &sis_port_info; - probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); - if (!probe_ent) { - rc = -ENOMEM; - goto err_out_regions; - } - /* check and see if the SCRs are in IO space or PCI cfg space */ pci_read_config_dword(pdev, SIS_GENCTL, &genctl); if ((genctl & GENCTL_IOMAPPED_SCR) == 0) - probe_ent->port_flags |= SIS_FLAG_CFGSCR; + pi.flags |= SIS_FLAG_CFGSCR; /* if hardware thinks SCRs are in IO space, but there are * no IO resources assigned, change to PCI cfg space. */ - if ((!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) && + if ((!(pi.flags & SIS_FLAG_CFGSCR)) && ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) || (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) { genctl &= ~GENCTL_IOMAPPED_SCR; pci_write_config_dword(pdev, SIS_GENCTL, genctl); - probe_ent->port_flags |= SIS_FLAG_CFGSCR; + pi.flags |= SIS_FLAG_CFGSCR; } pci_read_config_byte(pdev, SIS_PMR, &pmr); @@ -306,6 +299,12 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) port2_start = 0x20; } + probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY); + if (!probe_ent) { + rc = -ENOMEM; + goto err_out_regions; + } + if (!(probe_ent->port_flags & SIS_FLAG_CFGSCR)) { probe_ent->port[0].scr_addr = pci_resource_start(pdev, SIS_SCR_PCI_BAR); -- cgit v1.2.3 From f833229c96c0bf53c05995e4bd58709d9e9edd67 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 31 Oct 2006 09:31:37 +0100 Subject: [PATCH] Add 0x7110 piix to ata_piix.c Hi Jeff, I tested the PATA support on my old VAIO notebook, and it failed to find my piix device: 00:07.1 Class 0101: 8086:7111 (rev 01) (prog-if 80 [Master]) Control: I/O+ Mem- BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- Status: Cap- 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- SERR- Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 5250187ffce2..4fad8d2382ca 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -169,6 +169,7 @@ static const struct pci_device_id piix_pci_tbl[] = { #ifdef ATA_ENABLE_PATA /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ + { 0x8086, 0x7110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, -- cgit v1.2.3 From 6e42acc4115bc376b8523acbcba2b2b7cc27d016 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 27 Oct 2006 19:08:42 -0700 Subject: [PATCH] libata: unexport ata_dev_revalidate() ata_dev_revalidate() isn't used outside of libata core. Unexport it. Signed-off-by: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 - drivers/ata/libata.h | 1 + include/linux/libata.h | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 83728a9457ad..a8fd0c3e59b3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6122,7 +6122,6 @@ EXPORT_SYMBOL_GPL(ata_std_prereset); EXPORT_SYMBOL_GPL(ata_std_softreset); EXPORT_SYMBOL_GPL(sata_std_hardreset); EXPORT_SYMBOL_GPL(ata_std_postreset); -EXPORT_SYMBOL_GPL(ata_dev_revalidate); EXPORT_SYMBOL_GPL(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); EXPORT_SYMBOL_GPL(ata_port_disable); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index a5ecb71390a9..0ed263be652a 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -53,6 +53,7 @@ extern unsigned ata_exec_internal(struct ata_device *dev, extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd); extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, int post_reset, u16 *id); +extern int ata_dev_revalidate(struct ata_device *dev, int post_reset); extern int ata_dev_configure(struct ata_device *dev, int print_info); extern int sata_down_spd_limit(struct ata_port *ap); extern int sata_set_spd_needed(struct ata_port *ap); diff --git a/include/linux/libata.h b/include/linux/libata.h index b03d5a340dc8..abd2debebca2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -702,7 +702,6 @@ extern int ata_std_prereset(struct ata_port *ap); extern int ata_std_softreset(struct ata_port *ap, unsigned int *classes); extern int sata_std_hardreset(struct ata_port *ap, unsigned int *class); extern void ata_std_postreset(struct ata_port *ap, unsigned int *classes); -extern int ata_dev_revalidate(struct ata_device *dev, int post_reset); extern void ata_port_disable(struct ata_port *); extern void ata_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI -- cgit v1.2.3 From c6446a4cdadaf411bafe1565e9fa7666f3c2fe95 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 9 Oct 2006 13:23:58 +0900 Subject: [PATCH] ata_piix: allow 01b MAP for both ICH6M and ICH7M ICH7M was separated from ICH6M to allow undocumented MAP value 01b which was spotted on an ASUS notebook. However, there is also notebooks with MAP value 01b on ICH6M. This patch re-merges ICH6M and ICH7M entries and allows MAP value 01b for both. This problem has been reported and initial patch provided by Jonathan Dieter. Signed-off-by: Tejun Heo Cc: Jonathan Dieter Cc: Tom Deblauwe Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 4fad8d2382ca..8385387c49cd 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -126,8 +126,7 @@ enum { ich6_sata = 7, ich6_sata_ahci = 8, ich6m_sata_ahci = 9, - ich7m_sata_ahci = 10, - ich8_sata_ahci = 11, + ich8_sata_ahci = 10, /* constants for mapping table */ P0 = 0, /* port 0 */ @@ -228,7 +227,7 @@ static const struct pci_device_id piix_pci_tbl[] = { /* 82801GB/GR/GH (ICH7, identical to ICH6) */ { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ - { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich7m_sata_ahci }, + { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, /* Enterprise Southbridge 2 (where's the datasheet?) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ @@ -400,23 +399,10 @@ static const struct piix_map_db ich6m_map_db = { .mask = 0x3, .port_enable = 0x5, .present_shift = 4, - .map = { - /* PM PS SM SS MAP */ - { P0, P2, RV, RV }, /* 00b */ - { RV, RV, RV, RV }, - { P0, P2, IDE, IDE }, /* 10b */ - { RV, RV, RV, RV }, - }, -}; - -static const struct piix_map_db ich7m_map_db = { - .mask = 0x3, - .port_enable = 0x5, - .present_shift = 4, /* Map 01b isn't specified in the doc but some notebooks use - * it anyway. ATM, the only case spotted carries subsystem ID - * 1025:0107. This is the only difference from ich6m. + * it anyway. MAP 01b have been spotted on both ICH6M and + * ICH7M. */ .map = { /* PM PS SM SS MAP */ @@ -446,7 +432,6 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich6_sata] = &ich6_map_db, [ich6_sata_ahci] = &ich6_map_db, [ich6m_sata_ahci] = &ich6m_map_db, - [ich7m_sata_ahci] = &ich7m_map_db, [ich8_sata_ahci] = &ich8_map_db, }; @@ -557,19 +542,7 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, - /* ich7m_sata_ahci: 10 */ - { - .sht = &piix_sht, - .flags = ATA_FLAG_SATA | - PIIX_FLAG_CHECKINTR | PIIX_FLAG_SCR | - PIIX_FLAG_AHCI, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = 0x7f, /* udma0-6 */ - .port_ops = &piix_sata_ops, - }, - - /* ich8_sata_ahci: 11 */ + /* ich8_sata_ahci: 10 */ { .sht = &piix_sht, .flags = ATA_FLAG_SATA | -- cgit v1.2.3 From 115e222d538e7838bffa0f76409acd9816a0ef32 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 24 Oct 2006 22:41:27 -0400 Subject: [PATCH] hostap_plx: fix CIS verification The length of the manfid CIS should be at least 4, and it's normally 4. It's incorrect to require it to be at least 5. This breaks support for most (if not all) cards. The right place to ensure that we don't access beyond the CIS buffer is to strengthen another check. Make sure that the next tuple begins at least at the CIS buffer end (in which case we stop processing) or before that. Reported by ph35sm@free.fr Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_plx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 6dfa041be66d..bc81b13a5a2a 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -364,7 +364,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, pos = 0; while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) { - if (pos + cis[pos + 1] >= CIS_MAX_LEN) + if (pos + 2 + cis[pos + 1] > CIS_MAX_LEN) goto cis_error; switch (cis[pos]) { @@ -391,7 +391,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, break; case CISTPL_MANFID: - if (cis[pos + 1] < 5) + if (cis[pos + 1] < 4) goto cis_error; manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); -- cgit v1.2.3 From 81e171b95d2d06a64465a1e6ab1e2fb864ea2448 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 28 Oct 2006 17:52:34 -0500 Subject: [PATCH] bcm43xx: Fix low-traffic netdev watchdog TX timeouts This fixes a netdev watchdog timeout problem. The software needs to call netif_tx_disable before running the hardware calibration code. The problem condition can be shown by the following timegraph. |---5secs - ~10 jiffies time---|---|OOPS ^ ^ last real TX periodic work stops netif At OOPS, the following happens: The watchdog timer triggers, because the timeout of 5secs is over. The watchdog first checks for stopped TX. _Usually_ TX is only stopped from the TX handler to indicate a full TX queue. But this is different. We need to stop TX here, regardless of the TX queue state. So the watchdog recognizes the stopped device and assumes it is stopped due to full TX queues (Which is a _wrong_ assumption in this case). It then tests how far the last TX has been in the past. If it's more than 5secs (which is the case for low or no traffic), it will fire a TX timeout. Signed-off-by: Michael Buesch Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a94c6d8826f8..65edb56107fd 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3163,9 +3163,11 @@ static int estimate_periodic_work_badness(unsigned int state) static void bcm43xx_periodic_work_handler(void *d) { struct bcm43xx_private *bcm = d; + struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; int badness; + unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); badness = estimate_periodic_work_badness(bcm->periodic_state); @@ -3173,7 +3175,18 @@ static void bcm43xx_periodic_work_handler(void *d) /* Periodic work will take a long time, so we want it to * be preemtible. */ - netif_tx_disable(bcm->net_dev); + + netif_tx_lock_bh(net_dev); + /* We must fake a started transmission here, as we are going to + * disable TX. If we wouldn't fake a TX, it would be possible to + * trigger the netdev watchdog, if the last real TX is already + * some time on the past (slightly less than 5secs) + */ + orig_trans_start = net_dev->trans_start; + net_dev->trans_start = jiffies; + netif_stop_queue(net_dev); + netif_tx_unlock_bh(net_dev); + spin_lock_irqsave(&bcm->irq_lock, flags); bcm43xx_mac_suspend(bcm); if (bcm43xx_using_pio(bcm)) @@ -3198,6 +3211,7 @@ static void bcm43xx_periodic_work_handler(void *d) bcm43xx_pio_thaw_txqueues(bcm); bcm43xx_mac_enable(bcm); netif_wake_queue(bcm->net_dev); + net_dev->trans_start = orig_trans_start; } mmiowb(); spin_unlock_irqrestore(&bcm->irq_lock, flags); -- cgit v1.2.3 From df6d7c94b0c3ae6a1185c9e5fa8ee3368e4a5efb Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 17 Oct 2006 23:38:26 -0500 Subject: [PATCH] bcm43xx: fix unexpected LED control values in BCM4303 sprom The bcm43xx driver uses 4 locations in the devices sprom to determine the behavior of the leds. Certain defaults are assigned if all bits are set in those locations. On at least one BCM4303 chip, the sprom contains values other than the default, which executes an assertion placed in the default case of a following switch statement. This patch makes the leds on the above mentioned interface behave correctly. In addition, it limits the number of logged messages to 20 for the case of unexpected values in the sprom locations. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 7 ++++++- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c index 2ddbec6bf15b..7d383a27b927 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c @@ -189,20 +189,24 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) case BCM43xx_LED_INACTIVE: continue; case BCM43xx_LED_OFF: + case BCM43xx_LED_BCM4303_3: break; case BCM43xx_LED_ON: turn_on = 1; break; case BCM43xx_LED_ACTIVITY: + case BCM43xx_LED_BCM4303_0: turn_on = activity; break; case BCM43xx_LED_RADIO_ALL: turn_on = radio->enabled; break; case BCM43xx_LED_RADIO_A: + case BCM43xx_LED_BCM4303_2: turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); break; case BCM43xx_LED_RADIO_B: + case BCM43xx_LED_BCM4303_1: turn_on = (radio->enabled && (phy->type == BCM43xx_PHYTYPE_B || phy->type == BCM43xx_PHYTYPE_G)); @@ -257,7 +261,8 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) continue; #endif /* CONFIG_BCM43XX_DEBUG */ default: - assert(0); + dprintkl(KERN_INFO PFX "Bad value in leds_update," + " led->behaviour: 0x%x\n", led->behaviour); }; if (led->activelow) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h index d3716cf3aebc..811e14a81198 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h @@ -46,6 +46,12 @@ enum { /* LED behaviour values */ BCM43xx_LED_TEST_BLINKSLOW, BCM43xx_LED_TEST_BLINKMEDIUM, BCM43xx_LED_TEST_BLINKFAST, + + /* Misc values for BCM4303 */ + BCM43xx_LED_BCM4303_0 = 0x2B, + BCM43xx_LED_BCM4303_1 = 0x78, + BCM43xx_LED_BCM4303_2 = 0x2E, + BCM43xx_LED_BCM4303_3 = 0x19, }; int bcm43xx_leds_init(struct bcm43xx_private *bcm); -- cgit v1.2.3 From 441cbd8dace80545db2ac43175ac1c097d96f75c Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 26 Oct 2006 15:38:10 +1000 Subject: [POWERPC] Fix various offb issues This patch fixes a few issues in offb: - A test was inverted causing the palette hack to never work (no device node was passed down to the init function) - Some cards seem to have their assigned-addresses property in a random order, thus we need to try using of_get_pci_address() first, which will fail if it's not a PCI device, and fallback to of_get_address() in that case. of_get_pci_address() properly parsees assigned-addresses to test the BAR number and thus will get it right whatever the order is. - Some cards (like GXT4500) provide a linebytes of 0xffffffff in the device-tree which does no good. This patch handles that by using the screen width when that happens. (Also fixes btext.c while at it). - Add detection of the GXT4500 in addition to the GXT2000 for the palette hacks (we use the same hack, palette is linear in register space at offset 0x6000). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/btext.c | 2 +- drivers/video/offb.c | 36 +++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 995fcef156fd..93f21aaf7c8e 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -182,7 +182,7 @@ int btext_initialize(struct device_node *np) prop = get_property(np, "linux,bootx-linebytes", NULL); if (prop == NULL) prop = get_property(np, "linebytes", NULL); - if (prop) + if (prop && *prop != 0xffffffffu) pitch = *prop; if (pitch == 1) pitch = 0x1000; diff --git a/drivers/video/offb.c b/drivers/video/offb.c index bad0e98fb3b6..9a40bbecf76b 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -157,7 +157,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, out_le32(par->cmap_adr + 0xb4, (red << 16 | green << 8 | blue)); break; case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + regno, + out_le32(((unsigned __iomem *) par->cmap_adr) + regno, (red << 16 | green << 8 | blue)); break; } @@ -213,7 +213,7 @@ static int offb_blank(int blank, struct fb_info *info) out_le32(par->cmap_adr + 0xb4, 0); break; case cmap_gxt2000: - out_le32((unsigned __iomem *) par->cmap_adr + i, + out_le32(((unsigned __iomem *) par->cmap_adr) + i, 0); break; } @@ -226,13 +226,23 @@ static int offb_blank(int blank, struct fb_info *info) static void __iomem *offb_map_reg(struct device_node *np, int index, unsigned long offset, unsigned long size) { - struct resource r; - - if (of_address_to_resource(np, index, &r)) - return 0; - if ((r.start + offset + size) > r.end) - return 0; - return ioremap(r.start + offset, size); + const u32 *addrp; + u64 asize, taddr; + unsigned int flags; + + addrp = of_get_pci_address(np, index, &asize, &flags); + if (addrp == NULL) + addrp = of_get_address(np, index, &asize, &flags); + if (addrp == NULL) + return NULL; + if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0) + return NULL; + if ((offset + size) > asize) + return NULL; + taddr = of_translate_address(np, addrp); + if (taddr == OF_BAD_ADDR) + return NULL; + return ioremap(taddr + offset, size); } static void __init offb_init_fb(const char *name, const char *full_name, @@ -289,7 +299,6 @@ static void __init offb_init_fb(const char *name, const char *full_name, par->cmap_type = cmap_unknown; if (depth == 8) { - /* Palette hacks disabled for now */ if (dp && !strncmp(name, "ATY,Rage128", 11)) { par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff); if (par->cmap_adr) @@ -313,7 +322,8 @@ static void __init offb_init_fb(const char *name, const char *full_name, ioremap(base + 0x7ff000, 0x1000) + 0xcc0; par->cmap_data = par->cmap_adr + 1; par->cmap_type = cmap_m64; - } else if (dp && device_is_compatible(dp, "pci1014,b7")) { + } else if (dp && (device_is_compatible(dp, "pci1014,b7") || + device_is_compatible(dp, "pci1014,21c"))) { par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000); if (par->cmap_adr) par->cmap_type = cmap_gxt2000; @@ -433,7 +443,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) pp = get_property(dp, "linux,bootx-linebytes", &len); if (pp == NULL) pp = get_property(dp, "linebytes", &len); - if (pp && len == sizeof(u32)) + if (pp && len == sizeof(u32) && (*pp != 0xffffffffu)) pitch = *pp; else pitch = width * ((depth + 7) / 8); @@ -496,7 +506,7 @@ static void __init offb_init_nodriver(struct device_node *dp, int no_real_node) offb_init_fb(no_real_node ? "bootx" : dp->name, no_real_node ? "display" : dp->full_name, width, height, depth, pitch, address, - no_real_node ? dp : NULL); + no_real_node ? NULL : dp); } } -- cgit v1.2.3 From 1244a19cde42c268aa159d264fc2df072a3ff82f Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 1 Nov 2006 17:19:18 +0900 Subject: [PATCH] ahci: fix status register check in ahci_softreset ahci_softreset() used to use ahci_tf_read() which reads D2H_REG area to check for the Status register. However, this area is zeroed on initialization and not set by initial signature FIS. Replace it with ahci_check_status(). This bug prevented CLO code from being activated whenever BSY and/or DRQ is set prior to softreset. This fix makes AHCI_FLAG_RESET_NEEDS_CLO flag redundant. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cef2e70d64f8..988f8bbd14ff 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -736,8 +736,7 @@ static int ahci_softreset(struct ata_port *ap, unsigned int *class) } /* check BUSY/DRQ, perform Command List Override if necessary */ - ahci_tf_read(ap, &tf); - if (tf.command & (ATA_BUSY | ATA_DRQ)) { + if (ahci_check_status(ap) & (ATA_BUSY | ATA_DRQ)) { rc = ahci_clo(ap); if (rc == -EOPNOTSUPP) { -- cgit v1.2.3 From 8fc2d9cae99e47e236cb7b77015b9faf69a097cc Mon Sep 17 00:00:00 2001 From: Peer Chen Date: Wed, 1 Nov 2006 05:23:11 -0500 Subject: [libata] sata_nv: Add PCI IDs Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 323b60710806..d65ebfd7c7b2 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -117,10 +117,14 @@ static const struct pci_device_id nv_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC }, - { PCI_VDEVICE(NVIDIA, 0x045c), GENERIC }, - { PCI_VDEVICE(NVIDIA, 0x045d), GENERIC }, - { PCI_VDEVICE(NVIDIA, 0x045e), GENERIC }, - { PCI_VDEVICE(NVIDIA, 0x045f), GENERIC }, + { PCI_VDEVICE(NVIDIA, 0x045c), GENERIC }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045d), GENERIC }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045e), GENERIC }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x045f), GENERIC }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x0550), GENERIC }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0551), GENERIC }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0552), GENERIC }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0553), GENERIC }, /* MCP67 */ { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC }, -- cgit v1.2.3 From 732f74a46711c0724885703fb689c79139c84a3c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 1 Nov 2006 22:09:21 -0500 Subject: Revert "[PATCH] Add 0x7110 piix to ata_piix.c" This reverts commit f833229c96c0bf53c05995e4bd58709d9e9edd67: According to reviewers and the lspci data provided in commit message itself, PCI ID 0x7110 should not have been added to ata_piix. Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 8385387c49cd..720174d628fa 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -168,7 +168,6 @@ static const struct pci_device_id piix_pci_tbl[] = { #ifdef ATA_ENABLE_PATA /* Intel PIIX4 for the 430TX/440BX/MX chipset: UDMA 33 */ /* Also PIIX4E (fn3 rev 2) and PIIX4M (fn3 rev 3) */ - { 0x8086, 0x7110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, { 0x8086, 0x7111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, piix_pata_33 }, { 0x8086, 0x24db, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, { 0x8086, 0x25a2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, -- cgit v1.2.3 From 7a118df3ea23820b9922a1b51cd2f24e464f4c17 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 31 Oct 2006 11:12:59 -0800 Subject: RDMA/addr: Use client registration to fix module unload race Require registration with ib_addr module to prevent caller from unloading while a callback is in progress. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 28 +++++++++++++++++++++++++++- drivers/infiniband/core/cma.c | 8 ++++++-- include/rdma/ib_addr.h | 20 +++++++++++++++++++- 3 files changed, 52 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 60d3fbdd216c..e11187ecc931 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -47,6 +47,7 @@ struct addr_req { struct sockaddr src_addr; struct sockaddr dst_addr; struct rdma_dev_addr *addr; + struct rdma_addr_client *client; void *context; void (*callback)(int status, struct sockaddr *src_addr, struct rdma_dev_addr *addr, void *context); @@ -61,6 +62,26 @@ static LIST_HEAD(req_list); static DECLARE_WORK(work, process_req, NULL); static struct workqueue_struct *addr_wq; +void rdma_addr_register_client(struct rdma_addr_client *client) +{ + atomic_set(&client->refcount, 1); + init_completion(&client->comp); +} +EXPORT_SYMBOL(rdma_addr_register_client); + +static inline void put_client(struct rdma_addr_client *client) +{ + if (atomic_dec_and_test(&client->refcount)) + complete(&client->comp); +} + +void rdma_addr_unregister_client(struct rdma_addr_client *client) +{ + put_client(client); + wait_for_completion(&client->comp); +} +EXPORT_SYMBOL(rdma_addr_unregister_client); + int rdma_copy_addr(struct rdma_dev_addr *dev_addr, struct net_device *dev, const unsigned char *dst_dev_addr) { @@ -229,6 +250,7 @@ static void process_req(void *data) list_del(&req->list); req->callback(req->status, &req->src_addr, req->addr, req->context); + put_client(req->client); kfree(req); } } @@ -264,7 +286,8 @@ static int addr_resolve_local(struct sockaddr_in *src_in, return ret; } -int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, +int rdma_resolve_ip(struct rdma_addr_client *client, + struct sockaddr *src_addr, struct sockaddr *dst_addr, struct rdma_dev_addr *addr, int timeout_ms, void (*callback)(int status, struct sockaddr *src_addr, struct rdma_dev_addr *addr, void *context), @@ -285,6 +308,8 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, req->addr = addr; req->callback = callback; req->context = context; + req->client = client; + atomic_inc(&client->refcount); src_in = (struct sockaddr_in *) &req->src_addr; dst_in = (struct sockaddr_in *) &req->dst_addr; @@ -305,6 +330,7 @@ int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, break; default: ret = req->status; + atomic_dec(&client->refcount); kfree(req); break; } diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d8ca3c1368b5..845090b0859c 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -63,6 +63,7 @@ static struct ib_client cma_client = { }; static struct ib_sa_client sa_client; +static struct rdma_addr_client addr_client; static LIST_HEAD(dev_list); static LIST_HEAD(listen_any_list); static DEFINE_MUTEX(lock); @@ -1625,8 +1626,8 @@ int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr, if (cma_any_addr(dst_addr)) ret = cma_resolve_loopback(id_priv); else - ret = rdma_resolve_ip(&id->route.addr.src_addr, dst_addr, - &id->route.addr.dev_addr, + ret = rdma_resolve_ip(&addr_client, &id->route.addr.src_addr, + dst_addr, &id->route.addr.dev_addr, timeout_ms, addr_handler, id_priv); if (ret) goto err; @@ -2217,6 +2218,7 @@ static int cma_init(void) return -ENOMEM; ib_sa_register_client(&sa_client); + rdma_addr_register_client(&addr_client); ret = ib_register_client(&cma_client); if (ret) @@ -2224,6 +2226,7 @@ static int cma_init(void) return 0; err: + rdma_addr_unregister_client(&addr_client); ib_sa_unregister_client(&sa_client); destroy_workqueue(cma_wq); return ret; @@ -2232,6 +2235,7 @@ err: static void cma_cleanup(void) { ib_unregister_client(&cma_client); + rdma_addr_unregister_client(&addr_client); ib_sa_unregister_client(&sa_client); destroy_workqueue(cma_wq); idr_destroy(&sdp_ps); diff --git a/include/rdma/ib_addr.h b/include/rdma/ib_addr.h index 81b62307621d..c094e5012862 100644 --- a/include/rdma/ib_addr.h +++ b/include/rdma/ib_addr.h @@ -36,6 +36,22 @@ #include #include +struct rdma_addr_client { + atomic_t refcount; + struct completion comp; +}; + +/** + * rdma_addr_register_client - Register an address client. + */ +void rdma_addr_register_client(struct rdma_addr_client *client); + +/** + * rdma_addr_unregister_client - Deregister an address client. + * @client: Client object to deregister. + */ +void rdma_addr_unregister_client(struct rdma_addr_client *client); + struct rdma_dev_addr { unsigned char src_dev_addr[MAX_ADDR_LEN]; unsigned char dst_dev_addr[MAX_ADDR_LEN]; @@ -52,6 +68,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr); /** * rdma_resolve_ip - Resolve source and destination IP addresses to * RDMA hardware addresses. + * @client: Address client associated with request. * @src_addr: An optional source address to use in the resolution. If a * source address is not provided, a usable address will be returned via * the callback. @@ -64,7 +81,8 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr); * or been canceled. A status of 0 indicates success. * @context: User-specified context associated with the call. */ -int rdma_resolve_ip(struct sockaddr *src_addr, struct sockaddr *dst_addr, +int rdma_resolve_ip(struct rdma_addr_client *client, + struct sockaddr *src_addr, struct sockaddr *dst_addr, struct rdma_dev_addr *addr, int timeout_ms, void (*callback)(int status, struct sockaddr *src_addr, struct rdma_dev_addr *addr, void *context), -- cgit v1.2.3 From 05e2867a7bcc76de37e103a97ed48ba6872db797 Mon Sep 17 00:00:00 2001 From: Peer Chen Date: Thu, 2 Nov 2006 17:58:21 -0500 Subject: [libata] Add support for PATA controllers of MCP67 to pata_amd.c. Signed-off-by: Peer Chen Signed-off-by: Jeff Garzik --- drivers/ata/pata_amd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 29234c897118..5c47a9e0e0ca 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -677,6 +677,8 @@ static const struct pci_device_id amd[] = { { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE), 8 }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE), 8 }, { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE), 8 }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE), 8 }, + { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE), 8 }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CS5536_IDE), 9 }, { }, -- cgit v1.2.3 From 895663cd92574367054e0eb604a7428852f359b8 Mon Sep 17 00:00:00 2001 From: Peer Chen Date: Thu, 2 Nov 2006 17:59:46 -0500 Subject: [libata] Add support for AHCI controllers of MCP67. Signed-off-by: Peer Chen Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 988f8bbd14ff..234197e57e9e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -334,6 +334,14 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x044d), board_ahci }, /* MCP65 */ { PCI_VDEVICE(NVIDIA, 0x044e), board_ahci }, /* MCP65 */ { PCI_VDEVICE(NVIDIA, 0x044f), board_ahci }, /* MCP65 */ + { PCI_VDEVICE(NVIDIA, 0x0554), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0555), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0556), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0557), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0558), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */ + { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */ /* SiS */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ -- cgit v1.2.3 From 6c8c21b9119cfe68a99825085014bba4f9c0c768 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 14 Oct 2006 16:21:02 -0300 Subject: V4L/DVB (4752): DVB: Add DVB_FE_CUSTOMISE support for MT2060 Let the MT2060 be customized like most of the other DVB PLLs/front-ends. Also, add a missing dependency on I2C. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/Kconfig | 12 ++++++------ drivers/media/dvb/frontends/Kconfig | 2 ++ drivers/media/dvb/frontends/mt2060.h | 8 ++++++++ 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 2cc5caa26a0a..a263b3f3c21d 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -26,7 +26,7 @@ config DVB_USB_A800 tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. @@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)" depends on DVB_USB select DVB_DIB3000MB - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-B demodulator. @@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB2.0 DVB-T receivers based on reference designs made by DiBcom () equipped with a DiB3000M-C/P demodulator. @@ -70,7 +70,7 @@ config DVB_USB_DIB0700 tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The USB bridge is also present in devices having the DiB7700 DVB-T-USB @@ -87,7 +87,7 @@ config DVB_USB_UMT_010 tristate "HanfTek UMT-010 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. @@ -153,7 +153,7 @@ config DVB_USB_NOVA_T_USB2 tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" depends on DVB_USB select DVB_DIB3000MC - select DVB_TUNER_MT2060 + select DVB_TUNER_MT2060 if !DVB_FE_CUSTOMISE help Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 080fa257a0bc..aebb8d6f26f8 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -276,6 +276,8 @@ config DVB_TDA826X config DVB_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. diff --git a/drivers/media/dvb/frontends/mt2060.h b/drivers/media/dvb/frontends/mt2060.h index 34a37c2b556f..0a86eab3a954 100644 --- a/drivers/media/dvb/frontends/mt2060.h +++ b/drivers/media/dvb/frontends/mt2060.h @@ -30,6 +30,14 @@ struct mt2060_config { u8 clock_out; /* 0 = off, 1 = CLK/4, 2 = CLK/2, 3 = CLK/1 */ }; +#if defined(CONFIG_DVB_TUNER_MT2060) || (defined(CONFIG_DVB_TUNER_MT2060_MODULE) && defined(MODULE)) extern struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1); +#else +static inline struct dvb_frontend * mt2060_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mt2060_config *cfg, u16 if1) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __FUNCTION__); + return NULL; +} +#endif // CONFIG_DVB_TUNER_MT2060 #endif -- cgit v1.2.3 From ecba77f246011344f0b8f46eb25ae01ab4ae282d Mon Sep 17 00:00:00 2001 From: David Härdeman Date: Fri, 27 Oct 2006 20:56:51 -0300 Subject: V4L/DVB (4785): Budget-ci: Change DEBIADDR_IR to a safer default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The IR chip has no address decoding, so the IR data is always present in the high byte when doing a read from the saa7146 chip. This means that the DEBI address used is irrelevant to the IR decoding logic. DEBI addresses 0x1XXX are mapped to the registers on the CI module itself, but only the lowest two bits are actually used (see EN50221, section A.2.2.1), meaning that 0x1234 is equivalent to 0x1000 which maps to register 0 (the data register). A read from the data register is supposed to be preceded by a read from the size register, so some CI modules will be confused (the AlphaCrypt CAM will hang completely). The attached patch changes the address used when reading the IR data to use 0x4000 instead. This is the CI version address, which is a safer default, works with the AlphaCrypt CAM and matches the behaviour of the Windows driver (AFAIK). Signed-off-by: David Härdeman Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 2a2e9b400613..ac0cecb14dc3 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -46,7 +46,14 @@ #include "bsbe1.h" #include "bsru6.h" -#define DEBIADDR_IR 0x1234 +/* + * Regarding DEBIADDR_IR: + * Some CI modules hang if random addresses are read. + * Using address 0x4000 for the IR read means that we + * use the same address as for CI version, which should + * be a safe default. + */ +#define DEBIADDR_IR 0x4000 #define DEBIADDR_CICONTROL 0x0000 #define DEBIADDR_CIVERSION 0x4000 #define DEBIADDR_IO 0x1000 -- cgit v1.2.3 From c2625bff997f195e067ae11c9b0aa7217fb32991 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 29 Oct 2006 11:12:27 -0300 Subject: V4L/DVB (4786): Pvrusb2: use NULL instead of 0 Fix sparse NULL usage warnings: drivers/media/video/pvrusb2/pvrusb2-v4l2.c:714:14: warning: Using plain integer as NULL pointer drivers/media/video/pvrusb2/pvrusb2-v4l2.c:715:16: warning: Using plain integer as NULL pointer drivers/media/video/pvrusb2/pvrusb2-v4l2.c:1079:10: warning: Using plain integer as NULL pointer drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c:224:58: warning: Using plain integer as NULL pointer Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c | 2 +- drivers/media/video/pvrusb2/pvrusb2-v4l2.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c index df8feac16aee..c80c26be6e4d 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c +++ b/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c @@ -221,7 +221,7 @@ static unsigned int decoder_describe(struct pvr2_v4l_cx2584x *ctxt, static void decoder_reset(struct pvr2_v4l_cx2584x *ctxt) { int ret; - ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,0); + ret = pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_RESET,NULL); pvr2_trace(PVR2_TRACE_CHIPS,"i2c cx25840 decoder_reset (ret=%d)",ret); } diff --git a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c index 97e974d9b9c3..bb40e9085977 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-v4l2.c +++ b/drivers/media/video/pvrusb2/pvrusb2-v4l2.c @@ -711,8 +711,8 @@ static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip) dip->devbase.minor,pvr2_config_get_name(dip->config)); /* Paranoia */ - dip->v4lp = 0; - dip->stream = 0; + dip->v4lp = NULL; + dip->stream = NULL; /* Actual deallocation happens later when all internal references are gone. */ @@ -1076,7 +1076,7 @@ struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp) vp->vdev = kmalloc(sizeof(*vp->vdev),GFP_KERNEL); if (!vp->vdev) { kfree(vp); - return 0; + return NULL; } memset(vp->vdev,0,sizeof(*vp->vdev)); pvr2_channel_init(&vp->channel,mnp); -- cgit v1.2.3 From 9e741b74afc975da51ec60c5a8147b2ebcf7e33a Mon Sep 17 00:00:00 2001 From: Raymond Mantchala Date: Mon, 30 Oct 2006 23:20:50 -0300 Subject: V4L/DVB (4787): Budget-ci: Inversion setting fixed for Technotrend 1500 T Technotrend 1500 T card have "inverted inversion". This patch fixes that. Many thanks to Martin Zwickel from Technotrend for his confirmation and correction proposal. Signed-off-by: Raymond Mantchala Signed-off-by: Perceval Anichini Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index ac0cecb14dc3..cd5ec489af1c 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -1035,6 +1035,7 @@ static void frontend_init(struct budget_ci *budget_ci) case 0x1012: // TT DVB-T CI budget (tda10046/Philips tdm1316l(tda6651tt)) budget_ci->tuner_pll_address = 0x60; + philips_tdm1316l_config.invert = 1; budget_ci->budget.dvb_frontend = dvb_attach(tda10046_attach, &philips_tdm1316l_config, &budget_ci->budget.i2c_adap); if (budget_ci->budget.dvb_frontend) { -- cgit v1.2.3 From 588f98312c7fd1d86290583189d2eb24da70f752 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Wed, 18 Oct 2006 17:30:42 -0300 Subject: V4L/DVB (4770): Fix mode switch of Compro Videomate T300 The board did not return to analog mode since the board specific "demod sleep" function was not called. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1ba53b525ad2..6b61d9b2fcb5 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1147,6 +1147,8 @@ static int dvb_init(struct saa7134_dev *dev) &philips_europa_config, &dev->i2c_adap); if (dev->dvb.frontend) { + dev->original_demod_sleep = dev->dvb.frontend->ops.sleep; + dev->dvb.frontend->ops.sleep = philips_europa_demod_sleep; dev->dvb.frontend->ops.tuner_ops.init = philips_europa_tuner_init; dev->dvb.frontend->ops.tuner_ops.sleep = philips_europa_tuner_sleep; dev->dvb.frontend->ops.tuner_ops.set_params = philips_td1316_tuner_set_params; -- cgit v1.2.3 From 9bb6e2593ad4cb94944f547154baee64b4734598 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Fri, 27 Oct 2006 18:02:01 -0300 Subject: V4L/DVB (4784): [saa7146_i2c] short_delay mode fixed for fast machines TT DVB-C 2300 runs at 137 kHz I2C speed. short_delay mode did not work reliably on fast machines with that speed. Increased max loop count from 20 to 50. Moved dummy access out of the loop. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/saa7146_i2c.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c index d9953f7a8b6b..5297a365c928 100644 --- a/drivers/media/common/saa7146_i2c.c +++ b/drivers/media/common/saa7146_i2c.c @@ -217,11 +217,9 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d } /* wait until we get a transfer done or error */ timeout = jiffies + HZ/100 + 1; /* 10ms */ + /* first read usually delivers bogus results... */ + saa7146_i2c_status(dev); while(1) { - /** - * first read usually delivers bogus results... - */ - saa7146_i2c_status(dev); status = saa7146_i2c_status(dev); if ((status & 0x3) != 1) break; @@ -232,10 +230,10 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d DEB_I2C(("saa7146_i2c_writeout: timed out waiting for end of xfer\n")); return -EIO; } - if ((++trial < 20) && short_delay) + if (++trial < 50 && short_delay) udelay(10); else - msleep(1); + msleep(1); } } -- cgit v1.2.3 From c5dec9fb248e3318f30a26f9984b3b064053a77f Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 14 Oct 2006 15:44:44 -0300 Subject: V4L/DVB (4751): Fix DBV_FE_CUSTOMISE for card drivers compiled into kernel When a front-end is disabled, card drivers that use it are compiled with a stub version of the front-end's attach function. This way they have no references to the front-end's code and don't need it to be loaded. If a card driver is compiled into the kernel, and a front-end is a module, then that front-end is effectively disabled wrt the card driver. In this case, the card driver should get the stub version. This was not happening. The stub vs real attach function selection is changed so that when the front-end is a module the real attach function is only used if the card driver is a module as well. This means a module front-end will be supported by card drivers that are modules and not supported by card drivers compiled into the kernel. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/bcm3510.h | 2 +- drivers/media/dvb/frontends/cx22700.h | 2 +- drivers/media/dvb/frontends/cx22702.h | 2 +- drivers/media/dvb/frontends/cx24110.h | 2 +- drivers/media/dvb/frontends/cx24123.h | 2 +- drivers/media/dvb/frontends/dib3000.h | 2 +- drivers/media/dvb/frontends/dib3000mc.h | 2 +- drivers/media/dvb/frontends/isl6421.h | 2 +- drivers/media/dvb/frontends/l64781.h | 2 +- drivers/media/dvb/frontends/lgdt330x.h | 2 +- drivers/media/dvb/frontends/lnbp21.h | 2 +- drivers/media/dvb/frontends/mt312.h | 2 +- drivers/media/dvb/frontends/mt352.h | 2 +- drivers/media/dvb/frontends/nxt200x.h | 2 +- drivers/media/dvb/frontends/nxt6000.h | 2 +- drivers/media/dvb/frontends/or51132.h | 2 +- drivers/media/dvb/frontends/or51211.h | 2 +- drivers/media/dvb/frontends/s5h1420.h | 2 +- drivers/media/dvb/frontends/sp8870.h | 2 +- drivers/media/dvb/frontends/sp887x.h | 2 +- drivers/media/dvb/frontends/stv0297.h | 2 +- drivers/media/dvb/frontends/stv0299.h | 2 +- drivers/media/dvb/frontends/tda10021.h | 2 +- drivers/media/dvb/frontends/tda1004x.h | 2 +- drivers/media/dvb/frontends/tda10086.h | 2 +- drivers/media/dvb/frontends/tda8083.h | 2 +- drivers/media/dvb/frontends/tda826x.h | 2 +- drivers/media/dvb/frontends/tua6100.h | 2 +- drivers/media/dvb/frontends/ves1820.h | 2 +- drivers/media/dvb/frontends/ves1x93.h | 2 +- drivers/media/dvb/frontends/zl10353.h | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h index 6dfa839a7022..7e4f95e1734b 100644 --- a/drivers/media/dvb/frontends/bcm3510.h +++ b/drivers/media/dvb/frontends/bcm3510.h @@ -34,7 +34,7 @@ struct bcm3510_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_BCM3510) || defined(CONFIG_DVB_BCM3510_MODULE) +#if defined(CONFIG_DVB_BCM3510) || (defined(CONFIG_DVB_BCM3510_MODULE) && defined(MODULE)) extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/cx22700.h b/drivers/media/dvb/frontends/cx22700.h index 10286cc29fb4..7ac33690cdcc 100644 --- a/drivers/media/dvb/frontends/cx22700.h +++ b/drivers/media/dvb/frontends/cx22700.h @@ -31,7 +31,7 @@ struct cx22700_config u8 demod_address; }; -#if defined(CONFIG_DVB_CX22700) || defined(CONFIG_DVB_CX22700_MODULE) +#if defined(CONFIG_DVB_CX22700) || (defined(CONFIG_DVB_CX22700_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx22700_attach(const struct cx22700_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/cx22702.h b/drivers/media/dvb/frontends/cx22702.h index bc217ddf02c0..9cd64da6ee40 100644 --- a/drivers/media/dvb/frontends/cx22702.h +++ b/drivers/media/dvb/frontends/cx22702.h @@ -41,7 +41,7 @@ struct cx22702_config u8 output_mode; }; -#if defined(CONFIG_DVB_CX22702) || defined(CONFIG_DVB_CX22702_MODULE) +#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx22702_attach(const struct cx22702_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/cx24110.h b/drivers/media/dvb/frontends/cx24110.h index c9d5ae250ebb..0ca3af4db513 100644 --- a/drivers/media/dvb/frontends/cx24110.h +++ b/drivers/media/dvb/frontends/cx24110.h @@ -41,7 +41,7 @@ static inline int cx24110_pll_write(struct dvb_frontend *fe, u32 val) { return r; } -#if defined(CONFIG_DVB_CX24110) || defined(CONFIG_DVB_CX24110_MODULE) +#if defined(CONFIG_DVB_CX24110) || (defined(CONFIG_DVB_CX24110_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx24110_attach(const struct cx24110_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/cx24123.h b/drivers/media/dvb/frontends/cx24123.h index 57a1dae1dc40..84f9e4f5c15e 100644 --- a/drivers/media/dvb/frontends/cx24123.h +++ b/drivers/media/dvb/frontends/cx24123.h @@ -35,7 +35,7 @@ struct cx24123_config int lnb_polarity; }; -#if defined(CONFIG_DVB_CX24123) || defined(CONFIG_DVB_CX24123_MODULE) +#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) && defined(MODULE)) extern struct dvb_frontend* cx24123_attach(const struct cx24123_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h index 0caac3f0f279..a6d3854a67bc 100644 --- a/drivers/media/dvb/frontends/dib3000.h +++ b/drivers/media/dvb/frontends/dib3000.h @@ -41,7 +41,7 @@ struct dib_fe_xfer_ops int (*tuner_pass_ctrl)(struct dvb_frontend *fe, int onoff, u8 pll_ctrl); }; -#if defined(CONFIG_DVB_DIB3000MB) || defined(CONFIG_DVB_DIB3000MB_MODULE) +#if defined(CONFIG_DVB_DIB3000MB) || (defined(CONFIG_DVB_DIB3000MB_MODULE) && defined(MODULE)) extern struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config, struct i2c_adapter* i2c, struct dib_fe_xfer_ops *xfer_ops); #else diff --git a/drivers/media/dvb/frontends/dib3000mc.h b/drivers/media/dvb/frontends/dib3000mc.h index 0d6fdef77538..72d4757601d8 100644 --- a/drivers/media/dvb/frontends/dib3000mc.h +++ b/drivers/media/dvb/frontends/dib3000mc.h @@ -39,7 +39,7 @@ struct dib3000mc_config { #define DEFAULT_DIB3000MC_I2C_ADDRESS 16 #define DEFAULT_DIB3000P_I2C_ADDRESS 24 -#if defined(CONFIG_DVB_DIB3000MC) || defined(CONFIG_DVB_DIB3000MC_MODULE) +#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && defined(MODULE)) extern struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg); #else static inline struct dvb_frontend * dib3000mc_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib3000mc_config *cfg) diff --git a/drivers/media/dvb/frontends/isl6421.h b/drivers/media/dvb/frontends/isl6421.h index 1916e3eb2df3..ea7f78a7d3cd 100644 --- a/drivers/media/dvb/frontends/isl6421.h +++ b/drivers/media/dvb/frontends/isl6421.h @@ -39,7 +39,7 @@ #define ISL6421_ISEL1 0x20 #define ISL6421_DCL 0x40 -#if defined(CONFIG_DVB_ISL6421) || defined(CONFIG_DVB_ISL6421_MODULE) +#if defined(CONFIG_DVB_ISL6421) || (defined(CONFIG_DVB_ISL6421_MODULE) && defined(MODULE)) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr, u8 override_set, u8 override_clear); diff --git a/drivers/media/dvb/frontends/l64781.h b/drivers/media/dvb/frontends/l64781.h index 21ba4a230760..cd15f76ff28d 100644 --- a/drivers/media/dvb/frontends/l64781.h +++ b/drivers/media/dvb/frontends/l64781.h @@ -31,7 +31,7 @@ struct l64781_config u8 demod_address; }; -#if defined(CONFIG_DVB_L64781) || defined(CONFIG_DVB_L64781_MODULE) +#if defined(CONFIG_DVB_L64781) || (defined(CONFIG_DVB_L64781_MODULE) && defined(MODULE)) extern struct dvb_frontend* l64781_attach(const struct l64781_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/lgdt330x.h b/drivers/media/dvb/frontends/lgdt330x.h index 3f96b485584c..995059004b10 100644 --- a/drivers/media/dvb/frontends/lgdt330x.h +++ b/drivers/media/dvb/frontends/lgdt330x.h @@ -52,7 +52,7 @@ struct lgdt330x_config int clock_polarity_flip; }; -#if defined(CONFIG_DVB_LGDT330X) || defined(CONFIG_DVB_LGDT330X_MODULE) +#if defined(CONFIG_DVB_LGDT330X) || (defined(CONFIG_DVB_LGDT330X_MODULE) && defined(MODULE)) extern struct dvb_frontend* lgdt330x_attach(const struct lgdt330x_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/lnbp21.h b/drivers/media/dvb/frontends/lnbp21.h index 1fe1dd179312..68906acf7d63 100644 --- a/drivers/media/dvb/frontends/lnbp21.h +++ b/drivers/media/dvb/frontends/lnbp21.h @@ -39,7 +39,7 @@ #include -#if defined(CONFIG_DVB_LNBP21) || defined(CONFIG_DVB_LNBP21_MODULE) +#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) && defined(MODULE)) /* override_set and override_clear control which system register bits (above) to always set & clear */ extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 override_set, u8 override_clear); #else diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index 7112fb4d58ac..cf9a1505ad4b 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -34,7 +34,7 @@ struct mt312_config u8 demod_address; }; -#if defined(CONFIG_DVB_MT312) || defined(CONFIG_DVB_MT312_MODULE) +#if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE)) struct dvb_frontend* vp310_mt312_attach(const struct mt312_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h index 0035c2e2d7c2..e9964081fd84 100644 --- a/drivers/media/dvb/frontends/mt352.h +++ b/drivers/media/dvb/frontends/mt352.h @@ -51,7 +51,7 @@ struct mt352_config int (*demod_init)(struct dvb_frontend* fe); }; -#if defined(CONFIG_DVB_MT352) || defined(CONFIG_DVB_MT352_MODULE) +#if defined(CONFIG_DVB_MT352) || (defined(CONFIG_DVB_MT352_MODULE) && defined(MODULE)) extern struct dvb_frontend* mt352_attach(const struct mt352_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/nxt200x.h b/drivers/media/dvb/frontends/nxt200x.h index 2eb220e98062..28bc5591b319 100644 --- a/drivers/media/dvb/frontends/nxt200x.h +++ b/drivers/media/dvb/frontends/nxt200x.h @@ -45,7 +45,7 @@ struct nxt200x_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; -#if defined(CONFIG_DVB_NXT200X) || defined(CONFIG_DVB_NXT200X_MODULE) +#if defined(CONFIG_DVB_NXT200X) || (defined(CONFIG_DVB_NXT200X_MODULE) && defined(MODULE)) extern struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/nxt6000.h b/drivers/media/dvb/frontends/nxt6000.h index 9397393a6bd1..13d22518356e 100644 --- a/drivers/media/dvb/frontends/nxt6000.h +++ b/drivers/media/dvb/frontends/nxt6000.h @@ -33,7 +33,7 @@ struct nxt6000_config u8 clock_inversion:1; }; -#if defined(CONFIG_DVB_NXT6000) || defined(CONFIG_DVB_NXT6000_MODULE) +#if defined(CONFIG_DVB_NXT6000) || (defined(CONFIG_DVB_NXT6000_MODULE) && defined(MODULE)) extern struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/or51132.h b/drivers/media/dvb/frontends/or51132.h index 9718be4fb835..add24f0a743b 100644 --- a/drivers/media/dvb/frontends/or51132.h +++ b/drivers/media/dvb/frontends/or51132.h @@ -34,7 +34,7 @@ struct or51132_config int (*set_ts_params)(struct dvb_frontend* fe, int is_punctured); }; -#if defined(CONFIG_DVB_OR51132) || defined(CONFIG_DVB_OR51132_MODULE) +#if defined(CONFIG_DVB_OR51132) || (defined(CONFIG_DVB_OR51132_MODULE) && defined(MODULE)) extern struct dvb_frontend* or51132_attach(const struct or51132_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/or51211.h b/drivers/media/dvb/frontends/or51211.h index 10a5419f9e00..8aad8402d615 100644 --- a/drivers/media/dvb/frontends/or51211.h +++ b/drivers/media/dvb/frontends/or51211.h @@ -37,7 +37,7 @@ struct or51211_config void (*sleep)(struct dvb_frontend * fe); }; -#if defined(CONFIG_DVB_OR51211) || defined(CONFIG_DVB_OR51211_MODULE) +#if defined(CONFIG_DVB_OR51211) || (defined(CONFIG_DVB_OR51211_MODULE) && defined(MODULE)) extern struct dvb_frontend* or51211_attach(const struct or51211_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/s5h1420.h b/drivers/media/dvb/frontends/s5h1420.h index efc54d7f3c55..1555870f7226 100644 --- a/drivers/media/dvb/frontends/s5h1420.h +++ b/drivers/media/dvb/frontends/s5h1420.h @@ -34,7 +34,7 @@ struct s5h1420_config u8 invert:1; }; -#if defined(CONFIG_DVB_S5H1420) || defined(CONFIG_DVB_S5H1420_MODULE) +#if defined(CONFIG_DVB_S5H1420) || (defined(CONFIG_DVB_S5H1420_MODULE) && defined(MODULE)) extern struct dvb_frontend* s5h1420_attach(const struct s5h1420_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/sp8870.h b/drivers/media/dvb/frontends/sp8870.h index 4cf27d3b10f2..909cefe7139e 100644 --- a/drivers/media/dvb/frontends/sp8870.h +++ b/drivers/media/dvb/frontends/sp8870.h @@ -35,7 +35,7 @@ struct sp8870_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_SP8870) || defined(CONFIG_DVB_SP8870_MODULE) +#if defined(CONFIG_DVB_SP8870) || (defined(CONFIG_DVB_SP8870_MODULE) && defined(MODULE)) extern struct dvb_frontend* sp8870_attach(const struct sp8870_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/sp887x.h b/drivers/media/dvb/frontends/sp887x.h index cab7ea644dfa..7ee78d7d916d 100644 --- a/drivers/media/dvb/frontends/sp887x.h +++ b/drivers/media/dvb/frontends/sp887x.h @@ -17,7 +17,7 @@ struct sp887x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_SP887X) || defined(CONFIG_DVB_SP887X_MODULE) +#if defined(CONFIG_DVB_SP887X) || (defined(CONFIG_DVB_SP887X_MODULE) && defined(MODULE)) extern struct dvb_frontend* sp887x_attach(const struct sp887x_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/stv0297.h b/drivers/media/dvb/frontends/stv0297.h index 760b80db43a5..69f4515df2b9 100644 --- a/drivers/media/dvb/frontends/stv0297.h +++ b/drivers/media/dvb/frontends/stv0297.h @@ -42,7 +42,7 @@ struct stv0297_config u8 stop_during_read:1; }; -#if defined(CONFIG_DVB_STV0297) || defined(CONFIG_DVB_STV0297_MODULE) +#if defined(CONFIG_DVB_STV0297) || (defined(CONFIG_DVB_STV0297_MODULE) && defined(MODULE)) extern struct dvb_frontend* stv0297_attach(const struct stv0297_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h index 7ef25207081d..33df9495908f 100644 --- a/drivers/media/dvb/frontends/stv0299.h +++ b/drivers/media/dvb/frontends/stv0299.h @@ -89,7 +89,7 @@ struct stv0299_config int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); }; -#if defined(CONFIG_DVB_STV0299) || defined(CONFIG_DVB_STV0299_MODULE) +#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/tda10021.h b/drivers/media/dvb/frontends/tda10021.h index d68ae20c8412..e3da780108f6 100644 --- a/drivers/media/dvb/frontends/tda10021.h +++ b/drivers/media/dvb/frontends/tda10021.h @@ -32,7 +32,7 @@ struct tda10021_config u8 demod_address; }; -#if defined(CONFIG_DVB_TDA10021) || defined(CONFIG_DVB_TDA10021_MODULE) +#if defined(CONFIG_DVB_TDA10021) || (defined(CONFIG_DVB_TDA10021_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10021_attach(const struct tda10021_config* config, struct i2c_adapter* i2c, u8 pwm); #else diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h index e28fca05734c..605ad2dfc09d 100644 --- a/drivers/media/dvb/frontends/tda1004x.h +++ b/drivers/media/dvb/frontends/tda1004x.h @@ -71,7 +71,7 @@ struct tda1004x_config int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name); }; -#if defined(CONFIG_DVB_TDA1004X) || defined(CONFIG_DVB_TDA1004X_MODULE) +#if defined(CONFIG_DVB_TDA1004X) || (defined(CONFIG_DVB_TDA1004X_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config, struct i2c_adapter* i2c); diff --git a/drivers/media/dvb/frontends/tda10086.h b/drivers/media/dvb/frontends/tda10086.h index 18457adee30b..ed584a8f4a89 100644 --- a/drivers/media/dvb/frontends/tda10086.h +++ b/drivers/media/dvb/frontends/tda10086.h @@ -35,7 +35,7 @@ struct tda10086_config u8 invert; }; -#if defined(CONFIG_DVB_TDA10086) || defined(CONFIG_DVB_TDA10086_MODULE) +#if defined(CONFIG_DVB_TDA10086) || (defined(CONFIG_DVB_TDA10086_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda10086_attach(const struct tda10086_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/tda8083.h b/drivers/media/dvb/frontends/tda8083.h index aae15bdce6eb..2d3307999f21 100644 --- a/drivers/media/dvb/frontends/tda8083.h +++ b/drivers/media/dvb/frontends/tda8083.h @@ -35,7 +35,7 @@ struct tda8083_config u8 demod_address; }; -#if defined(CONFIG_DVB_TDA8083) || defined(CONFIG_DVB_TDA8083_MODULE) +#if defined(CONFIG_DVB_TDA8083) || (defined(CONFIG_DVB_TDA8083_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda8083_attach(const struct tda8083_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/tda826x.h b/drivers/media/dvb/frontends/tda826x.h index 83998c001196..ad9981195961 100644 --- a/drivers/media/dvb/frontends/tda826x.h +++ b/drivers/media/dvb/frontends/tda826x.h @@ -35,7 +35,7 @@ * @param has_loopthrough Set to 1 if the card has a loopthrough RF connector. * @return FE pointer on success, NULL on failure. */ -#if defined(CONFIG_DVB_TDA826X) || defined(CONFIG_DVB_TDA826X_MODULE) +#if defined(CONFIG_DVB_TDA826X) || (defined(CONFIG_DVB_TDA826X_MODULE) && defined(MODULE)) extern struct dvb_frontend* tda826x_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c, int has_loopthrough); diff --git a/drivers/media/dvb/frontends/tua6100.h b/drivers/media/dvb/frontends/tua6100.h index 8f98033ffa7b..03a665e7df6d 100644 --- a/drivers/media/dvb/frontends/tua6100.h +++ b/drivers/media/dvb/frontends/tua6100.h @@ -34,7 +34,7 @@ #include #include "dvb_frontend.h" -#if defined(CONFIG_DVB_TUA6100) || defined(CONFIG_DVB_TUA6100_MODULE) +#if defined(CONFIG_DVB_TUA6100) || (defined(CONFIG_DVB_TUA6100_MODULE) && defined(MODULE)) extern struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c); #else static inline struct dvb_frontend* tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c) diff --git a/drivers/media/dvb/frontends/ves1820.h b/drivers/media/dvb/frontends/ves1820.h index f0c9dded39d7..e4a2a324046a 100644 --- a/drivers/media/dvb/frontends/ves1820.h +++ b/drivers/media/dvb/frontends/ves1820.h @@ -41,7 +41,7 @@ struct ves1820_config u8 selagc:1; }; -#if defined(CONFIG_DVB_VES1820) || defined(CONFIG_DVB_VES1820_MODULE) +#if defined(CONFIG_DVB_VES1820) || (defined(CONFIG_DVB_VES1820_MODULE) && defined(MODULE)) extern struct dvb_frontend* ves1820_attach(const struct ves1820_config* config, struct i2c_adapter* i2c, u8 pwm); #else diff --git a/drivers/media/dvb/frontends/ves1x93.h b/drivers/media/dvb/frontends/ves1x93.h index 395fed39b286..d507f8966f81 100644 --- a/drivers/media/dvb/frontends/ves1x93.h +++ b/drivers/media/dvb/frontends/ves1x93.h @@ -40,7 +40,7 @@ struct ves1x93_config u8 invert_pwm:1; }; -#if defined(CONFIG_DVB_VES1X93) || defined(CONFIG_DVB_VES1X93_MODULE) +#if defined(CONFIG_DVB_VES1X93) || (defined(CONFIG_DVB_VES1X93_MODULE) && defined(MODULE)) extern struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config, struct i2c_adapter* i2c); #else diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index 79a947215c4d..0bc0109737f1 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -36,7 +36,7 @@ struct zl10353_config int parallel_ts; }; -#if defined(CONFIG_DVB_ZL10353) || defined(CONFIG_DVB_ZL10353_MODULE) +#if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) extern struct dvb_frontend* zl10353_attach(const struct zl10353_config *config, struct i2c_adapter *i2c); #else -- cgit v1.2.3 From bb44c308ee37c14ab63251e27d6d8b4dc73a10a4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 27 Oct 2006 16:12:30 -0700 Subject: PCI: Let PCI_MULTITHREAD_PROBE depend on BROKEN PCI_MULTITHREAD_PROBE is an interesting feature, but in its current state it seems to be more of a trap for users who accidentally enable it. This patch lets PCI_MULTITHREAD_PROBE depend on BROKEN for 2.6.19. The intention is to get this patch reversed in -mm as soon as it's in Linus' tree, and reverse it for 2.6.20 or 2.6.21 after the fallout of in-kernel problems PCI_MULTITHREAD_PROBE causes got fixed. (akpm: I get enough bug reports already) Signed-off-by: Adrian Bunk Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index ecc50db8585a..5f1b9f58070e 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -19,7 +19,7 @@ config PCI_MSI config PCI_MULTITHREAD_PROBE bool "PCI Multi-threaded probe (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + depends on PCI && EXPERIMENTAL && BROKEN help Say Y here if you want the PCI core to spawn a new thread for every PCI device that is probed. This can cause a huge -- cgit v1.2.3 From 90ac3c8124453fb355c10d3e1a27af5c0ab21099 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Apr 2002 12:14:34 -0700 Subject: USB: add another sierra wireless device id As reported by Peter Kucmeroski and Jason Ganovsky. Cc: Peter Kucmeroski Cc: Jason Ganovsky Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index ea16572d19f8..69cc8fb4156d 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -35,6 +35,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */ @@ -58,6 +59,7 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x0020) }, /* Sierra Wireless MC5725 */ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ { USB_DEVICE(0x1199, 0x0019) }, /* Sierra Wireless AirCard 595 */ + { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ -- cgit v1.2.3 From bc724b98c5e782c2d6781428ed87768daa34921d Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Thu, 19 Oct 2006 00:11:17 -0700 Subject: USB: usb-storage: Unusual_dev update The protocol in this entry is needed for some versions of the device but not others. This adds the NEED_OVERRIDE flag to prevent it complaining to users who don't need it. Signed-off-by: Phil Dibowitz --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 37ed8e0f2dc8..1e0d04f721fd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1236,7 +1236,7 @@ UNUSUAL_DEV( 0x0e21, 0x0520, 0x0100, 0x0100, "Cowon Systems", "iAUDIO M5", US_SC_DEVICE, US_PR_BULK, NULL, - 0 ), + US_FL_NEED_OVERRIDE ), /* Submitted by Antoine Mairesse */ UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300, -- cgit v1.2.3 From 68717950e11eab8ff754b2721d23e9cb3a47b56f Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Thu, 19 Oct 2006 15:09:51 -0700 Subject: hid-core: big-endian fix fix Adam Kropelin had posted 32-bit fix in June 2005 about two weeks after I originally had posted my fixes for big endian support. Adam has a UPS device which reports LINEV using 32-bits. Added comments to describe the limitations of the code. extract() is the same version I posted earlier and tested in user space. Made similar changes to implement() routine. I've written (and will shortly post) a test for implement(). Code tested on C3600 (parisc) with USB keyboard/mouse attached. I've dropped test_implement.c and a few other user space test programs on http://iou.parisc-linux.org/~grundler/tests/ -rw-r--r-- 1 grundler grundler 1750 Oct 18 09:13 test_extract.c -rw-r--r-- 1 grundler grundler 561 Jan 25 2006 test_ffs.c -rw-r--r-- 1 grundler users 7175 Apr 8 2005 test_fls.c -rw-r--r-- 1 grundler grundler 206 Sep 1 15:52 test_gettimeofday.c -rw-r--r-- 1 grundler grundler 1886 Oct 19 09:20 test_implement.c -rw-r--r-- 1 grundler users 2707 Jun 4 2005 test_unaligned.c I would appreciate if someone else would look at the output of test_implement.c to make it does The Right Thing. Signed-off-by: Grant Grundler Cc: Matthew Wilcox Cc: Dmitry Torokhov Acked-By: Adam Kropelin Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 59 +++++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 45f44fe33bfe..6d42036c906c 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -270,7 +270,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign * Read data value from item. */ -static __inline__ __u32 item_udata(struct hid_item *item) +static u32 item_udata(struct hid_item *item) { switch (item->size) { case 1: return item->data.u8; @@ -280,7 +280,7 @@ static __inline__ __u32 item_udata(struct hid_item *item) return 0; } -static __inline__ __s32 item_sdata(struct hid_item *item) +static s32 item_sdata(struct hid_item *item) { switch (item->size) { case 1: return item->data.s8; @@ -727,7 +727,7 @@ static struct hid_device *hid_parse_report(__u8 *start, unsigned size) * done by hand. */ -static __inline__ __s32 snto32(__u32 value, unsigned n) +static s32 snto32(__u32 value, unsigned n) { switch (n) { case 8: return ((__s8)value); @@ -741,9 +741,9 @@ static __inline__ __s32 snto32(__u32 value, unsigned n) * Convert a signed 32-bit integer to a signed n-bit integer. */ -static __inline__ __u32 s32ton(__s32 value, unsigned n) +static u32 s32ton(__s32 value, unsigned n) { - __s32 a = value >> (n - 1); + s32 a = value >> (n - 1); if (a && a != -1) return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1; return value & ((1 << n) - 1); @@ -751,30 +751,55 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) /* * Extract/implement a data field from/to a little endian report (bit array). + * + * Code sort-of follows HID spec: + * http://www.usb.org/developers/devclass_docs/HID1_11.pdf + * + * While the USB HID spec allows unlimited length bit fields in "report + * descriptors", most devices never use more than 16 bits. + * One model of UPS is claimed to report "LINEV" as a 32-bit field. + * Search linux-kernel and linux-usb-devel archives for "hid-core extract". */ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) { - u32 x; + u64 x; + + WARN_ON(n > 32); report += offset >> 3; /* adjust byte index */ - offset &= 8 - 1; - x = get_unaligned((u32 *) report); - x = le32_to_cpu(x); - x = (x >> offset) & ((1 << n) - 1); - return x; + offset &= 7; /* now only need bit offset into one byte */ + x = get_unaligned((u64 *) report); + x = le64_to_cpu(x); + x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ + return (u32) x; } +/* + * "implement" : set bits in a little endian bit stream. + * Same concepts as "extract" (see comments above). + * The data mangled in the bit stream remains in little endian + * order the whole time. It make more sense to talk about + * endianness of register values by considering a register + * a "cached" copy of the little endiad bit stream. + */ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) { - u32 x; + u64 x; + u64 m = (1ULL << n) - 1; + + WARN_ON(n > 32); + + WARN_ON(value > m); + value &= m; report += offset >> 3; - offset &= 8 - 1; - x = get_unaligned((u32 *)report); - x &= cpu_to_le32(~((((__u32) 1 << n) - 1) << offset)); - x |= cpu_to_le32(value << offset); - put_unaligned(x,(u32 *)report); + offset &= 7; + + x = get_unaligned((u64 *)report); + x &= cpu_to_le64(~(m << offset)); + x |= cpu_to_le64(((u64) value) << offset); + put_unaligned(x, (u64 *) report); } /* -- cgit v1.2.3 From 78001e3d75c5d3ae1e8dc9875892b9461e4c8d4b Mon Sep 17 00:00:00 2001 From: Bjorn Schneider Date: Sat, 28 Oct 2006 12:42:04 +0200 Subject: USB: new VID/PID-combos for cp2101 3 new VID/PID combinations (registered with Silicon Laboratories Inc.) added for devices made by Lipowsky Industrie Elektronik GmbH all using the CP2102 usb-to-serial converter (Baby-JTAG, Baby-LIN, HARP-1). Signed-off-by: Bjorn Schneider Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index bbf6532c26e5..f95d42c0d16a 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -64,6 +64,9 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ -- cgit v1.2.3 From baafe37c6a58d4ddb8c2c62cd0f20340b4c66b35 Mon Sep 17 00:00:00 2001 From: Jan Luebbe Date: Fri, 27 Oct 2006 18:59:24 +0200 Subject: USB: sierra: Fix id for Sierra Wireless MC8755 in new table The new version of sierra.c has introduced tables for the 1 port and 3 port variants. The device id i added in my last patch needs to be added to the 3 port table. Signed-off-by: Jan Luebbe Cc: Kevin Lloyd Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 69cc8fb4156d..4b5097fa48d7 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -62,6 +62,7 @@ static struct usb_device_id id_table_3port [] = { { USB_DEVICE(0x1199, 0x0218) }, /* Sierra Wireless MC5720 */ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */ + { USB_DEVICE(0x1199, 0x6804) }, /* Sierra Wireless MC8755 for Europe */ { USB_DEVICE(0x1199, 0x6812) }, /* Sierra Wireless MC8775 */ { USB_DEVICE(0x1199, 0x6820) }, /* Sierra Wireless AirCard 875 */ { } -- cgit v1.2.3 From d8fa59a8f6f7c9a1bc294154fd6805c6b247683d Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Fri, 27 Oct 2006 22:46:03 +0200 Subject: usbtouchscreen: use endpoint address from endpoint descriptor use the endpoint address from the endpoint descriptor instead of the hardcoding it to 0x81. at least some ITM based screen use a different address and don't work without this. Signed-off-by: Daniel Ritz Cc: Ralf Lehmann Cc: J.P. Delport Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/usbtouchscreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index 2902742895ad..933ceddf3dee 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -640,7 +640,7 @@ static int usbtouch_probe(struct usb_interface *intf, type->max_press, 0, 0); usb_fill_int_urb(usbtouch->irq, usbtouch->udev, - usb_rcvintpipe(usbtouch->udev, 0x81), + usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), usbtouch->data, type->rept_size, usbtouch_irq, usbtouch, endpoint->bInterval); -- cgit v1.2.3 From 6c8df79f8c0f8d861ea25e6e104a29398d8398f4 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sat, 28 Oct 2006 11:36:59 +0200 Subject: USB: failure in usblp's error path if urb submission fails due to a transient error here eg. ENOMEM , the driver is dead. This fixes it. Regards Oliver Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 809d465eb257..16353b661a04 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -722,6 +722,7 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t usblp->wcomplete = 0; err = usb_submit_urb(usblp->writeurb, GFP_KERNEL); if (err) { + usblp->wcomplete = 1; if (err != -ENOMEM) count = -EIO; else -- cgit v1.2.3 From 5a69ebe1e90d9e8d43131f08d344751cf42254c5 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sat, 28 Oct 2006 18:07:25 +0200 Subject: USB: usblp: fix system suspend for some systems this has been confirmed to fix suspend problems with usblp. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 16353b661a04..6303970e93c1 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1203,8 +1203,6 @@ static int usblp_suspend (struct usb_interface *intf, pm_message_t message) down (&usblp->sem); /* we take no more IO */ usblp->sleeping = 1; - /* we wait for anything printing */ - wait_event (usblp->wait, usblp->wcomplete || !usblp->present); usblp_unlink_urbs(usblp); up (&usblp->sem); mutex_unlock (&usblp_mutex); -- cgit v1.2.3 From 23b0d968c2c82c2574ca97148ce092eff4ab84a6 Mon Sep 17 00:00:00 2001 From: Naranjo Manuel Francisco Date: Fri, 27 Oct 2006 16:08:54 -0300 Subject: USB: HID: add blacklist AIRcable USB, little beautification This patch add AIRcable USBto USB-HID blacklist, makes some little changes things in the Kconfig to make AIRcable USB look as all the rest of drivers. And it removes the readme part that was on Documentation/usb/usb-serial.txt because it is not needed anymore. Signed-off-by: Naranjo Manuel Francisco --- Documentation/usb/usb-serial.txt | 6 ------ drivers/usb/input/hid-core.c | 4 ++++ drivers/usb/serial/Kconfig | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 8dc2bacc8f1f..50436e1663ea 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -428,12 +428,6 @@ Options supported: See http://www.uuhaus.de/linux/palmconnect.html for up-to-date information on this driver. -AIRcable USB Dongle Bluetooth driver - If there is the cdc_acm driver loaded in the system, you will find that the - cdc_acm claims the device before AIRcable can. This is simply corrected - by unloading both modules and then loading the aircable module before - cdc_acm module - Generic Serial driver If your device is not one of the above listed devices, compatible with diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6d42036c906c..6daf85c6eeee 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1640,6 +1640,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_SUN 0x0430 #define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab +#define USB_VENDOR_ID_AIRCABLE 0x16CA +#define USB_DEVICE_ID_AIRCABLE1 0x1502 + /* * Alphabetically sorted blacklist by quirk type. */ @@ -1657,6 +1660,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_22, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_23, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_24, HID_QUIRK_IGNORE }, + { USB_VENDOR_ID_AIRCABLE, USB_DEVICE_ID_AIRCABLE1, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ALCOR, USB_DEVICE_ID_ALCOR_USBRS232, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE }, diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 9a6ec1b5e3d5..2a8dd4cc943d 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -54,10 +54,10 @@ config USB_SERIAL_GENERIC properly. config USB_SERIAL_AIRCABLE - tristate "AIRcable USB Bluetooth Dongle Driver (EXPERIMENTAL)" + tristate "USB AIRcable Bluetooth Dongle Driver (EXPERIMENTAL)" depends on USB_SERIAL && EXPERIMENTAL help - Say Y here if you want to use AIRcable USB Bluetoot Dongle. + Say Y here if you want to use USB AIRcable Bluetooth Dongle. To compile this driver as a module, choose M here: the module will be called aircable. -- cgit v1.2.3 From 11bd44abbd204f580ea91e75c84e012988971012 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 1 Nov 2006 14:26:26 -0800 Subject: USB: fix compiler issues with newer gcc versions Remove complaint from newer GCCs; they don't like forward function declarations except in top-level contexts. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 66bff184a30c..ba165aff9ea4 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1188,6 +1188,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) #ifdef CONFIG_USB_OTG #include "otg_whitelist.h" +static int __usb_port_suspend(struct usb_device *, int port1); #endif /** @@ -1289,8 +1290,6 @@ int usb_new_device(struct usb_device *udev) * (Includes HNP test device.) */ if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { - static int __usb_port_suspend(struct usb_device *, - int port1); err = __usb_port_suspend(udev, udev->bus->otg_port); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); -- cgit v1.2.3 From d518b2b48a9c11fc381b179709f5321bce1f3b39 Mon Sep 17 00:00:00 2001 From: Dominic Cerquetti Date: Fri, 20 Oct 2006 14:51:45 -0700 Subject: USB: xpad: additional USB id's added Adding additional USB vendor/product ID's for XBOX pads provided by the XBOX Linux team. Signed-off-by: Dominic Cerquetti Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/xpad.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index 6a12a943b938..df97e5c803f9 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c @@ -2,6 +2,10 @@ * X-Box gamepad - v0.0.6 * * Copyright (c) 2002 Marko Friedemann + * 2004 Oliver Schwartz , + * Steven Toth , + * Franz Lehner , + * Ivan Hawkes * 2005 Dominic Cerquetti * 2006 Adam Buchbinder * @@ -29,6 +33,7 @@ * - ITO Takayuki for providing essential xpad information on his website * - Vojtech Pavlik - iforce driver / input subsystem * - Greg Kroah-Hartman - usb-skeleton driver + * - XBOX Linux project - extra USB id's * * TODO: * - fine tune axes (especially trigger axes) @@ -54,6 +59,13 @@ * - fixed d-pad to axes mapping * * 2002-07-17 - 0.0.5 : simplified d-pad handling + * + * 2004-10-02 - 0.0.6 : DDR pad support + * - borrowed from the XBOX linux kernel + * - USB id's for commonly used dance pads are present + * - dance pads will map D-PAD to buttons, not axes + * - pass the module paramater 'dpad_to_buttons' to force + * the D-PAD to map to buttons if your pad is not detected */ #include @@ -90,8 +102,35 @@ static const struct xpad_device { { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES }, { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES }, - { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, + { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES }, { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS }, + { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES }, + { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES }, + { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES }, + { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES }, + { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES }, + { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES }, + { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES }, + { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES }, + { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES }, + { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS }, + { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES }, + { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS }, + { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, + { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES }, + { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES }, + { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES }, + { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES}, + { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES }, + { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES }, + { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES }, + { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES }, + { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES }, + { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES }, + { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES }, + { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS }, + { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS }, + { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES }, { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN } }; -- cgit v1.2.3 From 9b823b43ff308c914530ec7fde5e2d79cb37b51a Mon Sep 17 00:00:00 2001 From: Jan Mate Date: Fri, 20 Oct 2006 14:51:44 -0700 Subject: USB Storage: unusual_devs.h entry for Sony Ericsson P990i USB Storage: this patch adds support for Sony Ericsson P990i Signed-off-by: Jan Mate Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1e0d04f721fd..bc1ac07bf6ce 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1313,6 +1313,13 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Jan Mate */ +UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, + "Sony Ericsson", + "P990i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. -- cgit v1.2.3 From 18ee91fa9815fa3bb4e51cdcb8229bd0a0f11a70 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 2 Nov 2006 12:29:12 -0800 Subject: USB: use MII hooks only if CONFIG_MII is enabled Fix mcs7830 patch The recent mcs7830 update to make the MII support sharable goofed various pre-existing configurations in two ways: - it made the usbnet infrastructure reference MII symbols even when they're not needed in the kernel being built - it didn't enable MII along with the mcs7830 minidriver This patch fixes these two problems. However, there does seem to be a Kconfig reverse dependency bug in that MII gets wrongly enabled in some cases (like USBNET=y and USBNET_MII=n); I think I've noticed that same problem in other situations too. So the result can mean kernels being bloated by stuff that's needlessly enabled ... better than wrongly being disabled, but contributing to bloat. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/Kconfig | 8 ++++++- drivers/usb/net/usbnet.c | 58 ++++++++++++++++++++++++++---------------------- 2 files changed, 39 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig index 454a186b64ad..e081836014ac 100644 --- a/drivers/usb/net/Kconfig +++ b/drivers/usb/net/Kconfig @@ -92,8 +92,13 @@ config USB_RTL8150 To compile this driver as a module, choose M here: the module will be called rtl8150. +config USB_USBNET_MII + tristate + default n + config USB_USBNET tristate "Multi-purpose USB Networking Framework" + select MII if USBNET_MII != n ---help--- This driver supports several kinds of network links over USB, with "minidrivers" built around a common network driver core @@ -129,7 +134,7 @@ config USB_NET_AX8817X tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters" depends on USB_USBNET && NET_ETHERNET select CRC32 - select MII + select USB_USBNET_MII default y help This option adds support for ASIX AX88xxx based USB 2.0 @@ -210,6 +215,7 @@ config USB_NET_PLUSB config USB_NET_MCS7830 tristate "MosChip MCS7830 based Ethernet adapters" depends on USB_USBNET + select USB_USBNET_MII help Choose this option if you're using a 10/100 Ethernet USB2 adapter based on the MosChip 7830 controller. This includes diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 40873635d80e..760b5327b81b 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -669,6 +669,9 @@ done: * they'll probably want to use this base set. */ +#if defined(CONFIG_MII) || defined(CONFIG_MII_MODULE) +#define HAVE_MII + int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd) { struct usbnet *dev = netdev_priv(net); @@ -699,20 +702,6 @@ int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd) } EXPORT_SYMBOL_GPL(usbnet_set_settings); - -void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) -{ - struct usbnet *dev = netdev_priv(net); - - /* REVISIT don't always return "usbnet" */ - strncpy (info->driver, driver_name, sizeof info->driver); - strncpy (info->version, DRIVER_VERSION, sizeof info->version); - strncpy (info->fw_version, dev->driver_info->description, - sizeof info->fw_version); - usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info); -} -EXPORT_SYMBOL_GPL(usbnet_get_drvinfo); - u32 usbnet_get_link (struct net_device *net) { struct usbnet *dev = netdev_priv(net); @@ -730,40 +719,57 @@ u32 usbnet_get_link (struct net_device *net) } EXPORT_SYMBOL_GPL(usbnet_get_link); -u32 usbnet_get_msglevel (struct net_device *net) +int usbnet_nway_reset(struct net_device *net) { struct usbnet *dev = netdev_priv(net); - return dev->msg_enable; + if (!dev->mii.mdio_write) + return -EOPNOTSUPP; + + return mii_nway_restart(&dev->mii); } -EXPORT_SYMBOL_GPL(usbnet_get_msglevel); +EXPORT_SYMBOL_GPL(usbnet_nway_reset); -void usbnet_set_msglevel (struct net_device *net, u32 level) +#endif /* HAVE_MII */ + +void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info) { struct usbnet *dev = netdev_priv(net); - dev->msg_enable = level; + /* REVISIT don't always return "usbnet" */ + strncpy (info->driver, driver_name, sizeof info->driver); + strncpy (info->version, DRIVER_VERSION, sizeof info->version); + strncpy (info->fw_version, dev->driver_info->description, + sizeof info->fw_version); + usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info); } -EXPORT_SYMBOL_GPL(usbnet_set_msglevel); +EXPORT_SYMBOL_GPL(usbnet_get_drvinfo); -int usbnet_nway_reset(struct net_device *net) +u32 usbnet_get_msglevel (struct net_device *net) { struct usbnet *dev = netdev_priv(net); - if (!dev->mii.mdio_write) - return -EOPNOTSUPP; + return dev->msg_enable; +} +EXPORT_SYMBOL_GPL(usbnet_get_msglevel); - return mii_nway_restart(&dev->mii); +void usbnet_set_msglevel (struct net_device *net, u32 level) +{ + struct usbnet *dev = netdev_priv(net); + + dev->msg_enable = level; } -EXPORT_SYMBOL_GPL(usbnet_nway_reset); +EXPORT_SYMBOL_GPL(usbnet_set_msglevel); /* drivers may override default ethtool_ops in their bind() routine */ static struct ethtool_ops usbnet_ethtool_ops = { +#ifdef HAVE_MII .get_settings = usbnet_get_settings, .set_settings = usbnet_set_settings, - .get_drvinfo = usbnet_get_drvinfo, .get_link = usbnet_get_link, .nway_reset = usbnet_nway_reset, +#endif + .get_drvinfo = usbnet_get_drvinfo, .get_msglevel = usbnet_get_msglevel, .set_msglevel = usbnet_set_msglevel, }; -- cgit v1.2.3 From 7870db4c7fa1b03fec133c4f4e67fdaa04c5ac15 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 2 Nov 2006 22:06:57 -0800 Subject: [PATCH] md: send online/offline uevents when an md array starts/stops This allows udev to do something intelligent when an array becomes available. Acked-by: Greg KH Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 50ab4a936e30..d11135604403 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3200,6 +3200,7 @@ static int do_md_run(mddev_t * mddev) mddev->changed = 1; md_new_event(mddev); + kobject_uevent(&mddev->gendisk->kobj, KOBJ_ONLINE); return 0; } @@ -3313,6 +3314,7 @@ static int do_md_stop(mddev_t * mddev, int mode) module_put(mddev->pers->owner); mddev->pers = NULL; + kobject_uevent(&mddev->gendisk->kobj, KOBJ_OFFLINE); if (mddev->ro) mddev->ro = 0; } -- cgit v1.2.3 From 5d861d920a86523bbeb56c19b9906c3fb1b58048 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 2 Nov 2006 22:07:06 -0800 Subject: [PATCH] lkdtm: cleanup headers and module_param/MODULE_PARM_DESC Fix module_param/sysfs file permission typo. Clean up MODULE_PARM_DESC strings to avoid fancy (and incorrect) formatting. Fix header includes for lkdtm; add some needed ones, remove unused ones; and fix this gcc warning: drivers/misc/lkdtm.c:150: warning: 'struct buffer_head' declared inside parameter list drivers/misc/lkdtm.c:150: warning: its scope is only this definition or declaration, which is probably not what you want Signed-off-by: Randy Dunlap Cc: Ankita Garg Cc: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/lkdtm.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index bbdba7b37e11..46a9c35943bd 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -44,12 +44,14 @@ */ #include +#include #include +#include #include -#include +#include #include -#include #include +#include #include #ifdef CONFIG_IDE @@ -116,16 +118,16 @@ static enum ctype cptype = NONE; static int count = DEFAULT_COUNT; module_param(recur_count, int, 0644); -MODULE_PARM_DESC(recur_count, "Recurcion level for the stack overflow test,\ - default is 10"); +MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\ + "default is 10"); module_param(cpoint_name, charp, 0644); -MODULE_PARM_DESC(cpoint_name, "Crash Point, where kernel is to be crashed"); -module_param(cpoint_type, charp, 06444); -MODULE_PARM_DESC(cpoint_type, "Crash Point Type, action to be taken on\ - hitting the crash point"); -module_param(cpoint_count, int, 06444); -MODULE_PARM_DESC(cpoint_count, "Crash Point Count, number of times the \ - crash point is to be hit to trigger action"); +MODULE_PARM_DESC(cpoint_name, " Crash Point, where kernel is to be crashed"); +module_param(cpoint_type, charp, 0644); +MODULE_PARM_DESC(cpoint_type, " Crash Point Type, action to be taken on "\ + "hitting the crash point"); +module_param(cpoint_count, int, 0644); +MODULE_PARM_DESC(cpoint_count, " Crash Point Count, number of times the "\ + "crash point is to be hit to trigger action"); unsigned int jp_do_irq(unsigned int irq) { -- cgit v1.2.3 From 77d6e1397a004c9376fed855e4164ca2b1dba2ed Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 2 Nov 2006 22:07:10 -0800 Subject: [PATCH] edac_mc: fix error handling Call sysdev_class_unregister() on failure in edac_sysfs_memctrl_setup() and decrease identation level for clear logic. Acked-by: Doug Thompson Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/edac/edac_mc.c | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 4bde30bb3be7..75e9e38330ff 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -230,34 +230,43 @@ static struct kobj_type ktype_memctrl = { */ static int edac_sysfs_memctrl_setup(void) { - int err=0; + int err = 0; debugf1("%s()\n", __func__); /* create the /sys/devices/system/edac directory */ err = sysdev_class_register(&edac_class); - if (!err) { - /* Init the MC's kobject */ - memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); - edac_memctrl_kobj.parent = &edac_class.kset.kobj; - edac_memctrl_kobj.ktype = &ktype_memctrl; + if (err) { + debugf1("%s() error=%d\n", __func__, err); + return err; + } - /* generate sysfs "..../edac/mc" */ - err = kobject_set_name(&edac_memctrl_kobj,"mc"); + /* Init the MC's kobject */ + memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj)); + edac_memctrl_kobj.parent = &edac_class.kset.kobj; + edac_memctrl_kobj.ktype = &ktype_memctrl; - if (!err) { - /* FIXME: maybe new sysdev_create_subdir() */ - err = kobject_register(&edac_memctrl_kobj); + /* generate sysfs "..../edac/mc" */ + err = kobject_set_name(&edac_memctrl_kobj,"mc"); - if (err) - debugf1("Failed to register '.../edac/mc'\n"); - else - debugf1("Registered '.../edac/mc' kobject\n"); - } - } else - debugf1("%s() error=%d\n", __func__, err); + if (err) + goto fail; + + /* FIXME: maybe new sysdev_create_subdir() */ + err = kobject_register(&edac_memctrl_kobj); + + if (err) { + debugf1("Failed to register '.../edac/mc'\n"); + goto fail; + } + debugf1("Registered '.../edac/mc' kobject\n"); + + return 0; + +fail: + sysdev_class_unregister(&edac_class); return err; } -- cgit v1.2.3 From d13adb604693374c5fce47cd1a2017bcf3178eae Mon Sep 17 00:00:00 2001 From: Yvan Seth Date: Thu, 2 Nov 2006 22:07:13 -0800 Subject: [PATCH] ipmi_si_intf.c sets bad class_mask with PCI_DEVICE_CLASS Taken from http://bugzilla.kernel.org/show_bug.cgi?id=7439 It looks like device registration in drivers/char/ipmi/ipmi_si_intf.c was cleaned up and a small error was made when setting the class_mask. The fix is simple as the correct mask value is defined in the code but is not used. Acked-by: Corey Minyard Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index e5cfb1fa47d1..157fa81a264f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1867,7 +1867,7 @@ static int ipmi_pci_resume(struct pci_dev *pdev) static struct pci_device_id ipmi_pci_devices[] = { { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, - { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE) } + { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) } }; MODULE_DEVICE_TABLE(pci, ipmi_pci_devices); -- cgit v1.2.3 From d3e5a938e7ed718f6d191e8b6b176fcfeb88a294 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 2 Nov 2006 22:07:20 -0800 Subject: [PATCH] spi section fix WARNING: vmlinux - Section mismatch: reference to .init.text:spi_register_board_info from __ksymtab_gpl between '__ksymtab_spi_register_board_info' (at offset 0xc032f7d0) and '__ksymtab_spi_alloc_master' Fix this by removing the export. Acked-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 146298ad7371..c3c0626f550b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -281,7 +281,6 @@ spi_register_board_info(struct spi_board_info const *info, unsigned n) up(&board_lock); return 0; } -EXPORT_SYMBOL_GPL(spi_register_board_info); /* FIXME someone should add support for a __setup("spi", ...) that * creates board info from kernel command lines -- cgit v1.2.3 From 1f604c4bc078213aa1c4576efa0e8dad98522fa7 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Thu, 2 Nov 2006 22:07:25 -0800 Subject: [PATCH] drivers/isdn/hysdn/hysdn_sched.c: sleep after taking spinlock fix spin_lock_irq{save,restore} is incorrectly called here (the function can sleep after acquring the lock). done the necessary corrections and removed unwanted cli/sti. Signed-off-by: Amol Lad Signed-off-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hysdn/hysdn_sched.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c index 1fadf0133e9b..18758772b744 100644 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -155,21 +155,17 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1); - spin_lock_irqsave(&card->hysdn_lock, flags); while (card->async_busy) { - sti(); if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg delayed"); msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); + if (!--cnt) return (-ERR_ASYNC_TIME); /* timed out */ - } - cli(); } /* wait for buffer to become free */ + spin_lock_irqsave(&card->hysdn_lock, flags); strcpy(card->async_data, line); card->async_len = strlen(line) + 1; card->async_channel = chan; @@ -177,30 +173,23 @@ hysdn_tx_cfgline(hysdn_card *card, unsigned char *line, unsigned short chan) /* now queue the task */ schedule_work(&card->irq_queue); - sti(); + spin_unlock_irqrestore(&card->hysdn_lock, flags); if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg data queued"); cnt++; /* short delay */ - cli(); while (card->async_busy) { - sti(); if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg waiting for tx-ready"); msleep_interruptible(20); /* Timeout 20ms */ - if (!--cnt) { - spin_unlock_irqrestore(&card->hysdn_lock, flags); + if (!--cnt) return (-ERR_ASYNC_TIME); /* timed out */ - } - cli(); } /* wait for buffer to become free again */ - spin_unlock_irqrestore(&card->hysdn_lock, flags); - if (card->debug_flags & LOG_SCHED_ASYN) hysdn_addlog(card, "async tx-cfg data send"); -- cgit v1.2.3 From cda5e61a8e0b11826780b8e5a4155683f0557c8b Mon Sep 17 00:00:00 2001 From: Peer Chen Date: Thu, 2 Nov 2006 22:07:27 -0800 Subject: [PATCH] IDE: Add the support of nvidia PATA controllers of MCP67 to amd74xx.c Add support for PATA controllers of MCP67 to amd74xx.c. Signed-off-by: Peer Chen Cc: Jeff Garzik Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/amd74xx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c index 2b0ea8b6608d..753fe0e21456 100644 --- a/drivers/ide/pci/amd74xx.c +++ b/drivers/ide/pci/amd74xx.c @@ -75,6 +75,7 @@ static struct amd_ide_chip { { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 }, + { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, { 0 } }; @@ -491,7 +492,8 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { /* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"), /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"), /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"), - /* 19 */ DECLARE_AMD_DEV("AMD5536"), + /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"), + /* 20 */ DECLARE_AMD_DEV("AMD5536"), }; static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -530,7 +532,8 @@ static struct pci_device_id amd74xx_pci_tbl[] = { { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 }, + { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 }, + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 }, { 0, }, }; MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); -- cgit v1.2.3 From 36da4d869f23bc7d1a70a3185218cb626537845c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 3 Nov 2006 01:01:03 -0800 Subject: [TG3]: Fix 2nd ifup failure on 5752M. This fixes a bug reported in: http://bugzilla.kernel.org/show_bug.cgi?id=7438 tg3_close() turns off the PHY if WoL and ASF are both disabled. On the next tg3_open(), some devices such as the 5752M will not be brought up correctly without a PHY reset early in the reset sequence. The PHY clock is needed for some internal MAC blocks to function correctly. This problem is fixed by always resetting the PHY early in tg3_reset_hw() when it is called from tg3_open() or tg3_resume(). tg3_setup_phy() can then be called later in the sequence without the reset_phy parameter set to 1, since the PHY reset is already done. Update version to 3.68. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8e398499c045..8f059b7968bd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.67" -#define DRV_MODULE_RELDATE "October 18, 2006" +#define DRV_MODULE_VERSION "3.68" +#define DRV_MODULE_RELDATE "November 02, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -6014,7 +6014,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tg3_abort_hw(tp, 1); } - if ((tp->tg3_flags2 & TG3_FLG2_MII_SERDES) && reset_phy) + if (reset_phy) tg3_phy_reset(tp); err = tg3_chip_reset(tp); @@ -6574,7 +6574,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl); } - err = tg3_setup_phy(tp, reset_phy); + err = tg3_setup_phy(tp, 0); if (err) return err; -- cgit v1.2.3 From 1b5135d9b922fdcf46e1e7383167d93d42635fb4 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 3 Nov 2006 17:47:20 +0100 Subject: [PATCH] ehea: Nullpointer dereferencation fix Fix: Must check for nullpointer before dereferencing it - not afterwards. Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_qmr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 3e1862326c88..161559315c0e 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -209,11 +209,11 @@ int ehea_destroy_cq(struct ehea_cq *cq) { u64 adapter_handle, hret; - adapter_handle = cq->adapter->handle; - if (!cq) return 0; + adapter_handle = cq->adapter->handle; + /* deregister all previous registered pages */ hret = ehea_h_free_resource(adapter_handle, cq->fw_handle); if (hret != H_SUCCESS) { -- cgit v1.2.3 From 07fd06b3bc1589e44aefd02eb28700a51b3c9d12 Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 3 Nov 2006 17:47:52 +0100 Subject: [PATCH] ehea: Removed redundant define Removed define H_CB_ALIGNMENT which is already defined in include/asm-powerpc/hvcall.h Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index b40724fc6b74..39ad9f73d1ec 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -39,7 +39,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0034" +#define DRV_VERSION "EHEA_0043" #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -105,9 +105,6 @@ #define EHEA_BCMC_VLANID_ALL 0x01 #define EHEA_BCMC_VLANID_SINGLE 0x00 -/* Use this define to kmallocate pHYP control blocks */ -#define H_CB_ALIGNMENT 4096 - #define EHEA_CACHE_LINE 128 /* Memory Regions */ -- cgit v1.2.3 From a1d261c561522151cb96c75f1dd1a51cf17665cf Mon Sep 17 00:00:00 2001 From: Thomas Klein Date: Fri, 3 Nov 2006 17:48:23 +0100 Subject: [PATCH] ehea: 64K page support fix This patch fixes 64k page support by using PAGE_MASK and appropriate pagesize defines in several places. Signed-off-by: Thomas Klein Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea_ethtool.c | 2 +- drivers/net/ehea/ehea_main.c | 26 +++++++++++++------------- drivers/net/ehea/ehea_phyp.c | 2 +- drivers/net/ehea/ehea_phyp.h | 6 ++++-- drivers/net/ehea/ehea_qmr.c | 13 +++++++------ 5 files changed, 26 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c index 82eb2fb8c75e..9f57c2e78ced 100644 --- a/drivers/net/ehea/ehea_ethtool.c +++ b/drivers/net/ehea/ehea_ethtool.c @@ -238,7 +238,7 @@ static void ehea_get_ethtool_stats(struct net_device *dev, data[i++] = port->port_res[0].swqe_refill_th; data[i++] = port->resets; - cb6 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb6 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb6) { ehea_error("no mem for cb6"); return; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 4538c99733fd..6ad696101418 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -92,7 +92,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) memset(stats, 0, sizeof(*stats)); - cb2 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb2) { ehea_error("no mem for cb2"); goto out; @@ -586,8 +586,8 @@ int ehea_sense_port_attr(struct ehea_port *port) u64 hret; struct hcp_ehea_port_cb0 *cb0; - cb0 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); /* May be called via */ - if (!cb0) { /* ehea_neq_tasklet() */ + cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC); /* May be called via */ + if (!cb0) { /* ehea_neq_tasklet() */ ehea_error("no mem for cb0"); ret = -ENOMEM; goto out; @@ -670,7 +670,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed) u64 hret; int ret = 0; - cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb4) { ehea_error("no mem for cb4"); ret = -ENOMEM; @@ -985,7 +985,7 @@ static int ehea_configure_port(struct ehea_port *port) struct hcp_ehea_port_cb0 *cb0; ret = -ENOMEM; - cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb0) goto out; @@ -1443,7 +1443,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) goto out; } - cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb0) { ehea_error("no mem for cb0"); ret = -ENOMEM; @@ -1501,7 +1501,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable) if ((enable && port->promisc) || (!enable && !port->promisc)) return; - cb7 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); + cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC); if (!cb7) { ehea_error("no mem for cb7"); goto out; @@ -1870,7 +1870,7 @@ static void ehea_vlan_rx_register(struct net_device *dev, port->vgrp = grp; - cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -1899,7 +1899,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) int index; u64 hret; - cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -1935,7 +1935,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) if (port->vgrp) port->vgrp->vlan_devices[vid] = NULL; - cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb1) { ehea_error("no mem for cb1"); goto out; @@ -1968,7 +1968,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp) u64 dummy64 = 0; struct hcp_modify_qp_cb0* cb0; - cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb0) { ret = -ENOMEM; goto out; @@ -2269,7 +2269,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter) u64 hret; int ret; - cb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb) { ret = -ENOMEM; goto out; @@ -2340,7 +2340,7 @@ static int ehea_setup_single_port(struct ehea_port *port, goto out; /* Enable Jumbo frames */ - cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!cb4) { ehea_error("no mem for cb4"); } else { diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c index 0b51a8cea077..0cfc2bc1a27b 100644 --- a/drivers/net/ehea/ehea_phyp.c +++ b/drivers/net/ehea/ehea_phyp.c @@ -506,7 +506,7 @@ u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle, const u8 pagesize, const u8 queue_type, const u64 log_pageaddr, const u64 count) { - if ((count > 1) && (log_pageaddr & 0xfff)) { + if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) { ehea_error("not on pageboundary"); return H_PARAMETER; } diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h index fa51e3b5bb05..919f94b75933 100644 --- a/drivers/net/ehea/ehea_phyp.h +++ b/drivers/net/ehea/ehea_phyp.h @@ -81,14 +81,16 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code) static inline void hcp_epas_ctor(struct h_epas *epas, u64 paddr_kernel, u64 paddr_user) { - epas->kernel.addr = ioremap(paddr_kernel, PAGE_SIZE); + /* To support 64k pages we must round to 64k page boundary */ + epas->kernel.addr = ioremap((paddr_kernel & PAGE_MASK), PAGE_SIZE) + + (paddr_kernel & ~PAGE_MASK); epas->user.addr = paddr_user; } static inline void hcp_epas_dtor(struct h_epas *epas) { if (epas->kernel.addr) - iounmap(epas->kernel.addr); + iounmap((void __iomem*)((u64)epas->kernel.addr & PAGE_MASK)); epas->user.addr = 0; epas->kernel.addr = 0; diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index 161559315c0e..72ef7bde3346 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -512,7 +512,7 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) start = KERNELBASE; end = (u64)high_memory; - nr_pages = (end - start) / PAGE_SIZE; + nr_pages = (end - start) / EHEA_PAGESIZE; pt = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!pt) { @@ -538,9 +538,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) if (nr_pages > 1) { u64 num_pages = min(nr_pages, (u64)512); for (i = 0; i < num_pages; i++) - pt[i] = virt_to_abs((void*)(((u64)start) - + ((k++) * - PAGE_SIZE))); + pt[i] = virt_to_abs((void*)(((u64)start) + + ((k++) * + EHEA_PAGESIZE))); hret = ehea_h_register_rpage_mr(adapter->handle, adapter->mr.handle, 0, @@ -548,8 +548,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) num_pages); nr_pages -= num_pages; } else { - u64 abs_adr = virt_to_abs((void*)(((u64)start) - + (k * PAGE_SIZE))); + u64 abs_adr = virt_to_abs((void*)(((u64)start) + + (k * EHEA_PAGESIZE))); + hret = ehea_h_register_rpage_mr(adapter->handle, adapter->mr.handle, 0, 0, abs_adr,1); -- cgit v1.2.3 From a81c52a81d6dbe6a36bce18112da04f20b175192 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 1 Nov 2006 21:18:58 -0800 Subject: [PATCH] Kconfig: remove redundant NETDEVICES depends drivers/net/Kconfig says: # All the following symbols are dependent on NETDEVICES - do not repeat # that for each of the symbols. so remove duplicate 'depends' uses of NETDEVICES. Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 28c17d1ca5cb..9cb3ca5806fc 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -486,7 +486,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM config MIPS_SIM_NET tristate "MIPS simulator Network device (EXPERIMENTAL)" - depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL + depends on MIPS_SIM && EXPERIMENTAL help The MIPSNET device is a simple Ethernet network device which is emulated by the MIPS Simulator. @@ -2467,7 +2467,7 @@ config ISERIES_VETH config RIONET tristate "RapidIO Ethernet over messaging driver support" - depends on NETDEVICES && RAPIDIO + depends on RAPIDIO config RIONET_TX_SIZE int "Number of outbound queue entries" -- cgit v1.2.3 From 18a61e4adbc4dbe209e0d154df5cd37ce17dc314 Mon Sep 17 00:00:00 2001 From: Ankita Garg Date: Sun, 5 Nov 2006 23:52:07 -0800 Subject: [PATCH] Fix for LKDTM MEM_SWAPOUT crashpoint The MEM_SWAPOUT crashpoint in LKDTM could be broken as some compilers inline the call to shrink_page_list() and symbol lookup for this function name fails. Replacing it with the function shrink_inactive_list(), which is the only function calling shrink_page_list(). Signed-off-by: Ankita Garg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/lkdtm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 46a9c35943bd..db9d7df75ae0 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c @@ -157,8 +157,8 @@ void jp_ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) struct scan_control; -unsigned long jp_shrink_page_list(struct list_head *page_list, - struct scan_control *sc) +unsigned long jp_shrink_inactive_list(unsigned long max_scan, + struct zone *zone, struct scan_control *sc) { lkdtm_handler(); jprobe_return(); @@ -297,8 +297,8 @@ int lkdtm_module_init(void) lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block; break; case MEM_SWAPOUT: - lkdtm.kp.symbol_name = "shrink_page_list"; - lkdtm.entry = (kprobe_opcode_t*) jp_shrink_page_list; + lkdtm.kp.symbol_name = "shrink_inactive_list"; + lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list; break; case TIMERADD: lkdtm.kp.symbol_name = "hrtimer_start"; -- cgit v1.2.3 From e5b9a335fd2180c6db1bcc4b24e83aff7481ebe3 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Sun, 5 Nov 2006 23:52:08 -0800 Subject: [PATCH] isdn/gigaset: convert warning message Make the failed-to-allocate-skb warning a non-debug message. Signed-off-by: Tilman Schmidt Cc: Hansjoerg Lipp Cc: Karsten Keil Cc: Kai Germaschewski Cc: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/gigaset/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index d8d256dadddf..5800beeebb85 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -616,7 +616,7 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, } else if ((bcs->skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL) skb_reserve(bcs->skb, HW_HDR_LEN); else { - gig_dbg(DEBUG_INIT, "could not allocate skb\n"); + warn("could not allocate skb\n"); bcs->inputstate |= INS_skip_frame; } -- cgit v1.2.3 From e78181feb0b94fb6afeaef3b28d4f5df1b847c98 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 6 Nov 2006 23:17:20 +0100 Subject: [PATCH] b44: change comment about irq mask register Through some experimentation with the similarly built bcm43xx I came to the conclusion that if the hw/firmware sets a bit in the interrupt register, an interrupt will only be raised if that bit is included in the interrupt mask. Hence, the interrupt mask is more like an interrupt control mask. This patch changes the comment to reflect that. Signed-off-by: Johannes Berg Signed-off-by: Jeff Garzik --- drivers/net/b44.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 1ec217433b4c..474a4e3438db 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -908,8 +908,9 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id) istat = br32(bp, B44_ISTAT); imask = br32(bp, B44_IMASK); - /* ??? What the fuck is the purpose of the interrupt mask - * ??? register if we have to mask it out by hand anyways? + /* The interrupt mask register controls which interrupt bits + * will actually raise an interrupt to the CPU when set by hw/firmware, + * but doesn't mask off the bits. */ istat &= imask; if (istat) { -- cgit v1.2.3 From edd106fc8ac1826dbe231b70ce0762db24133e5c Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Mon, 6 Nov 2006 08:57:12 -0800 Subject: [PATCH] e1000: Fix regression: garbled stats and irq allocation during swsusp e1000: Fix suspend/resume powerup and irq allocation From: Auke Kok After 7.0.33/2.6.16, e1000 suspend/resume left the user with an enabled device showing garbled statistics and undetermined irq allocation state, where `ifconfig eth0 down` would display `trying to free already freed irq`. Explicitly free and allocate irq as well as powerup the PHY during resume fixes when needed. Signed-off-by: Auke Kok Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 8d04752777a8..726ec5e88ab2 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -4800,6 +4800,9 @@ e1000_suspend(struct pci_dev *pdev, pm_message_t state) if (adapter->hw.phy_type == e1000_phy_igp_3) e1000_phy_powerdown_workaround(&adapter->hw); + if (netif_running(netdev)) + e1000_free_irq(adapter); + /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ e1000_release_hw_control(adapter); @@ -4830,6 +4833,10 @@ e1000_resume(struct pci_dev *pdev) pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); + if (netif_running(netdev) && (err = e1000_request_irq(adapter))) + return err; + + e1000_power_up_phy(adapter); e1000_reset(adapter); E1000_WRITE_REG(&adapter->hw, WUS, ~0); -- cgit v1.2.3 From 3b6a792f6ace33584897d1af08630c9acc0ce221 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 6 Nov 2006 14:34:48 -0800 Subject: [NET]: kconfig, correct traffic shaper As Patrick McHardy suggested, Traffic Shaper is now obsolete and alternative to it is no longer CBQ, since its problems with virtual devices, alter Kconfig text to reflect this -- put a link to the traffic schedulers as a whole. Signed-off-by: Jiri Slaby Acked-by: Patrick McHardy Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/Kconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9cb3ca5806fc..6e863aa9894c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2833,7 +2833,7 @@ config NET_FC "SCSI generic support". config SHAPER - tristate "Traffic Shaper (EXPERIMENTAL)" + tristate "Traffic Shaper (OBSOLETE)" depends on EXPERIMENTAL ---help--- The traffic shaper is a virtual network device that allows you to @@ -2842,9 +2842,9 @@ config SHAPER these virtual devices. See for more information. - An alternative to this traffic shaper is the experimental - Class-Based Queuing (CBQ) scheduling support which you get if you - say Y to "QoS and/or fair queuing" above. + An alternative to this traffic shaper are traffic schedulers which + you'll get if you say Y to "QoS and/or fair queuing" in + "Networking options". To compile this driver as a module, choose M here: the module will be called shaper. If unsure, say N. -- cgit v1.2.3 From af2c6a4aaa2253f1e29df8fb59a3d92174d30a33 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Tue, 7 Nov 2006 14:57:51 -0800 Subject: [TG3]: Fix array overrun in tg3_read_partno(). Use proper upper limits for the loops and check for all error conditions. The problem was noticed by Adrian Bunk. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8f059b7968bd..06e4f77b0988 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -10212,7 +10212,7 @@ skip_phy_reset: static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[256]; - int i; + unsigned int i; u32 magic; if (tg3_nvram_read_swab(tp, 0x0, &magic)) @@ -10258,9 +10258,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } /* Now parse and find the part number. */ - for (i = 0; i < 256; ) { + for (i = 0; i < 254; ) { unsigned char val = vpd_data[i]; - int block_end; + unsigned int block_end; if (val == 0x82 || val == 0x91) { i = (i + 3 + @@ -10276,21 +10276,26 @@ static void __devinit tg3_read_partno(struct tg3 *tp) (vpd_data[i + 1] + (vpd_data[i + 2] << 8))); i += 3; - while (i < block_end) { + + if (block_end > 256) + goto out_not_found; + + while (i < (block_end - 2)) { if (vpd_data[i + 0] == 'P' && vpd_data[i + 1] == 'N') { int partno_len = vpd_data[i + 2]; - if (partno_len > 24) + i += 3; + if (partno_len > 24 || (partno_len + i) > 256) goto out_not_found; memcpy(tp->board_part_number, - &vpd_data[i + 3], - partno_len); + &vpd_data[i], partno_len); /* Success. */ return; } + i += 3 + vpd_data[i + 2]; } /* Part number not found. */ -- cgit v1.2.3 From ecac598bcd1f151ee4760489bded625c147fb366 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Mon, 6 Nov 2006 09:45:31 -0600 Subject: [PATCH] bcm43xx: Drain TX status before starting IRQs Drain the Microcode TX-status-FIFO before we enable IRQs. This is required, because the FIFO may still have entries left from a previous run. Those would immediately fire after enabling IRQs and would lead to an oops in the DMA TXstatus handling code. Signed-off-by: Michael Buesch Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 65edb56107fd..62c2ff8dfb9f 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -1463,6 +1463,23 @@ static void handle_irq_transmit_status(struct bcm43xx_private *bcm) } } +static void drain_txstatus_queue(struct bcm43xx_private *bcm) +{ + u32 dummy; + + if (bcm->current_core->rev < 5) + return; + /* Read all entries from the microcode TXstatus FIFO + * and throw them away. + */ + while (1) { + dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); + if (!dummy) + break; + dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); + } +} + static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) { bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); @@ -3532,6 +3549,7 @@ int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); bcm43xx_security_init(bcm); + drain_txstatus_queue(bcm); ieee80211softmac_start(bcm->net_dev); /* Let's go! Be careful after enabling the IRQs. -- cgit v1.2.3 From 3406118cd34762a7bf6b1a4f1095f9ea7576a354 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 6 Nov 2006 09:48:48 -0600 Subject: [PATCH] bcm43xx: Add error checking in bcm43xx_sprom_write() The Coverity checker noted that these "if (err)"'s couldn't ever be true. It seems the intention was to check the return values of the bcm43xx_pci_write_config32()'s? Signed-off-by: Adrian Bunk Signed-off-by: Larry Finger Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 62c2ff8dfb9f..a1b783813d8e 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -746,7 +746,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) if (err) goto err_ctlreg; spromctl |= 0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); if (err) goto err_ctlreg; /* We must burn lots of CPU cycles here, but that does not @@ -768,7 +768,7 @@ int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) mdelay(20); } spromctl &= ~0x10; /* SPROM WRITE enable. */ - bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); + err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); if (err) goto err_ctlreg; mdelay(500); -- cgit v1.2.3 From 68ff6e8e0e203580ecb118319b5a3b53962edf5a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 8 Nov 2006 07:46:02 -0500 Subject: [libata] sata_via: fix obvious typo Spotted by Martin Devera. Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index f4455a1efe2d..1c7f19aecc25 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -230,7 +230,7 @@ static int vt6420_prereset(struct ata_port *ap) int online; /* don't do any SCR stuff if we're not loading */ - if (!ATA_PFLAG_LOADING) + if (!(ap->pflags & ATA_PFLAG_LOADING)) goto skip_scr; /* Resume phy. This is the old resume sequence from -- cgit v1.2.3 From bfc5ecdf48b529f6a2bd98ba26bfac39ca8cd8a5 Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Wed, 8 Nov 2006 17:44:42 -0800 Subject: [PATCH] dm: fix find_device race There is a race between dev_create() and find_device(). If the mdptr has not yet been stored against a device, find_device() needs to behave as though no device was found. It already returns NULL, but there is a dm_put() missing: it must drop the reference dm_get_md() took. The bug was introduced by dm-fix-mapped-device-ref-counting.patch. It manifests itself if another dm ioctl attempts to reference a newly-created device while the device creation ioctl is still running. The consequence is that the device cannot be removed until the machine is rebooted. Certain udev configurations can lead to this happening. Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-ioctl.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d13bb15a8a02..4510ad8f971c 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -606,9 +606,14 @@ static struct hash_cell *__find_device_hash_cell(struct dm_ioctl *param) return __get_name_cell(param->name); md = dm_get_md(huge_decode_dev(param->dev)); - if (md) - mdptr = dm_get_mdptr(md); + if (!md) + goto out; + mdptr = dm_get_mdptr(md); + if (!mdptr) + dm_put(md); + +out: return mdptr; } -- cgit v1.2.3 From d287483d6d7a2d5b313aee155285f89b57d9cd4a Mon Sep 17 00:00:00 2001 From: Alasdair G Kergon Date: Wed, 8 Nov 2006 17:44:43 -0800 Subject: [PATCH] dm: suspend: fix error path If the device is already suspended, just return the error and skip the code that would incorrectly wipe md->suspended_bdev. (This isn't currently a problem because existing code avoids calling this function if the device is already suspended.) Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm.c b/drivers/md/dm.c index b5764a86c8b5..fc4f743f3b53 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1285,7 +1285,7 @@ int dm_suspend(struct mapped_device *md, int do_lockfs) down(&md->suspend_lock); if (dm_suspended(md)) - goto out; + goto out_unlock; map = dm_get_table(md); @@ -1361,6 +1361,8 @@ out: } dm_table_put(map); + +out_unlock: up(&md->suspend_lock); return r; } -- cgit v1.2.3 From 5d55fdf94998db1df9ee7f1def8806bfd0e5ff73 Mon Sep 17 00:00:00 2001 From: Jonathan E Brassow Date: Wed, 8 Nov 2006 17:44:43 -0800 Subject: [PATCH] dm: multipath: fix rr_add_path order When adding paths to the round-robin path selector, their order gets inverted, which is not desirable. Fix by replacing list_add() with list_add_tail(). Signed-off-by: Jonathan E Brassow Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-round-robin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c index c5a16c550122..6f9fcd4db9b5 100644 --- a/drivers/md/dm-round-robin.c +++ b/drivers/md/dm-round-robin.c @@ -136,7 +136,7 @@ static int rr_add_path(struct path_selector *ps, struct path *path, path->pscontext = pi; - list_add(&pi->list, &s->valid_paths); + list_add_tail(&pi->list, &s->valid_paths); return 0; } -- cgit v1.2.3 From 33184048dc4f9d5550d3b6a88c8e0ff92033eb6e Mon Sep 17 00:00:00 2001 From: Jonathan E Brassow Date: Wed, 8 Nov 2006 17:44:44 -0800 Subject: [PATCH] dm: raid1: fix waiting for io on suspend All device-mapper targets must complete outstanding I/O before suspending. The mirror target generates I/O in its recovery phase and fails to wait for it. It needs to be tracked so we can ensure that it has completed before we suspend. [akpm@osdl.org: cleanup] Signed-off-by: Jonathan E Brassow Signed-off-by: Alasdair G Kergon Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/dm-raid1.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 659224cb7c53..48a653b3f518 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -24,6 +24,7 @@ static struct workqueue_struct *_kmirrord_wq; static struct work_struct _kmirrord_work; +static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); static inline void wake(void) { @@ -83,6 +84,7 @@ struct region_hash { struct list_head *buckets; spinlock_t region_lock; + atomic_t recovery_in_flight; struct semaphore recovery_count; struct list_head clean_regions; struct list_head quiesced_regions; @@ -191,6 +193,7 @@ static int rh_init(struct region_hash *rh, struct mirror_set *ms, spin_lock_init(&rh->region_lock); sema_init(&rh->recovery_count, 0); + atomic_set(&rh->recovery_in_flight, 0); INIT_LIST_HEAD(&rh->clean_regions); INIT_LIST_HEAD(&rh->quiesced_regions); INIT_LIST_HEAD(&rh->recovered_regions); @@ -382,6 +385,8 @@ static void rh_update_states(struct region_hash *rh) rh->log->type->clear_region(rh->log, reg->key); rh->log->type->complete_resync_work(rh->log, reg->key, 1); dispatch_bios(rh->ms, ®->delayed_bios); + if (atomic_dec_and_test(&rh->recovery_in_flight)) + wake_up_all(&_kmirrord_recovery_stopped); up(&rh->recovery_count); mempool_free(reg, rh->region_pool); } @@ -502,11 +507,21 @@ static int __rh_recovery_prepare(struct region_hash *rh) static void rh_recovery_prepare(struct region_hash *rh) { - while (!down_trylock(&rh->recovery_count)) + /* Extra reference to avoid race with rh_stop_recovery */ + atomic_inc(&rh->recovery_in_flight); + + while (!down_trylock(&rh->recovery_count)) { + atomic_inc(&rh->recovery_in_flight); if (__rh_recovery_prepare(rh) <= 0) { + atomic_dec(&rh->recovery_in_flight); up(&rh->recovery_count); break; } + } + + /* Drop the extra reference */ + if (atomic_dec_and_test(&rh->recovery_in_flight)) + wake_up_all(&_kmirrord_recovery_stopped); } /* @@ -1177,6 +1192,11 @@ static void mirror_postsuspend(struct dm_target *ti) struct dirty_log *log = ms->rh.log; rh_stop_recovery(&ms->rh); + + /* Wait for all I/O we generated to complete */ + wait_event(_kmirrord_recovery_stopped, + !atomic_read(&ms->rh.recovery_in_flight)); + if (log->type->suspend && log->type->suspend(log)) /* FIXME: need better error handling */ DMWARN("log suspend failed"); -- cgit v1.2.3 From b196872cd65a06ad65853c4513e0d0f24452d32e Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Nov 2006 17:44:45 -0800 Subject: [PATCH] drivers/telephony/ixj: fix an array overrun The Coverity checker noted that in drivers/telephony/ixj.c:ixj_build_filter_cadence(), filter_en[4] or filter_en[5] could be written to. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/telephony/ixj.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index fbea4541c234..8d69bcdc29c9 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -1295,7 +1295,7 @@ typedef struct { Proc_Info_Type Info_write; unsigned short frame_count; unsigned int filter_hist[4]; - unsigned char filter_en[4]; + unsigned char filter_en[6]; unsigned short proc_load; unsigned long framesread; unsigned long frameswritten; -- cgit v1.2.3 From 2f4713036114dd13d1f4fe433b7f236250b65f5a Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 8 Nov 2006 17:44:47 -0800 Subject: [PATCH] md: change ONLINE/OFFLINE events to a single CHANGE event It turns out that CHANGE is preferred to ONLINE/OFFLINE for various reasons (not least of which being that udev understands it already). So remove the recently added KOBJ_OFFLINE (no-one is likely to care anyway) and change the ONLINE to a CHANGE event Cc: Kay Sievers Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index d11135604403..ae50a2419cc6 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3200,7 +3200,7 @@ static int do_md_run(mddev_t * mddev) mddev->changed = 1; md_new_event(mddev); - kobject_uevent(&mddev->gendisk->kobj, KOBJ_ONLINE); + kobject_uevent(&mddev->gendisk->kobj, KOBJ_CHANGE); return 0; } @@ -3314,7 +3314,6 @@ static int do_md_stop(mddev_t * mddev, int mode) module_put(mddev->pers->owner); mddev->pers = NULL; - kobject_uevent(&mddev->gendisk->kobj, KOBJ_OFFLINE); if (mddev->ro) mddev->ro = 0; } -- cgit v1.2.3 From 0692c6b1cf5537b190f90fb5903f1af89a41b0a8 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 8 Nov 2006 17:44:48 -0800 Subject: [PATCH] md: fix sizing problem with raid5-reshape and CONFIG_LBD=n I forgot to has the size-in-blocks to (loff_t) before shifting up to a size-in-bytes. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e14f45780720..69c3e201fa3b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3659,7 +3659,7 @@ static void end_reshape(raid5_conf_t *conf) bdev = bdget_disk(conf->mddev->gendisk, 0); if (bdev) { mutex_lock(&bdev->bd_inode->i_mutex); - i_size_write(bdev->bd_inode, conf->mddev->array_size << 10); + i_size_write(bdev->bd_inode, (loff_t)conf->mddev->array_size << 10); mutex_unlock(&bdev->bd_inode->i_mutex); bdput(bdev); } -- cgit v1.2.3 From 4b438a23fb05b6566393f9f0a3987ea3dcc1c0c4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 8 Nov 2006 17:44:48 -0800 Subject: [PATCH] md: do not freeze md threads for suspend If there's a swap file on a software RAID, it should be possible to use this file for saving the swsusp's suspend image. Also, this file should be available to the memory management subsystem when memory is being freed before the suspend image is created. For the above reasons it seems that md_threads should not be frozen during the suspend and the appended patch makes this happen, but then there is the question if they don't cause any data to be written to disks after the suspend image has been created, provided that all filesystems are frozen at that time. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index ae50a2419cc6..8cbf9c9df1c3 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4486,6 +4486,7 @@ static int md_thread(void * arg) * many dirty RAID5 blocks. */ + current->flags |= PF_NOFREEZE; allow_signal(SIGKILL); while (!kthread_should_stop()) { @@ -4502,7 +4503,6 @@ static int md_thread(void * arg) test_bit(THREAD_WAKEUP, &thread->flags) || kthread_should_stop(), thread->timeout); - try_to_freeze(); clear_bit(THREAD_WAKEUP, &thread->flags); -- cgit v1.2.3 From f3ce6a0ead8c557e9acdc733addd23cbc206c7e3 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 8 Nov 2006 17:44:52 -0800 Subject: [PATCH] IPMI: Clean up the waiting message queue properly on unload A wrong function was being used to free a list; this fixes the problem. Otherwise, an oops at unload time was possible. But not likely, since you can't have any users when you unload the modules and it is very hard to get messages into this queue without users. Signed-off-by: Corey Minyard Cc: Patrick Schoeller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 34a4fd13fa81..e55a0d276729 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -376,13 +376,23 @@ static void free_recv_msg_list(struct list_head *q) } } +static void free_smi_msg_list(struct list_head *q) +{ + struct ipmi_smi_msg *msg, *msg2; + + list_for_each_entry_safe(msg, msg2, q, link) { + list_del(&msg->link); + ipmi_free_smi_msg(msg); + } +} + static void clean_up_interface_data(ipmi_smi_t intf) { int i; struct cmd_rcvr *rcvr, *rcvr2; struct list_head list; - free_recv_msg_list(&intf->waiting_msgs); + free_smi_msg_list(&intf->waiting_msgs); free_recv_msg_list(&intf->waiting_events); /* Wholesale remove all the entries from the list in the -- cgit v1.2.3 From 46d52b09fa6a2d1e313cb75ca352d6f466e67bd1 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Wed, 8 Nov 2006 17:44:55 -0800 Subject: [PATCH] IPMI: retry messages on certain error returns Some more errors from the IPMI send message command are retryable, but are not being retried by the IPMI code. Make sure they get retried. Signed-off-by: Corey Minyard Cc: Frederic Lelievre Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 4 +++- include/linux/ipmi_msgdefs.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index e55a0d276729..0b07ca1b71fa 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -3242,7 +3242,9 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, report the error immediately. */ if ((msg->rsp_size >= 3) && (msg->rsp[2] != 0) && (msg->rsp[2] != IPMI_NODE_BUSY_ERR) - && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR)) + && (msg->rsp[2] != IPMI_LOST_ARBITRATION_ERR) + && (msg->rsp[2] != IPMI_BUS_ERR) + && (msg->rsp[2] != IPMI_NAK_ON_WRITE_ERR)) { int chan = msg->rsp[3] & 0xf; diff --git a/include/linux/ipmi_msgdefs.h b/include/linux/ipmi_msgdefs.h index 22f5e2afda4f..4d04d8b58a0a 100644 --- a/include/linux/ipmi_msgdefs.h +++ b/include/linux/ipmi_msgdefs.h @@ -75,6 +75,8 @@ #define IPMI_INVALID_COMMAND_ERR 0xc1 #define IPMI_ERR_MSG_TRUNCATED 0xc6 #define IPMI_LOST_ARBITRATION_ERR 0x81 +#define IPMI_BUS_ERR 0x82 +#define IPMI_NAK_ON_WRITE_ERR 0x83 #define IPMI_ERR_UNSPECIFIED 0xff #define IPMI_CHANNEL_PROTOCOL_IPMB 1 -- cgit v1.2.3 From 64d9fe6973a9348e5211f3cc9f04b899329caeb4 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 8 Nov 2006 17:44:56 -0800 Subject: [PATCH] ipmi_si_intf.c: fix "&& 0xff" typos Signed-off-by: Alexey Dobriyan Acked-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 157fa81a264f..abc5149e30e8 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1211,7 +1211,7 @@ static void intf_mem_outb(struct si_sm_io *io, unsigned int offset, static unsigned char intf_mem_inw(struct si_sm_io *io, unsigned int offset) { return (readw((io->addr)+(offset * io->regspacing)) >> io->regshift) - && 0xff; + & 0xff; } static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, @@ -1223,7 +1223,7 @@ static void intf_mem_outw(struct si_sm_io *io, unsigned int offset, static unsigned char intf_mem_inl(struct si_sm_io *io, unsigned int offset) { return (readl((io->addr)+(offset * io->regspacing)) >> io->regshift) - && 0xff; + & 0xff; } static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, @@ -1236,7 +1236,7 @@ static void intf_mem_outl(struct si_sm_io *io, unsigned int offset, static unsigned char mem_inq(struct si_sm_io *io, unsigned int offset) { return (readq((io->addr)+(offset * io->regspacing)) >> io->regshift) - && 0xff; + & 0xff; } static void mem_outq(struct si_sm_io *io, unsigned int offset, -- cgit v1.2.3 From ec68307cc5a8dc499e48693843bb42f6b6028458 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 8 Nov 2006 17:44:57 -0800 Subject: [PATCH] htirq: refactor so we only have one function that writes to the chip This refactoring actually optimizes the code a little by caching the value that we think the device is programmed with instead of reading it back from the hardware. Which simplifies the code a little and should speed things up a bit. This patch introduces the concept of a ht_irq_msg and modifies the architecture read/write routines to update this code. There is a minor consistency fix here as well as x86_64 forgot to initialize the htirq as masked. Signed-off-by: Eric W. Biederman Cc: Andi Kleen Acked-by: Bryan O'Sullivan Cc: Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/io_apic.c | 26 ++++++++-------- arch/x86_64/kernel/io_apic.c | 31 +++++++++---------- drivers/pci/htirq.c | 72 +++++++++++++++----------------------------- include/linux/htirq.h | 11 ++++--- 4 files changed, 58 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 507983c513c3..ad84bc2802a6 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -2624,18 +2624,16 @@ void arch_teardown_msi_irq(unsigned int irq) static void target_ht_irq(unsigned int irq, unsigned int dest) { - u32 low, high; - low = read_ht_irq_low(irq); - high = read_ht_irq_high(irq); + struct ht_irq_msg msg; + fetch_ht_irq_msg(irq, &msg); - low &= ~(HT_IRQ_LOW_DEST_ID_MASK); - high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); + msg.address_lo &= ~(HT_IRQ_LOW_DEST_ID_MASK); + msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); - low |= HT_IRQ_LOW_DEST_ID(dest); - high |= HT_IRQ_HIGH_DEST_ID(dest); + msg.address_lo |= HT_IRQ_LOW_DEST_ID(dest); + msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); - write_ht_irq_low(irq, low); - write_ht_irq_high(irq, high); + write_ht_irq_msg(irq, &msg); } static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) @@ -2673,7 +2671,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) vector = assign_irq_vector(irq); if (vector >= 0) { - u32 low, high; + struct ht_irq_msg msg; unsigned dest; cpumask_t tmp; @@ -2681,9 +2679,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) cpu_set(vector >> 8, tmp); dest = cpu_mask_to_apicid(tmp); - high = HT_IRQ_HIGH_DEST_ID(dest); + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); - low = HT_IRQ_LOW_BASE | + msg.address_lo = + HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(dest) | HT_IRQ_LOW_VECTOR(vector) | ((INT_DEST_MODE == 0) ? @@ -2695,8 +2694,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) HT_IRQ_LOW_MT_ARBITRATED) | HT_IRQ_LOW_IRQ_MASKED; - write_ht_irq_low(irq, low); - write_ht_irq_high(irq, high); + write_ht_irq_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &ht_irq_chip, handle_edge_irq, "edge"); diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index 3b8f9c68ad3c..41bfc49301ad 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c @@ -1955,18 +1955,16 @@ void arch_teardown_msi_irq(unsigned int irq) static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) { - u32 low, high; - low = read_ht_irq_low(irq); - high = read_ht_irq_high(irq); + struct ht_irq_msg msg; + fetch_ht_irq_msg(irq, &msg); - low &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); - high &= ~(HT_IRQ_HIGH_DEST_ID_MASK); + msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); + msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); - low |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); - high |= HT_IRQ_HIGH_DEST_ID(dest); + msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); + msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); - write_ht_irq_low(irq, low); - write_ht_irq_high(irq, high); + write_ht_irq_msg(irq, &msg); } static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) @@ -1987,7 +1985,7 @@ static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask) dest = cpu_mask_to_apicid(tmp); - target_ht_irq(irq, dest, vector & 0xff); + target_ht_irq(irq, dest, vector); set_native_irq_info(irq, mask); } #endif @@ -2010,14 +2008,15 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) vector = assign_irq_vector(irq, TARGET_CPUS, &tmp); if (vector >= 0) { - u32 low, high; + struct ht_irq_msg msg; unsigned dest; dest = cpu_mask_to_apicid(tmp); - high = HT_IRQ_HIGH_DEST_ID(dest); + msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); - low = HT_IRQ_LOW_BASE | + msg.address_lo = + HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(dest) | HT_IRQ_LOW_VECTOR(vector) | ((INT_DEST_MODE == 0) ? @@ -2026,10 +2025,10 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) HT_IRQ_LOW_RQEOI_EDGE | ((INT_DELIVERY_MODE != dest_LowestPrio) ? HT_IRQ_LOW_MT_FIXED : - HT_IRQ_LOW_MT_ARBITRATED); + HT_IRQ_LOW_MT_ARBITRATED) | + HT_IRQ_LOW_IRQ_MASKED; - write_ht_irq_low(irq, low); - write_ht_irq_high(irq, high); + write_ht_irq_msg(irq, &msg); set_irq_chip_and_handler_name(irq, &ht_irq_chip, handle_edge_irq, "edge"); diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 0e27f2404a83..e346fe31f97a 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c @@ -27,82 +27,55 @@ struct ht_irq_cfg { struct pci_dev *dev; unsigned pos; unsigned idx; + struct ht_irq_msg msg; }; -void write_ht_irq_low(unsigned int irq, u32 data) -{ - struct ht_irq_cfg *cfg = get_irq_data(irq); - unsigned long flags; - spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); - spin_unlock_irqrestore(&ht_irq_lock, flags); -} - -void write_ht_irq_high(unsigned int irq, u32 data) -{ - struct ht_irq_cfg *cfg = get_irq_data(irq); - unsigned long flags; - spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); - spin_unlock_irqrestore(&ht_irq_lock, flags); -} -u32 read_ht_irq_low(unsigned int irq) +void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) { struct ht_irq_cfg *cfg = get_irq_data(irq); unsigned long flags; - u32 data; spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); + if (cfg->msg.address_lo != msg->address_lo) { + pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); + pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_lo); + } + if (cfg->msg.address_hi != msg->address_hi) { + pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); + pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); + } spin_unlock_irqrestore(&ht_irq_lock, flags); - return data; + cfg->msg = *msg; } -u32 read_ht_irq_high(unsigned int irq) +void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) { struct ht_irq_cfg *cfg = get_irq_data(irq); - unsigned long flags; - u32 data; - spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); - spin_unlock_irqrestore(&ht_irq_lock, flags); - return data; + *msg = cfg->msg; } void mask_ht_irq(unsigned int irq) { struct ht_irq_cfg *cfg; - unsigned long flags; - u32 data; + struct ht_irq_msg msg; cfg = get_irq_data(irq); - spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); - data |= 1; - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); - spin_unlock_irqrestore(&ht_irq_lock, flags); + msg = cfg->msg; + msg.address_lo |= 1; + write_ht_irq_msg(irq, &msg); } void unmask_ht_irq(unsigned int irq) { struct ht_irq_cfg *cfg; - unsigned long flags; - u32 data; + struct ht_irq_msg msg; cfg = get_irq_data(irq); - spin_lock_irqsave(&ht_irq_lock, flags); - pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx); - pci_read_config_dword(cfg->dev, cfg->pos + 4, &data); - data &= ~1; - pci_write_config_dword(cfg->dev, cfg->pos + 4, data); - spin_unlock_irqrestore(&ht_irq_lock, flags); + msg = cfg->msg; + msg.address_lo &= ~1; + write_ht_irq_msg(irq, &msg); } /** @@ -152,6 +125,9 @@ int ht_create_irq(struct pci_dev *dev, int idx) cfg->dev = dev; cfg->pos = pos; cfg->idx = 0x10 + (idx * 2); + /* Initialize msg to a value that will never match the first write. */ + cfg->msg.address_lo = 0xffffffff; + cfg->msg.address_hi = 0xffffffff; irq = create_irq(); if (irq < 0) { diff --git a/include/linux/htirq.h b/include/linux/htirq.h index 1f15ce279a23..108f0d91e11e 100644 --- a/include/linux/htirq.h +++ b/include/linux/htirq.h @@ -1,11 +1,14 @@ #ifndef LINUX_HTIRQ_H #define LINUX_HTIRQ_H +struct ht_irq_msg { + u32 address_lo; /* low 32 bits of the ht irq message */ + u32 address_hi; /* high 32 bits of the it irq message */ +}; + /* Helper functions.. */ -void write_ht_irq_low(unsigned int irq, u32 data); -void write_ht_irq_high(unsigned int irq, u32 data); -u32 read_ht_irq_low(unsigned int irq); -u32 read_ht_irq_high(unsigned int irq); +void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); +void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg); void mask_ht_irq(unsigned int irq); void unmask_ht_irq(unsigned int irq); -- cgit v1.2.3 From 43539c38cd8edb915d1f0e1f55dcb70638b4cc8e Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Wed, 8 Nov 2006 17:44:57 -0800 Subject: [PATCH] htirq: allow buggy drivers of buggy hardware to write the registers This patch adds a variant of ht_create_irq __ht_create_irq that takes an aditional parameter update that is a function that is called whenever we want to write to a drivers htirq configuration registers. This is needed to support the ipath_iba6110 because it's registers in the proper location are not actually conected to the hardware that controlls interrupt delivery. [bos@serpentine.com: fixes] Signed-off-by: Eric W. Biederman Cc: Andi Kleen Cc: Cc: Roland Dreier Signed-off-by: Bryan O'Sullivan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pci/htirq.c | 29 ++++++++++++++++++++++++----- include/linux/htirq.h | 5 +++++ 2 files changed, 29 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index e346fe31f97a..0a8d1cce9fa0 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c @@ -25,6 +25,8 @@ static DEFINE_SPINLOCK(ht_irq_lock); struct ht_irq_cfg { struct pci_dev *dev; + /* Update callback used to cope with buggy hardware */ + ht_irq_update_t *update; unsigned pos; unsigned idx; struct ht_irq_msg msg; @@ -44,6 +46,8 @@ void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg) pci_write_config_byte(cfg->dev, cfg->pos + 2, cfg->idx + 1); pci_write_config_dword(cfg->dev, cfg->pos + 4, msg->address_hi); } + if (cfg->update) + cfg->update(cfg->dev, irq, msg); spin_unlock_irqrestore(&ht_irq_lock, flags); cfg->msg = *msg; } @@ -79,16 +83,14 @@ void unmask_ht_irq(unsigned int irq) } /** - * ht_create_irq - create an irq and attach it to a device. + * __ht_create_irq - create an irq and attach it to a device. * @dev: The hypertransport device to find the irq capability on. * @idx: Which of the possible irqs to attach to. - * - * ht_create_irq is needs to be called for all hypertransport devices - * that generate irqs. + * @update: Function to be called when changing the htirq message * * The irq number of the new irq or a negative error value is returned. */ -int ht_create_irq(struct pci_dev *dev, int idx) +int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) { struct ht_irq_cfg *cfg; unsigned long flags; @@ -123,6 +125,7 @@ int ht_create_irq(struct pci_dev *dev, int idx) return -ENOMEM; cfg->dev = dev; + cfg->update = update; cfg->pos = pos; cfg->idx = 0x10 + (idx * 2); /* Initialize msg to a value that will never match the first write. */ @@ -144,6 +147,21 @@ int ht_create_irq(struct pci_dev *dev, int idx) return irq; } +/** + * ht_create_irq - create an irq and attach it to a device. + * @dev: The hypertransport device to find the irq capability on. + * @idx: Which of the possible irqs to attach to. + * + * ht_create_irq needs to be called for all hypertransport devices + * that generate irqs. + * + * The irq number of the new irq or a negative error value is returned. + */ +int ht_create_irq(struct pci_dev *dev, int idx) +{ + return __ht_create_irq(dev, idx, NULL); +} + /** * ht_destroy_irq - destroy an irq created with ht_create_irq * @@ -162,5 +180,6 @@ void ht_destroy_irq(unsigned int irq) kfree(cfg); } +EXPORT_SYMBOL(__ht_create_irq); EXPORT_SYMBOL(ht_create_irq); EXPORT_SYMBOL(ht_destroy_irq); diff --git a/include/linux/htirq.h b/include/linux/htirq.h index 108f0d91e11e..c96ea46737d0 100644 --- a/include/linux/htirq.h +++ b/include/linux/htirq.h @@ -15,4 +15,9 @@ void unmask_ht_irq(unsigned int irq); /* The arch hook for getting things started */ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev); +/* For drivers of buggy hardware */ +typedef void (ht_irq_update_t)(struct pci_dev *dev, int irq, + struct ht_irq_msg *msg); +int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update); + #endif /* LINUX_HTIRQ_H */ -- cgit v1.2.3 From 51f65ebccf55121832c265838f93949f898b12ff Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Wed, 8 Nov 2006 17:44:58 -0800 Subject: [PATCH] IB/ipath - program intconfig register using new HT irq hook Eric's changes to the htirq infrastructure require corresponding modifications to the ipath HT driver code so that interrupts are still delivered properly. Signed-off-by: Bryan O'Sullivan Cc: Eric W. Biederman Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/ipath/ipath_driver.c | 17 ++-- drivers/infiniband/hw/ipath/ipath_iba6110.c | 117 ++++++++++++---------------- drivers/infiniband/hw/ipath/ipath_iba6120.c | 8 ++ drivers/infiniband/hw/ipath/ipath_intr.c | 10 +-- drivers/infiniband/hw/ipath/ipath_kernel.h | 4 + 5 files changed, 74 insertions(+), 82 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index b4ffaa7bcbb7..09a13c1fc46a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -304,7 +304,7 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, } addr = pci_resource_start(pdev, 0); len = pci_resource_len(pdev, 0); - ipath_cdbg(VERBOSE, "regbase (0) %llx len %d irq %x, vend %x/%x " + ipath_cdbg(VERBOSE, "regbase (0) %llx len %d pdev->irq %d, vend %x/%x " "driver_data %lx\n", addr, len, pdev->irq, ent->vendor, ent->device, ent->driver_data); @@ -467,15 +467,15 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, * check 0 irq after we return from chip-specific bus setup, since * that can affect this due to setup */ - if (!pdev->irq) + if (!dd->ipath_irq) ipath_dev_err(dd, "irq is 0, BIOS error? Interrupts won't " "work\n"); else { - ret = request_irq(pdev->irq, ipath_intr, IRQF_SHARED, + ret = request_irq(dd->ipath_irq, ipath_intr, IRQF_SHARED, IPATH_DRV_NAME, dd); if (ret) { ipath_dev_err(dd, "Couldn't setup irq handler, " - "irq=%u: %d\n", pdev->irq, ret); + "irq=%d: %d\n", dd->ipath_irq, ret); goto bail_iounmap; } } @@ -637,11 +637,10 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev) * free up port 0 (kernel) rcvhdr, egr bufs, and eventually tid bufs * for all versions of the driver, if they were allocated */ - if (pdev->irq) { - ipath_cdbg(VERBOSE, - "unit %u free_irq of irq %x\n", - dd->ipath_unit, pdev->irq); - free_irq(pdev->irq, dd); + if (dd->ipath_irq) { + ipath_cdbg(VERBOSE, "unit %u free irq %d\n", + dd->ipath_unit, dd->ipath_irq); + dd->ipath_f_free_irq(dd); } else ipath_dbg("irq is 0, not doing free_irq " "for unit %u\n", dd->ipath_unit); diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c index 9e4e8d4c6e20..e57c7a351cb5 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6110.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c @@ -38,6 +38,7 @@ #include #include +#include #include "ipath_kernel.h" #include "ipath_registers.h" @@ -913,49 +914,40 @@ static void slave_or_pri_blk(struct ipath_devdata *dd, struct pci_dev *pdev, } } -static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, - int pos) +static int ipath_ht_intconfig(struct ipath_devdata *dd) { - u32 int_handler_addr_lower; - u32 int_handler_addr_upper; - u64 ihandler; - u32 intvec; + int ret; - /* use indirection register to get the intr handler */ - pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x10); - pci_read_config_dword(pdev, pos + 4, &int_handler_addr_lower); - pci_write_config_byte(pdev, pos + HT_INTR_REG_INDEX, 0x11); - pci_read_config_dword(pdev, pos + 4, &int_handler_addr_upper); + if (dd->ipath_intconfig) { + ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, + dd->ipath_intconfig); /* interrupt address */ + ret = 0; + } else { + ipath_dev_err(dd, "No interrupts enabled, couldn't setup " + "interrupt address\n"); + ret = -EINVAL; + } - ihandler = (u64) int_handler_addr_lower | - ((u64) int_handler_addr_upper << 32); + return ret; +} + +static void ipath_ht_irq_update(struct pci_dev *dev, int irq, + struct ht_irq_msg *msg) +{ + struct ipath_devdata *dd = pci_get_drvdata(dev); + u64 prev_intconfig = dd->ipath_intconfig; + + dd->ipath_intconfig = msg->address_lo; + dd->ipath_intconfig |= ((u64) msg->address_hi) << 32; /* - * kernels with CONFIG_PCI_MSI set the vector in the irq field of - * struct pci_device, so we use that to program the internal - * interrupt register (not config space) with that value. The BIOS - * must still have done the basic MSI setup. - */ - intvec = pdev->irq; - /* - * clear any vector bits there; normally not set but we'll overload - * this for some debug purposes (setting the HTC debug register - * value from software, rather than GPIOs), so it might be set on a - * driver reload. + * If the previous value of dd->ipath_intconfig is zero, we're + * getting configured for the first time, and must not program the + * intconfig register here (it will be programmed later, when the + * hardware is ready). Otherwise, we should. */ - ihandler &= ~0xff0000; - /* x86 vector goes in intrinfo[23:16] */ - ihandler |= intvec << 16; - ipath_cdbg(VERBOSE, "ihandler lower %x, upper %x, intvec %x, " - "interruptconfig %llx\n", int_handler_addr_lower, - int_handler_addr_upper, intvec, - (unsigned long long) ihandler); - - /* can't program yet, so save for interrupt setup */ - dd->ipath_intconfig = ihandler; - /* keep going, so we find link control stuff also */ - - return ihandler != 0; + if (prev_intconfig) + ipath_ht_intconfig(dd); } /** @@ -971,12 +963,19 @@ static int set_int_handler(struct ipath_devdata *dd, struct pci_dev *pdev, static int ipath_setup_ht_config(struct ipath_devdata *dd, struct pci_dev *pdev) { - int pos, ret = 0; - int ihandler = 0; + int pos, ret; + + ret = __ht_create_irq(pdev, 0, ipath_ht_irq_update); + if (ret < 0) { + ipath_dev_err(dd, "Couldn't create interrupt handler: " + "err %d\n", ret); + goto bail; + } + dd->ipath_irq = ret; + ret = 0; /* - * Read the capability info to find the interrupt info, and also - * handle clearing CRC errors in linkctrl register if necessary. We + * Handle clearing CRC errors in linkctrl register if necessary. We * do this early, before we ever enable errors or hardware errors, * mostly to avoid causing the chip to enter freeze mode. */ @@ -1000,17 +999,9 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd, } if (!(cap_type & 0xE0)) slave_or_pri_blk(dd, pdev, pos, cap_type); - else if (cap_type == HT_INTR_DISC_CONFIG) - ihandler = set_int_handler(dd, pdev, pos); } while ((pos = pci_find_next_capability(pdev, pos, PCI_CAP_ID_HT))); - if (!ihandler) { - ipath_dev_err(dd, "Couldn't find interrupt handler in " - "config space\n"); - ret = -ENODEV; - } - bail: return ret; } @@ -1360,25 +1351,6 @@ static void ipath_ht_quiet_serdes(struct ipath_devdata *dd) ipath_write_kreg(dd, dd->ipath_kregs->kr_serdesconfig0, val); } -static int ipath_ht_intconfig(struct ipath_devdata *dd) -{ - int ret; - - if (!dd->ipath_intconfig) { - ipath_dev_err(dd, "No interrupts enabled, couldn't setup " - "interrupt address\n"); - ret = 1; - goto bail; - } - - ipath_write_kreg(dd, dd->ipath_kregs->kr_interruptconfig, - dd->ipath_intconfig); /* interrupt address */ - ret = 0; - -bail: - return ret; -} - /** * ipath_pe_put_tid - write a TID in chip * @dd: the infinipath device @@ -1575,6 +1547,14 @@ static int ipath_ht_get_base_info(struct ipath_portdata *pd, void *kbase) return 0; } +static void ipath_ht_free_irq(struct ipath_devdata *dd) +{ + free_irq(dd->ipath_irq, dd); + ht_destroy_irq(dd->ipath_irq); + dd->ipath_irq = 0; + dd->ipath_intconfig = 0; +} + /** * ipath_init_iba6110_funcs - set up the chip-specific function pointers * @dd: the infinipath device @@ -1598,6 +1578,7 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd) dd->ipath_f_cleanup = ipath_setup_ht_cleanup; dd->ipath_f_setextled = ipath_setup_ht_setextled; dd->ipath_f_get_base_info = ipath_ht_get_base_info; + dd->ipath_f_free_irq = ipath_ht_free_irq; /* * initialize chip-specific variables diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c index a72ab9de386a..6af89683f710 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba6120.c +++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c @@ -851,6 +851,7 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd, int pos, ret; dd->ipath_msi_lo = 0; /* used as a flag during reset processing */ + dd->ipath_irq = pdev->irq; ret = pci_enable_msi(dd->pcidev); if (ret) ipath_dev_err(dd, "pci_enable_msi failed: %d, " @@ -1323,6 +1324,12 @@ done: return 0; } +static void ipath_pe_free_irq(struct ipath_devdata *dd) +{ + free_irq(dd->ipath_irq, dd); + dd->ipath_irq = 0; +} + /** * ipath_init_iba6120_funcs - set up the chip-specific function pointers * @dd: the infinipath device @@ -1349,6 +1356,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd) dd->ipath_f_cleanup = ipath_setup_pe_cleanup; dd->ipath_f_setextled = ipath_setup_pe_setextled; dd->ipath_f_get_base_info = ipath_pe_get_base_info; + dd->ipath_f_free_irq = ipath_pe_free_irq; /* initialize chip-specific variables */ dd->ipath_f_tidtemplate = ipath_pe_tidtemplate; diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c index d9079ee12030..5652a550d442 100644 --- a/drivers/infiniband/hw/ipath/ipath_intr.c +++ b/drivers/infiniband/hw/ipath/ipath_intr.c @@ -710,14 +710,14 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp) * linuxbios development work, and it may happen in * the future again. */ - if (dd->pcidev && dd->pcidev->irq) { + if (dd->pcidev && dd->ipath_irq) { ipath_dev_err(dd, "Now %u unexpected " "interrupts, unregistering " "interrupt handler\n", *unexpectp); - ipath_dbg("free_irq of irq %x\n", - dd->pcidev->irq); - free_irq(dd->pcidev->irq, dd); + ipath_dbg("free_irq of irq %d\n", + dd->ipath_irq); + dd->ipath_f_free_irq(dd); } } if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) { @@ -753,7 +753,7 @@ static void ipath_bad_regread(struct ipath_devdata *dd) if (allbits == 2) { ipath_dev_err(dd, "Still bad interrupt status, " "unregistering interrupt\n"); - free_irq(dd->pcidev->irq, dd); + dd->ipath_f_free_irq(dd); } else if (allbits > 2) { if ((allbits % 10000) == 0) printk("."); diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 06d5020a2f60..986b2125b8f5 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -213,6 +213,8 @@ struct ipath_devdata { void (*ipath_f_setextled)(struct ipath_devdata *, u64, u64); /* fill out chip-specific fields */ int (*ipath_f_get_base_info)(struct ipath_portdata *, void *); + /* free irq */ + void (*ipath_f_free_irq)(struct ipath_devdata *); struct ipath_ibdev *verbs_dev; struct timer_list verbs_timer; /* total dwords sent (summed from counter) */ @@ -328,6 +330,8 @@ struct ipath_devdata { /* so we can rewrite it after a chip reset */ u32 ipath_pcibar1; + /* interrupt number */ + int ipath_irq; /* HT/PCI Vendor ID (here for NodeInfo) */ u16 ipath_vendorid; /* HT/PCI Device ID (here for NodeInfo) */ -- cgit v1.2.3 From 3f048109d9c4f8bb028ccb0d256ab65eb44f5988 Mon Sep 17 00:00:00 2001 From: "malahal@us.ibm.com" Date: Wed, 4 Oct 2006 17:28:37 -0700 Subject: [SCSI] aic94xx SCSI timeout fix The patch updates DDB0 in the aic94xx driver itself. It doesn't supply or use lldd_port_formed field. DDB0 is updated prior to posting notification to libsas layer. Signed-off-by: Malahal Naineni Signed-off-by: James Bottomley --- drivers/scsi/aic94xx/aic94xx_hwi.c | 18 ++++++++++ drivers/scsi/aic94xx/aic94xx_hwi.h | 12 +++++++ drivers/scsi/aic94xx/aic94xx_init.c | 2 -- drivers/scsi/aic94xx/aic94xx_sas.h | 1 + drivers/scsi/aic94xx/aic94xx_scb.c | 72 +++++++++++++++++++++++++++++++++++++ drivers/scsi/aic94xx/aic94xx_seq.c | 5 ++- drivers/scsi/aic94xx/aic94xx_seq.h | 2 +- 7 files changed, 106 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c index 3c2d7a379931..af7e01134364 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.c +++ b/drivers/scsi/aic94xx/aic94xx_hwi.c @@ -112,6 +112,21 @@ static int asd_init_phy(struct asd_phy *phy) return 0; } +static void asd_init_ports(struct asd_ha_struct *asd_ha) +{ + int i; + + spin_lock_init(&asd_ha->asd_ports_lock); + for (i = 0; i < ASD_MAX_PHYS; i++) { + struct asd_port *asd_port = &asd_ha->asd_ports[i]; + + memset(asd_port->sas_addr, 0, SAS_ADDR_SIZE); + memset(asd_port->attached_sas_addr, 0, SAS_ADDR_SIZE); + asd_port->phy_mask = 0; + asd_port->num_phys = 0; + } +} + static int asd_init_phys(struct asd_ha_struct *asd_ha) { u8 i; @@ -121,6 +136,7 @@ static int asd_init_phys(struct asd_ha_struct *asd_ha) struct asd_phy *phy = &asd_ha->phys[i]; phy->phy_desc = &asd_ha->hw_prof.phy_desc[i]; + phy->asd_port = NULL; phy->sas_phy.enabled = 0; phy->sas_phy.id = i; @@ -658,6 +674,8 @@ int asd_init_hw(struct asd_ha_struct *asd_ha) goto Out; } + asd_init_ports(asd_ha); + err = asd_init_scbs(asd_ha); if (err) { asd_printk("couldn't initialize scbs for %s\n", diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h index 7b6aca02cf70..c6c3d18222fa 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.h +++ b/drivers/scsi/aic94xx/aic94xx_hwi.h @@ -193,6 +193,16 @@ struct asd_seq_data { struct asd_ascb **escb_arr; /* array of pointers to escbs */ }; +/* This is an internal port structure. These are used to get accurate + * phy_mask for updating DDB 0. + */ +struct asd_port { + u8 sas_addr[SAS_ADDR_SIZE]; + u8 attached_sas_addr[SAS_ADDR_SIZE]; + u32 phy_mask; + int num_phys; +}; + /* This is the Host Adapter structure. It describes the hardware * SAS adapter. */ @@ -211,6 +221,8 @@ struct asd_ha_struct { struct hw_profile hw_prof; struct asd_phy phys[ASD_MAX_PHYS]; + spinlock_t asd_ports_lock; + struct asd_port asd_ports[ASD_MAX_PHYS]; struct asd_sas_port ports[ASD_MAX_PHYS]; struct dma_pool *scb_pool; diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index a4cc432bbdab..57c5ba4043f2 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -786,8 +786,6 @@ static void asd_remove_driver_attrs(struct device_driver *driver) } static struct sas_domain_function_template aic94xx_transport_functions = { - .lldd_port_formed = asd_update_port_links, - .lldd_dev_found = asd_dev_found, .lldd_dev_gone = asd_dev_gone, diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h b/drivers/scsi/aic94xx/aic94xx_sas.h index 64d231712345..9050e93bfd5e 100644 --- a/drivers/scsi/aic94xx/aic94xx_sas.h +++ b/drivers/scsi/aic94xx/aic94xx_sas.h @@ -733,6 +733,7 @@ struct asd_phy { struct sas_identify_frame *identify_frame; struct asd_dma_tok *id_frm_tok; + struct asd_port *asd_port; u8 frame_rcvd[ASD_EDB_SIZE]; }; diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index 7ee49b51b724..b15caf1c8fa2 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -168,6 +168,70 @@ static inline void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr) } } +static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy) +{ + int i; + struct asd_port *free_port = NULL; + struct asd_port *port; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + unsigned long flags; + + spin_lock_irqsave(&asd_ha->asd_ports_lock, flags); + if (!phy->asd_port) { + for (i = 0; i < ASD_MAX_PHYS; i++) { + port = &asd_ha->asd_ports[i]; + + /* Check for wide port */ + if (port->num_phys > 0 && + memcmp(port->sas_addr, sas_phy->sas_addr, + SAS_ADDR_SIZE) == 0 && + memcmp(port->attached_sas_addr, + sas_phy->attached_sas_addr, + SAS_ADDR_SIZE) == 0) { + break; + } + + /* Find a free port */ + if (port->num_phys == 0 && free_port == NULL) { + free_port = port; + } + } + + /* Use a free port if this doesn't form a wide port */ + if (i >= ASD_MAX_PHYS) { + port = free_port; + BUG_ON(!port); + memcpy(port->sas_addr, sas_phy->sas_addr, + SAS_ADDR_SIZE); + memcpy(port->attached_sas_addr, + sas_phy->attached_sas_addr, + SAS_ADDR_SIZE); + } + port->num_phys++; + port->phy_mask |= (1U << sas_phy->id); + phy->asd_port = port; + } + ASD_DPRINTK("%s: updating phy_mask 0x%x for phy%d\n", + __FUNCTION__, phy->asd_port->phy_mask, sas_phy->id); + asd_update_port_links(asd_ha, phy); + spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags); +} + +static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy) +{ + struct asd_port *port = phy->asd_port; + struct asd_sas_phy *sas_phy = &phy->sas_phy; + unsigned long flags; + + spin_lock_irqsave(&asd_ha->asd_ports_lock, flags); + if (port) { + port->num_phys--; + port->phy_mask &= ~(1U << sas_phy->id); + phy->asd_port = NULL; + } + spin_unlock_irqrestore(&asd_ha->asd_ports_lock, flags); +} + static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, struct done_list_struct *dl, int edb_id, int phy_id) @@ -187,6 +251,7 @@ static inline void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb, asd_get_attached_sas_addr(phy, phy->sas_phy.attached_sas_addr); spin_unlock_irqrestore(&phy->sas_phy.frame_rcvd_lock, flags); asd_dump_frame_rcvd(phy, dl); + asd_form_port(ascb->ha, phy); sas_ha->notify_port_event(&phy->sas_phy, PORTE_BYTES_DMAED); } @@ -197,6 +262,7 @@ static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb, struct asd_ha_struct *asd_ha = ascb->ha; struct sas_ha_struct *sas_ha = &asd_ha->sas_ha; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; + struct asd_phy *phy = &asd_ha->phys[phy_id]; u8 lr_error = dl->status_block[1]; u8 retries_left = dl->status_block[2]; @@ -221,6 +287,7 @@ static inline void asd_link_reset_err_tasklet(struct asd_ascb *ascb, asd_turn_led(asd_ha, phy_id, 0); sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); sas_ha->notify_port_event(sas_phy, PORTE_LINK_RESET_ERR); if (retries_left == 0) { @@ -248,6 +315,8 @@ static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, unsigned long flags; struct sas_ha_struct *sas_ha = &ascb->ha->sas_ha; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; + struct asd_ha_struct *asd_ha = ascb->ha; + struct asd_phy *phy = &asd_ha->phys[phy_id]; u8 reg = dl->status_block[1]; u32 cont = dl->status_block[2] << ((reg & 3)*8); @@ -284,6 +353,7 @@ static inline void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb, phy_id); /* The sequencer disables all phys on that port. * We have to re-enable the phys ourselves. */ + asd_deform_port(asd_ha, phy); sas_ha->notify_port_event(sas_phy, PORTE_HARD_RESET); break; @@ -351,6 +421,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, u8 sb_opcode = dl->status_block[0]; int phy_id = sb_opcode & DL_PHY_MASK; struct asd_sas_phy *sas_phy = sas_ha->sas_phy[phy_id]; + struct asd_phy *phy = &asd_ha->phys[phy_id]; if (edb > 6 || edb < 0) { ASD_DPRINTK("edb is 0x%x! dl->opcode is 0x%x\n", @@ -395,6 +466,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb, asd_turn_led(asd_ha, phy_id, 0); /* the device is gone */ sas_phy_disconnected(sas_phy); + asd_deform_port(asd_ha, phy); sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT); break; case REQ_TASK_ABORT: diff --git a/drivers/scsi/aic94xx/aic94xx_seq.c b/drivers/scsi/aic94xx/aic94xx_seq.c index 56e4b3ba6a08..845112539d05 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.c +++ b/drivers/scsi/aic94xx/aic94xx_seq.c @@ -1369,10 +1369,9 @@ int asd_start_seqs(struct asd_ha_struct *asd_ha) * port_map_by_links is also used as the conn_mask byte in the * initiator/target port DDB. */ -void asd_update_port_links(struct asd_sas_phy *sas_phy) +void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy) { - struct asd_ha_struct *asd_ha = sas_phy->ha->lldd_ha; - const u8 phy_mask = (u8) sas_phy->port->phy_mask; + const u8 phy_mask = (u8) phy->asd_port->phy_mask; u8 phy_is_up; u8 mask; int i, err; diff --git a/drivers/scsi/aic94xx/aic94xx_seq.h b/drivers/scsi/aic94xx/aic94xx_seq.h index 42281c36153b..9e715e5496af 100644 --- a/drivers/scsi/aic94xx/aic94xx_seq.h +++ b/drivers/scsi/aic94xx/aic94xx_seq.h @@ -64,7 +64,7 @@ int asd_unpause_lseq(struct asd_ha_struct *asd_ha, u8 lseq_mask); int asd_init_seqs(struct asd_ha_struct *asd_ha); int asd_start_seqs(struct asd_ha_struct *asd_ha); -void asd_update_port_links(struct asd_sas_phy *phy); +void asd_update_port_links(struct asd_ha_struct *asd_ha, struct asd_phy *phy); #endif #endif -- cgit v1.2.3 From 42961ee8fc4b05f5ca4d96ab34abd5149afe3541 Mon Sep 17 00:00:00 2001 From: "malahal@us.ibm.com" Date: Wed, 4 Oct 2006 17:34:03 -0700 Subject: [SCSI] aic94xx SCSI timeout fix: SMP retry fix. Updating DDB0 inside aic94xx driver itself caused SMP command timeout. I hit this SMP timeout problem twice but I am not able to reproduce it since then. Here is a fix that retries an SMP command. Signed-off-by: Malahal Naineni Signed-off-by: James Bottomley --- drivers/scsi/libsas/sas_expander.c | 84 +++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 30b8014bcc7a..e34a93435497 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -71,55 +71,65 @@ static void smp_task_done(struct sas_task *task) static int smp_execute_task(struct domain_device *dev, void *req, int req_size, void *resp, int resp_size) { - int res; - struct sas_task *task = sas_alloc_task(GFP_KERNEL); + int res, retry; + struct sas_task *task = NULL; struct sas_internal *i = to_sas_internal(dev->port->ha->core.shost->transportt); - if (!task) - return -ENOMEM; - - task->dev = dev; - task->task_proto = dev->tproto; - sg_init_one(&task->smp_task.smp_req, req, req_size); - sg_init_one(&task->smp_task.smp_resp, resp, resp_size); + for (retry = 0; retry < 3; retry++) { + task = sas_alloc_task(GFP_KERNEL); + if (!task) + return -ENOMEM; - task->task_done = smp_task_done; + task->dev = dev; + task->task_proto = dev->tproto; + sg_init_one(&task->smp_task.smp_req, req, req_size); + sg_init_one(&task->smp_task.smp_resp, resp, resp_size); - task->timer.data = (unsigned long) task; - task->timer.function = smp_task_timedout; - task->timer.expires = jiffies + SMP_TIMEOUT*HZ; - add_timer(&task->timer); + task->task_done = smp_task_done; - res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); + task->timer.data = (unsigned long) task; + task->timer.function = smp_task_timedout; + task->timer.expires = jiffies + SMP_TIMEOUT*HZ; + add_timer(&task->timer); - if (res) { - del_timer(&task->timer); - SAS_DPRINTK("executing SMP task failed:%d\n", res); - goto ex_err; - } + res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); - wait_for_completion(&task->completion); - res = -ETASK; - if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { - SAS_DPRINTK("smp task timed out or aborted\n"); - i->dft->lldd_abort_task(task); - if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { - SAS_DPRINTK("SMP task aborted and not done\n"); + if (res) { + del_timer(&task->timer); + SAS_DPRINTK("executing SMP task failed:%d\n", res); goto ex_err; } + + wait_for_completion(&task->completion); + res = -ETASK; + if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { + SAS_DPRINTK("smp task timed out or aborted\n"); + i->dft->lldd_abort_task(task); + if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { + SAS_DPRINTK("SMP task aborted and not done\n"); + goto ex_err; + } + } + if (task->task_status.resp == SAS_TASK_COMPLETE && + task->task_status.stat == SAM_GOOD) { + res = 0; + break; + } else { + SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " + "status 0x%x\n", __FUNCTION__, + SAS_ADDR(dev->sas_addr), + task->task_status.resp, + task->task_status.stat); + sas_free_task(task); + task = NULL; + } } - if (task->task_status.resp == SAS_TASK_COMPLETE && - task->task_status.stat == SAM_GOOD) - res = 0; - else - SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " - "status 0x%x\n", __FUNCTION__, - SAS_ADDR(dev->sas_addr), - task->task_status.resp, - task->task_status.stat); ex_err: - sas_free_task(task); + BUG_ON(retry == 3 && task != NULL); + if (task != NULL) { + sas_free_task(task); + } return res; } -- cgit v1.2.3 From 4039c30ef5d9189ff8dc72aaf610d1c933877e20 Mon Sep 17 00:00:00 2001 From: adam radford Date: Thu, 26 Oct 2006 18:01:06 -0700 Subject: [SCSI] 3ware 9000 add support for 9650SE Updates the 3ware 9000 driver: - Free irq handler in __twa_shutdown(). - Serialize reset code. - Add support for 9650SE controllers. Signed-off-by: Adam Radford Signed-off-by: James Bottomley --- drivers/scsi/3w-9xxx.c | 141 +++++++++++++++++++++++++++++-------------------- drivers/scsi/3w-9xxx.h | 14 +++-- 2 files changed, 94 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 5f8c26cd66ca..b091a0fc4eb0 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -66,6 +66,9 @@ 2.26.02.006 - Fix 9550SX pchip reset timeout. Add big endian support. 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic(). + 2.26.02.008 - Free irq handler in __twa_shutdown(). + Serialize reset code. + Add support for 9650SE controllers. */ #include @@ -89,7 +92,7 @@ #include "3w-9xxx.h" /* Globals */ -#define TW_DRIVER_VERSION "2.26.02.007" +#define TW_DRIVER_VERSION "2.26.02.008" static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; static unsigned int twa_device_extension_count; static int twa_major = -1; @@ -566,9 +569,9 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed) goto out; } - tw_dev->working_srl = fw_on_ctlr_srl; - tw_dev->working_branch = fw_on_ctlr_branch; - tw_dev->working_build = fw_on_ctlr_build; + tw_dev->tw_compat_info.working_srl = fw_on_ctlr_srl; + tw_dev->tw_compat_info.working_branch = fw_on_ctlr_branch; + tw_dev->tw_compat_info.working_build = fw_on_ctlr_build; /* Try base mode compatibility */ if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) { @@ -590,10 +593,23 @@ static int twa_check_srl(TW_Device_Extension *tw_dev, int *flashed) } goto out; } - tw_dev->working_srl = TW_BASE_FW_SRL; - tw_dev->working_branch = TW_BASE_FW_BRANCH; - tw_dev->working_build = TW_BASE_FW_BUILD; - } + tw_dev->tw_compat_info.working_srl = TW_BASE_FW_SRL; + tw_dev->tw_compat_info.working_branch = TW_BASE_FW_BRANCH; + tw_dev->tw_compat_info.working_build = TW_BASE_FW_BUILD; + } + + /* Load rest of compatibility struct */ + strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION)); + tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL; + tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH; + tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD; + tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL; + tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH; + tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD; + tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl; + tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch; + tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build; + retval = 0; out: return retval; @@ -631,7 +647,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int goto out2; /* Check data buffer size */ - if (driver_command.buffer_length > TW_MAX_SECTORS * 512) { + if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) { retval = TW_IOCTL_ERROR_OS_EINVAL; goto out2; } @@ -680,13 +696,6 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int /* Now wait for command to complete */ timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); - /* See if we reset while waiting for the ioctl to complete */ - if (test_bit(TW_IN_RESET, &tw_dev->flags)) { - clear_bit(TW_IN_RESET, &tw_dev->flags); - retval = TW_IOCTL_ERROR_OS_ERESTARTSYS; - goto out3; - } - /* We timed out, and didn't get an interrupt */ if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { /* Now we need to reset the board */ @@ -694,11 +703,6 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int tw_dev->host->host_no, TW_DRIVER, 0xc, cmd); retval = TW_IOCTL_ERROR_OS_EIO; - spin_lock_irqsave(tw_dev->host->host_lock, flags); - tw_dev->state[request_id] = TW_S_COMPLETED; - twa_free_request_id(tw_dev, request_id); - tw_dev->posted_request_count--; - spin_unlock_irqrestore(tw_dev->host->host_lock, flags); twa_reset_device_extension(tw_dev, 1); goto out3; } @@ -717,16 +721,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int tw_ioctl->driver_command.status = 0; /* Copy compatiblity struct into ioctl data buffer */ tw_compat_info = (TW_Compatibility_Info *)tw_ioctl->data_buffer; - strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION)); - tw_compat_info->working_srl = tw_dev->working_srl; - tw_compat_info->working_branch = tw_dev->working_branch; - tw_compat_info->working_build = tw_dev->working_build; - tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL; - tw_compat_info->driver_branch_high = TW_CURRENT_DRIVER_BRANCH; - tw_compat_info->driver_build_high = TW_CURRENT_DRIVER_BUILD; - tw_compat_info->driver_srl_low = TW_BASE_FW_SRL; - tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH; - tw_compat_info->driver_build_low = TW_BASE_FW_BUILD; + memcpy(tw_compat_info, &tw_dev->tw_compat_info, sizeof(TW_Compatibility_Info)); break; case TW_IOCTL_GET_LAST_EVENT: if (tw_dev->event_queue_wrapped) { @@ -895,7 +890,8 @@ static int twa_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) } if (status_reg_value & TW_STATUS_QUEUE_ERROR) { - TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); + if ((tw_dev->tw_pci_dev->device != PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev->flags))) + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue Error: clearing"); writel(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev)); } @@ -939,10 +935,12 @@ static int twa_empty_response_queue_large(TW_Device_Extension *tw_dev) unsigned long before; int retval = 1; - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { before = jiffies; while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != TW_9550SX_DRAIN_COMPLETED) { response_que_value = readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); + msleep(1); if (time_after(jiffies, before + HZ * 30)) goto out; } @@ -1214,6 +1212,10 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) handled = 1; + /* If we are resetting, bail */ + if (test_bit(TW_IN_RESET, &tw_dev->flags)) + goto twa_interrupt_bail; + /* Check controller for errors */ if (twa_check_bits(status_reg_value)) { if (twa_decode_bits(tw_dev, status_reg_value)) { @@ -1355,8 +1357,8 @@ static void twa_load_sgl(TW_Command_Full *full_command_packet, int request_id, d if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { newcommand = &full_command_packet->command.newcommand; - newcommand->request_id__lunl = - TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id); + newcommand->request_id__lunl = + cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id)); newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1); newcommand->sg_list[0].length = cpu_to_le32(length); newcommand->sgl_entries__lunh = @@ -1531,6 +1533,13 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, int retval = 1; command_que_value = tw_dev->command_packet_phys[request_id]; + + /* For 9650SE write low 4 bytes first */ + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { + command_que_value += TW_COMMAND_OFFSET; + writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); + } + status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); if (twa_check_bits(status_reg_value)) @@ -1557,13 +1566,17 @@ static int twa_post_command_packet(TW_Device_Extension *tw_dev, int request_id, TW_UNMASK_COMMAND_INTERRUPT(tw_dev); goto out; } else { - /* We successfully posted the command packet */ - if (sizeof(dma_addr_t) > 4) { - command_que_value += TW_COMMAND_OFFSET; - writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); - writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4); + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { + /* Now write upper 4 bytes */ + writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); } else { - writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + if (sizeof(dma_addr_t) > 4) { + command_que_value += TW_COMMAND_OFFSET; + writel((u32)command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + writel((u32)((u64)command_que_value >> 32), TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4); + } else { + writel(TW_COMMAND_OFFSET + command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); + } } tw_dev->state[request_id] = TW_S_POSTED; tw_dev->posted_request_count++; @@ -1620,14 +1633,9 @@ static int twa_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_res goto out; TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); + clear_bit(TW_IN_RESET, &tw_dev->flags); + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - /* Wake up any ioctl that was pending before the reset */ - if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) { - clear_bit(TW_IN_RESET, &tw_dev->flags); - } else { - tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; - wake_up(&tw_dev->ioctl_wqueue); - } retval = 0; out: return retval; @@ -1736,6 +1744,9 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n", TW_DRIVER, 0x2c, SCpnt->cmnd[0]); + /* Make sure we are not issuing an ioctl or resetting from ioctl */ + mutex_lock(&tw_dev->ioctl_lock); + /* Now reset the card and some of the device extension data */ if (twa_reset_device_extension(tw_dev, 0)) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset failed during scsi host reset"); @@ -1744,6 +1755,7 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt) retval = SUCCESS; out: + mutex_unlock(&tw_dev->ioctl_lock); return retval; } /* End twa_scsi_eh_reset() */ @@ -1753,8 +1765,14 @@ static int twa_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd int request_id, retval; TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; + /* If we are resetting due to timed out ioctl, report as busy */ + if (test_bit(TW_IN_RESET, &tw_dev->flags)) { + retval = SCSI_MLQUEUE_HOST_BUSY; + goto out; + } + /* Check if this FW supports luns */ - if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < TW_FW_SRL_LUNS_SUPPORTED)) { + if ((SCpnt->device->lun != 0) && (tw_dev->tw_compat_info.working_srl < TW_FW_SRL_LUNS_SUPPORTED)) { SCpnt->result = (DID_BAD_TARGET << 16); done(SCpnt); retval = 0; @@ -1960,6 +1978,9 @@ static void __twa_shutdown(TW_Device_Extension *tw_dev) /* Disable interrupts */ TW_DISABLE_INTERRUPTS(tw_dev); + /* Free up the IRQ */ + free_irq(tw_dev->tw_pci_dev->irq, tw_dev); + printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev->host->host_no); /* Tell the card we are shutting down */ @@ -2091,21 +2112,25 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id /* Initialize the card */ if (twa_reset_sequence(tw_dev, 0)) - goto out_release_mem_region; + goto out_iounmap; /* Set host specific parameters */ - host->max_id = TW_MAX_UNITS; + if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) + host->max_id = TW_MAX_UNITS_9650SE; + else + host->max_id = TW_MAX_UNITS; + host->max_cmd_len = TW_MAX_CDB_LEN; /* Channels aren't supported by adapter */ - host->max_lun = TW_MAX_LUNS(tw_dev->working_srl); + host->max_lun = TW_MAX_LUNS(tw_dev->tw_compat_info.working_srl); host->max_channel = 0; /* Register the card with the kernel SCSI layer */ retval = scsi_add_host(host, &pdev->dev); if (retval) { TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host failed"); - goto out_release_mem_region; + goto out_iounmap; } pci_set_drvdata(pdev, host); @@ -2145,6 +2170,8 @@ static int __devinit twa_probe(struct pci_dev *pdev, const struct pci_device_id out_remove_host: scsi_remove_host(host); +out_iounmap: + iounmap(tw_dev->base_addr); out_release_mem_region: pci_release_regions(pdev); out_free_device_extension: @@ -2170,12 +2197,12 @@ static void twa_remove(struct pci_dev *pdev) twa_major = -1; } - /* Free up the IRQ */ - free_irq(tw_dev->tw_pci_dev->irq, tw_dev); - /* Shutdown the card */ __twa_shutdown(tw_dev); + /* Free IO remapping */ + iounmap(tw_dev->base_addr); + /* Free up the mem region */ pci_release_regions(pdev); @@ -2193,6 +2220,8 @@ static struct pci_device_id twa_pci_tbl[] __devinitdata = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { } }; MODULE_DEVICE_TABLE(pci, twa_pci_tbl); diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h index e5685be96f45..7901517d4513 100644 --- a/drivers/scsi/3w-9xxx.h +++ b/drivers/scsi/3w-9xxx.h @@ -289,7 +289,6 @@ static twa_message_type twa_error_table[] = { #define TW_STATUS_VALID_INTERRUPT 0x00DF0000 /* PCI related defines */ -#define TW_NUMDEVICES 1 #define TW_PCI_CLEAR_PARITY_ERRORS 0xc100 #define TW_PCI_CLEAR_PCI_ABORT 0x2000 @@ -335,6 +334,7 @@ static twa_message_type twa_error_table[] = { #define TW_ALIGNMENT_9000 4 /* 4 bytes */ #define TW_ALIGNMENT_9000_SGL 0x3 #define TW_MAX_UNITS 16 +#define TW_MAX_UNITS_9650SE 32 #define TW_INIT_MESSAGE_CREDITS 0x100 #define TW_INIT_COMMAND_PACKET_SIZE 0x3 #define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED 0x6 @@ -354,7 +354,6 @@ static twa_message_type twa_error_table[] = { #define TW_MAX_RESPONSE_DRAIN 256 #define TW_MAX_AEN_DRAIN 40 #define TW_IN_RESET 2 -#define TW_IN_CHRDEV_IOCTL 3 #define TW_IN_ATTENTION_LOOP 4 #define TW_MAX_SECTORS 256 #define TW_AEN_WAIT_TIME 1000 @@ -417,6 +416,9 @@ static twa_message_type twa_error_table[] = { #ifndef PCI_DEVICE_ID_3WARE_9550SX #define PCI_DEVICE_ID_3WARE_9550SX 0x1003 #endif +#ifndef PCI_DEVICE_ID_3WARE_9650SE +#define PCI_DEVICE_ID_3WARE_9650SE 0x1004 +#endif /* Bitmask macros to eliminate bitfields */ @@ -442,6 +444,7 @@ static twa_message_type twa_error_table[] = { #define TW_CONTROL_REG_ADDR(x) (x->base_addr) #define TW_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0x4) #define TW_COMMAND_QUEUE_REG_ADDR(x) (sizeof(dma_addr_t) > 4 ? ((unsigned char __iomem *)x->base_addr + 0x20) : ((unsigned char __iomem *)x->base_addr + 0x8)) +#define TW_COMMAND_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x20) #define TW_RESPONSE_QUEUE_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + 0xC) #define TW_RESPONSE_QUEUE_REG_ADDR_LARGE(x) ((unsigned char __iomem *)x->base_addr + 0x30) #define TW_CLEAR_ALL_INTERRUPTS(x) (writel(TW_STATUS_VALID_INTERRUPT, TW_CONTROL_REG_ADDR(x))) @@ -626,6 +629,9 @@ typedef struct TAG_TW_Compatibility_Info unsigned short driver_srl_low; unsigned short driver_branch_low; unsigned short driver_build_low; + unsigned short fw_on_ctlr_srl; + unsigned short fw_on_ctlr_branch; + unsigned short fw_on_ctlr_build; } TW_Compatibility_Info; #pragma pack() @@ -668,9 +674,7 @@ typedef struct TAG_TW_Device_Extension { wait_queue_head_t ioctl_wqueue; struct mutex ioctl_lock; char aen_clobber; - unsigned short working_srl; - unsigned short working_branch; - unsigned short working_build; + TW_Compatibility_Info tw_compat_info; } TW_Device_Extension; #endif /* _3W_9XXX_H */ -- cgit v1.2.3 From 7ca63cb470f23a197f187afe936d4bf806197d6e Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Fri, 27 Oct 2006 17:47:49 -0400 Subject: [SCSI] sg: fix incorrect last scatg length For certain LLDs the sg driver can cause on oops when the transfer length is large and not a multiple of PAGE_SIZE. ChangeLog: - correct the length of the last scatter gather list element. - fix some printk()s that have the wrong function name. Signed-off-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/sg.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3f8b93188567..81e3bc7b02a1 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -60,7 +60,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #ifdef CONFIG_SCSI_PROC_FS #include -static char *sg_version_date = "20060920"; +static char *sg_version_date = "20061027"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -710,12 +710,12 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, (int) cmnd[0], (int) hp->cmd_len)); if ((k = sg_start_req(srp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: start_req err=%d\n", k)); + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ } if ((k = sg_write_xfer(srp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: write_xfer, bad address\n")); + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: write_xfer, bad address\n")); sg_finish_rem_req(srp); return k; } @@ -746,7 +746,7 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->dxfer_len, srp->data.k_use_sg, timeout, SG_DEFAULT_RETRIES, srp, sg_cmd_done, GFP_ATOMIC)) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: scsi_execute_async failed\n")); + SCSI_LOG_TIMEOUT(1, printk("sg_common_write: scsi_execute_async failed\n")); /* * most likely out of mem, but could also be a bad map */ @@ -1283,7 +1283,7 @@ sg_cmd_done(void *data, char *sense, int result, int resid) sg_finish_rem_req(srp); srp = NULL; if (NULL == sfp->headrp) { - SCSI_LOG_TIMEOUT(1, printk("sg...bh: already closed, final cleanup\n")); + SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, final cleanup\n")); if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */ scsi_device_put(sdp->device); } @@ -1512,12 +1512,12 @@ sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) POLL_HUP); } } - SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k)); + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k)); if (NULL == sdp->headfp) { sg_dev_arr[k] = NULL; } } else { /* nothing active, simple case */ - SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d\n", k)); + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k)); sg_dev_arr[k] = NULL; } sg_nr_dev--; @@ -1876,14 +1876,15 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) } } sg->page = p; - sg->length = ret_sz; + sg->length = (ret_sz > num) ? num : ret_sz; - SCSI_LOG_TIMEOUT(5, printk("sg_build_build: k=%d, a=0x%p, len=%d\n", - k, p, ret_sz)); + SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " + "ret_sz=%d\n", k, num, ret_sz)); } /* end of for loop */ schp->k_use_sg = k; - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", k, rem_sz)); + SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " + "rem_sz=%d\n", k, rem_sz)); schp->bufflen = blk_size; if (rem_sz > 0) /* must have failed */ @@ -2014,7 +2015,7 @@ sg_remove_scat(Sg_scatter_hold * schp) for (k = 0; (k < schp->k_use_sg) && sg->page; ++k, ++sg) { SCSI_LOG_TIMEOUT(5, printk( - "sg_remove_scat: k=%d, a=0x%p, len=%d\n", + "sg_remove_scat: k=%d, pg=0x%p, len=%d\n", k, sg->page, sg->length)); sg_page_free(sg->page, sg->length); } -- cgit v1.2.3 From 25a122fd0d28b48782b9524a85895573e7ccf304 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Wed, 25 Oct 2006 09:37:41 +0300 Subject: MMC: Poll card status after rescanning cards Some broken cards seem to process CMD1 even in stand-by state. The result is that the card replies with ILLEGAL_COMMAND error for the next command sent after rescanning. Currently the next command is select card, which would return the error. But CMD7 does actually succeed and retries of the command will timeout. The workaround is to poll card status after CMD1 to clear the pending error. Signed-off-by: Timo Teras Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ee8863c123e3..ec8168ac75b1 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1178,14 +1178,29 @@ static void mmc_rescan(void *data) { struct mmc_host *host = data; struct list_head *l, *n; + unsigned char power_mode; mmc_claim_host(host); - if (host->ios.power_mode == MMC_POWER_ON) + /* + * Check for removed cards and newly inserted ones. We check for + * removed cards first so we can intelligently re-select the VDD. + */ + power_mode = host->ios.power_mode; + if (power_mode == MMC_POWER_ON) mmc_check_cards(host); mmc_setup(host); + /* + * Some broken cards process CMD1 even in stand-by state. There is + * no reply, but an ILLEGAL_COMMAND error is cached and returned + * after next command. We poll for card status here to clear any + * possibly pending error. + */ + if (power_mode == MMC_POWER_ON) + mmc_check_cards(host); + if (!list_empty(&host->cards)) { /* * (Re-)calculate the fastest clock rate which the -- cgit v1.2.3 From 63ef731aa6a81e286de78dcc92241d123424ed39 Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Thu, 2 Nov 2006 19:43:27 +0100 Subject: MMC: Do not set unsupported bits in OCR response The card might go to inactive state (according to specification), if there are unsupported bits set in the OCR. Signed-off-by: Timo Teras Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index ec8168ac75b1..766bc54406e5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -475,7 +475,7 @@ static u32 mmc_select_voltage(struct mmc_host *host, u32 ocr) if (bit) { bit -= 1; - ocr = 3 << bit; + ocr &= 3 << bit; host->ios.vdd = bit; mmc_set_ios(host); -- cgit v1.2.3 From 7e28db5d8ff63b1cabc221c5cb84a5f45752f1c2 Mon Sep 17 00:00:00 2001 From: Hoang-Nam Nguyen Date: Tue, 7 Nov 2006 00:56:39 +0100 Subject: IB/ehca: Assure 4K alignment for firmware control blocks Assure 4K alignment for firmware control blocks in 64K page mode, because kzalloc()'s result address might not be 4K aligned if 64K pages are enabled. Thus, we introduce wrappers called ehca_{alloc,free}_fw_ctrlblock(), which use a slab cache for objects with 4K length and 4K alignment in order to alloc/free firmware control blocks in 64K page mode. In 4K page mode those wrappers just are defines of get_zeroed_page() and free_page(). Signed-off-by: Hoang-Nam Nguyen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_hca.c | 17 +++++----- drivers/infiniband/hw/ehca/ehca_irq.c | 17 +++++----- drivers/infiniband/hw/ehca/ehca_iverbs.h | 8 +++++ drivers/infiniband/hw/ehca/ehca_main.c | 56 +++++++++++++++++++++++++++----- drivers/infiniband/hw/ehca/ehca_mrmw.c | 8 ++--- drivers/infiniband/hw/ehca/ehca_qp.c | 10 +++--- 6 files changed, 81 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_hca.c b/drivers/infiniband/hw/ehca/ehca_hca.c index 5eae6ac48425..e1b618c5f685 100644 --- a/drivers/infiniband/hw/ehca/ehca_hca.c +++ b/drivers/infiniband/hw/ehca/ehca_hca.c @@ -40,6 +40,7 @@ */ #include "ehca_tools.h" +#include "ehca_iverbs.h" #include "hcp_if.h" int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) @@ -49,7 +50,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) ib_device); struct hipz_query_hca *rblock; - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Can't allocate rblock memory."); return -ENOMEM; @@ -96,7 +97,7 @@ int ehca_query_device(struct ib_device *ibdev, struct ib_device_attr *props) = min_t(int, rblock->max_total_mcast_qp_attach, INT_MAX); query_device1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } @@ -109,7 +110,7 @@ int ehca_query_port(struct ib_device *ibdev, ib_device); struct hipz_query_port *rblock; - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Can't allocate rblock memory."); return -ENOMEM; @@ -162,7 +163,7 @@ int ehca_query_port(struct ib_device *ibdev, props->active_speed = 0x1; query_port1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } @@ -178,7 +179,7 @@ int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) return -EINVAL; } - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Can't allocate rblock memory."); return -ENOMEM; @@ -193,7 +194,7 @@ int ehca_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey) memcpy(pkey, &rblock->pkey_entries + index, sizeof(u16)); query_pkey1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } @@ -211,7 +212,7 @@ int ehca_query_gid(struct ib_device *ibdev, u8 port, return -EINVAL; } - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Can't allocate rblock memory."); return -ENOMEM; @@ -227,7 +228,7 @@ int ehca_query_gid(struct ib_device *ibdev, u8 port, memcpy(&gid->raw[8], &rblock->guid_entries[index], sizeof(u64)); query_gid1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 048cc443d1e7..c3ea746e9045 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -45,6 +45,7 @@ #include "ehca_tools.h" #include "hcp_if.h" #include "hipz_fns.h" +#include "ipz_pt_fn.h" #define EQE_COMPLETION_EVENT EHCA_BMASK_IBM(1,1) #define EQE_CQ_QP_NUMBER EHCA_BMASK_IBM(8,31) @@ -137,38 +138,36 @@ int ehca_error_data(struct ehca_shca *shca, void *data, u64 *rblock; unsigned long block_count; - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Cannot allocate rblock memory."); ret = -ENOMEM; goto error_data1; } + /* rblock must be 4K aligned and should be 4K large */ ret = hipz_h_error_data(shca->ipz_hca_handle, resource, rblock, &block_count); - if (ret == H_R_STATE) { + if (ret == H_R_STATE) ehca_err(&shca->ib_device, "No error data is available: %lx.", resource); - } else if (ret == H_SUCCESS) { int length; length = EHCA_BMASK_GET(ERROR_DATA_LENGTH, rblock[0]); - if (length > PAGE_SIZE) - length = PAGE_SIZE; + if (length > EHCA_PAGESIZE) + length = EHCA_PAGESIZE; print_error_data(shca, data, rblock, length); - } - else { + } else ehca_err(&shca->ib_device, "Error data could not be fetched: %lx", resource); - } - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); error_data1: return ret; diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h index 319c39d47f3a..3720e3032cce 100644 --- a/drivers/infiniband/hw/ehca/ehca_iverbs.h +++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h @@ -179,4 +179,12 @@ int ehca_mmap_register(u64 physical,void **mapped, int ehca_munmap(unsigned long addr, size_t len); +#ifdef CONFIG_PPC_64K_PAGES +void *ehca_alloc_fw_ctrlblock(void); +void ehca_free_fw_ctrlblock(void *ptr); +#else +#define ehca_alloc_fw_ctrlblock() ((void *) get_zeroed_page(GFP_KERNEL)) +#define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr)) +#endif + #endif diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 024d511c4b58..01f5aa9cb56d 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -40,6 +40,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifdef CONFIG_PPC_64K_PAGES +#include +#endif #include "ehca_classes.h" #include "ehca_iverbs.h" #include "ehca_mrmw.h" @@ -49,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch "); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0017"); +MODULE_VERSION("SVNEHCA_0018"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -94,11 +97,31 @@ spinlock_t ehca_cq_idr_lock; DEFINE_IDR(ehca_qp_idr); DEFINE_IDR(ehca_cq_idr); + static struct list_head shca_list; /* list of all registered ehcas */ static spinlock_t shca_list_lock; static struct timer_list poll_eqs_timer; +#ifdef CONFIG_PPC_64K_PAGES +static struct kmem_cache *ctblk_cache = NULL; + +void *ehca_alloc_fw_ctrlblock(void) +{ + void *ret = kmem_cache_zalloc(ctblk_cache, SLAB_KERNEL); + if (!ret) + ehca_gen_err("Out of memory for ctblk"); + return ret; +} + +void ehca_free_fw_ctrlblock(void *ptr) +{ + if (ptr) + kmem_cache_free(ctblk_cache, ptr); + +} +#endif + static int ehca_create_slab_caches(void) { int ret; @@ -133,6 +156,17 @@ static int ehca_create_slab_caches(void) goto create_slab_caches5; } +#ifdef CONFIG_PPC_64K_PAGES + ctblk_cache = kmem_cache_create("ehca_cache_ctblk", + EHCA_PAGESIZE, H_CB_ALIGNMENT, + SLAB_HWCACHE_ALIGN, + NULL, NULL); + if (!ctblk_cache) { + ehca_gen_err("Cannot create ctblk SLAB cache."); + ehca_cleanup_mrmw_cache(); + goto create_slab_caches5; + } +#endif return 0; create_slab_caches5: @@ -157,6 +191,10 @@ static void ehca_destroy_slab_caches(void) ehca_cleanup_qp_cache(); ehca_cleanup_cq_cache(); ehca_cleanup_pd_cache(); +#ifdef CONFIG_PPC_64K_PAGES + if (ctblk_cache) + kmem_cache_destroy(ctblk_cache); +#endif } #define EHCA_HCAAVER EHCA_BMASK_IBM(32,39) @@ -168,7 +206,7 @@ int ehca_sense_attributes(struct ehca_shca *shca) u64 h_ret; struct hipz_query_hca *rblock; - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_gen_err("Cannot allocate rblock memory."); return -ENOMEM; @@ -211,7 +249,7 @@ int ehca_sense_attributes(struct ehca_shca *shca) shca->sport[1].rate = IB_RATE_30_GBPS; num_ports1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } @@ -220,7 +258,7 @@ static int init_node_guid(struct ehca_shca *shca) int ret = 0; struct hipz_query_hca *rblock; - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + rblock = ehca_alloc_fw_ctrlblock(); if (!rblock) { ehca_err(&shca->ib_device, "Can't allocate rblock memory."); return -ENOMEM; @@ -235,7 +273,7 @@ static int init_node_guid(struct ehca_shca *shca) memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64)); init_node_guid1: - kfree(rblock); + ehca_free_fw_ctrlblock(rblock); return ret; } @@ -431,7 +469,7 @@ static ssize_t ehca_show_##name(struct device *dev, \ \ shca = dev->driver_data; \ \ - rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); \ + rblock = ehca_alloc_fw_ctrlblock(); \ if (!rblock) { \ dev_err(dev, "Can't allocate rblock memory."); \ return 0; \ @@ -439,12 +477,12 @@ static ssize_t ehca_show_##name(struct device *dev, \ \ if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \ dev_err(dev, "Can't query device properties"); \ - kfree(rblock); \ + ehca_free_fw_ctrlblock(rblock); \ return 0; \ } \ \ data = rblock->name; \ - kfree(rblock); \ + ehca_free_fw_ctrlblock(rblock); \ \ if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \ return snprintf(buf, 256, "1\n"); \ @@ -752,7 +790,7 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0017)\n"); + "(Rel.: SVNEHCA_0018)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); diff --git a/drivers/infiniband/hw/ehca/ehca_mrmw.c b/drivers/infiniband/hw/ehca/ehca_mrmw.c index 5ca65441e1da..abce676c0ae0 100644 --- a/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -1013,7 +1013,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca, u32 i; u64 *kpage; - kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + kpage = ehca_alloc_fw_ctrlblock(); if (!kpage) { ehca_err(&shca->ib_device, "kpage alloc failed"); ret = -ENOMEM; @@ -1092,7 +1092,7 @@ int ehca_reg_mr_rpages(struct ehca_shca *shca, ehca_reg_mr_rpages_exit1: - kfree(kpage); + ehca_free_fw_ctrlblock(kpage); ehca_reg_mr_rpages_exit0: if (ret) ehca_err(&shca->ib_device, "ret=%x shca=%p e_mr=%p pginfo=%p " @@ -1124,7 +1124,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, ehca_mrmw_map_acl(acl, &hipz_acl); ehca_mrmw_set_pgsize_hipz_acl(&hipz_acl); - kpage = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); + kpage = ehca_alloc_fw_ctrlblock(); if (!kpage) { ehca_err(&shca->ib_device, "kpage alloc failed"); ret = -ENOMEM; @@ -1181,7 +1181,7 @@ inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, } ehca_rereg_mr_rereg1_exit1: - kfree(kpage); + ehca_free_fw_ctrlblock(kpage); ehca_rereg_mr_rereg1_exit0: if ( ret && (ret != -EAGAIN) ) ehca_err(&shca->ib_device, "ret=%x lkey=%x rkey=%x " diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index 4394123cdbd7..cf3e50ee2d06 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -811,8 +811,8 @@ static int internal_modify_qp(struct ib_qp *ibqp, unsigned long spl_flags = 0; /* do query_qp to obtain current attr values */ - mqpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); - if (mqpcb == NULL) { + mqpcb = ehca_alloc_fw_ctrlblock(); + if (!mqpcb) { ehca_err(ibqp->device, "Could not get zeroed page for mqpcb " "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num); return -ENOMEM; @@ -1225,7 +1225,7 @@ modify_qp_exit2: } modify_qp_exit1: - kfree(mqpcb); + ehca_free_fw_ctrlblock(mqpcb); return ret; } @@ -1277,7 +1277,7 @@ int ehca_query_qp(struct ib_qp *qp, return -EINVAL; } - qpcb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL ); + qpcb = ehca_alloc_fw_ctrlblock(); if (!qpcb) { ehca_err(qp->device,"Out of memory for qpcb " "ehca_qp=%p qp_num=%x", my_qp, qp->qp_num); @@ -1401,7 +1401,7 @@ int ehca_query_qp(struct ib_qp *qp, ehca_dmp(qpcb, 4*70, "qp_num=%x", qp->qp_num); query_qp_exit1: - kfree(qpcb); + ehca_free_fw_ctrlblock(qpcb); return ret; } -- cgit v1.2.3 From 534284a09b3f58cd92acd0652b7267ee142932ba Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Wed, 8 Nov 2006 15:58:31 -0600 Subject: [SCSI] iscsi: always release crypto Unconditionally free crypto state, as it is always allocated during TCP connection creation. Without this, crypto structures leak and crc32c module refcounts grow as connections are created and destroyed. Signed-off-by: Pete Wyckoff Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 0a9dbc59663f..c0b8b33e935c 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -1816,21 +1816,14 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_conn *cls_conn) { struct iscsi_conn *conn = cls_conn->dd_data; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; - int digest = 0; - - if (conn->hdrdgst_en || conn->datadgst_en) - digest = 1; iscsi_tcp_release_conn(conn); iscsi_conn_teardown(cls_conn); - /* now free tcp_conn */ - if (digest) { - if (tcp_conn->tx_hash.tfm) - crypto_free_hash(tcp_conn->tx_hash.tfm); - if (tcp_conn->rx_hash.tfm) - crypto_free_hash(tcp_conn->rx_hash.tfm); - } + if (tcp_conn->tx_hash.tfm) + crypto_free_hash(tcp_conn->tx_hash.tfm); + if (tcp_conn->rx_hash.tfm) + crypto_free_hash(tcp_conn->rx_hash.tfm); kfree(tcp_conn); } -- cgit v1.2.3 From d6e24d1c8a197cc9c2a1568224474f4b7af50803 Mon Sep 17 00:00:00 2001 From: Pete Wyckoff Date: Wed, 8 Nov 2006 15:58:32 -0600 Subject: [SCSI] iscsi: add newlines to debug messages Some messages from debug_scsi do not have trailing newlines, making console messages difficult to read. Fix that. Signed-off-by: Pete Wyckoff Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 2865ebd557ef..5d8862189485 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -975,13 +975,13 @@ int iscsi_eh_host_reset(struct scsi_cmnd *sc) if (session->state == ISCSI_STATE_TERMINATE) { failed: debug_scsi("failing host reset: session terminated " - "[CID %d age %d]", conn->id, session->age); + "[CID %d age %d]\n", conn->id, session->age); spin_unlock_bh(&session->lock); return FAILED; } if (sc->SCp.phase == session->age) { - debug_scsi("failing connection CID %d due to SCSI host reset", + debug_scsi("failing connection CID %d due to SCSI host reset\n", conn->id); fail_session = 1; } @@ -1054,7 +1054,8 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, NULL, 0); if (rc) { iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - debug_scsi("abort sent failure [itt 0x%x] %d", ctask->itt, rc); + debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt, + rc); return rc; } @@ -1071,7 +1072,7 @@ static int iscsi_exec_abort_task(struct scsi_cmnd *sc, conn->tmabort_timer.function = iscsi_tmabort_timedout; conn->tmabort_timer.data = (unsigned long)ctask; add_timer(&conn->tmabort_timer); - debug_scsi("abort set timeout [itt 0x%x]", ctask->itt); + debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); } spin_unlock_bh(&session->lock); mutex_unlock(&conn->xmitmutex); -- cgit v1.2.3 From db37c505e5dfc1a26d6c82f1ce0c3ae06641c3e0 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 8 Nov 2006 15:58:33 -0600 Subject: [SCSI] iscsi_tcp: fix xmittask oops XMSTATE_SOL_HDR could be set when the xmit thread tests it, but there may not be anything on the r2tqueue yet. Move the XMSTATE_SOL_HDR set before the addition to the queue to make sure that when we pull something off it it is valid. This does not add locks around the xmstate test or make that a atmoic_t because this is a fast path and if it is set when we test it we can handle it there without the overhead. Later on we check the xmitqueue for all requests with the session lock so we will not miss it. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index c0b8b33e935c..d0b139cccbbc 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -415,8 +415,8 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_solicit_data_init(conn, ctask, r2t); tcp_ctask->exp_r2tsn = r2tsn + 1; - tcp_ctask->xmstate |= XMSTATE_SOL_HDR; __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); + tcp_ctask->xmstate |= XMSTATE_SOL_HDR; list_move_tail(&ctask->running, &conn->xmitqueue); scsi_queue_work(session->host, &conn->xmitwork); @@ -1627,9 +1627,12 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; tcp_ctask->xmstate |= XMSTATE_SOL_DATA; - if (!tcp_ctask->r2t) + if (!tcp_ctask->r2t) { + spin_lock_bh(&session->lock); __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, sizeof(void*)); + spin_unlock_bh(&session->lock); + } send_hdr: r2t = tcp_ctask->r2t; dtask = &r2t->dtask; -- cgit v1.2.3 From 82a0d7b5829ebd033b7f808c026ab43509913692 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 8 Nov 2006 15:58:34 -0600 Subject: [SCSI] iscsi class: update version Update version number Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 2d3baa99ca25..9b25124a989e 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -33,7 +33,7 @@ #define ISCSI_SESSION_ATTRS 11 #define ISCSI_CONN_ATTRS 11 #define ISCSI_HOST_ATTRS 0 -#define ISCSI_TRANSPORT_VERSION "2.0-685" +#define ISCSI_TRANSPORT_VERSION "2.0-724" struct iscsi_internal { int daemon_pid; -- cgit v1.2.3 From 107e716b3487df5e2940ebe3338d935306efc78b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 9 Nov 2006 21:45:09 +0100 Subject: [SCSI] gdth: Fix && typos Fix uses of "&&" where "&" was obviously intended instead. Signed-off-by: Jean Delvare Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 4bc14ad92e22..4c698a71f66f 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -3531,7 +3531,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) IStatus &= ~0x80; #ifdef INT_COAL if (coalesced) - ha->status = pcs->ext_status && 0xffff; + ha->status = pcs->ext_status & 0xffff; else #endif ha->status = gdth_readw(&dp6m_ptr->i960r.status); @@ -3543,7 +3543,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) if (coalesced) { ha->info = pcs->info0; ha->info2 = pcs->info1; - ha->service = (pcs->ext_status >> 16) && 0xffff; + ha->service = (pcs->ext_status >> 16) & 0xffff; } else #endif { -- cgit v1.2.3 From 05052f7f130b1232faeee1674a5bc41f67746cff Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 8 Nov 2006 19:56:37 -0800 Subject: [SCSI] psi240i.c: fix an array overrun Fix an array overrun spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/psi240i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/psi240i.c b/drivers/scsi/psi240i.c index ac0419e2714a..899e89d6fe67 100644 --- a/drivers/scsi/psi240i.c +++ b/drivers/scsi/psi240i.c @@ -328,7 +328,7 @@ static void Irq_Handler (int irq, void *dev_id) pinquiryData->AdditionalLength = 35 - 4; // Fill in vendor identification fields. - for ( z = 0; z < 20; z += 2 ) + for ( z = 0; z < 8; z += 2 ) { pinquiryData->VendorId[z] = ((UCHAR *)identifyData.ModelNumber)[z + 1]; pinquiryData->VendorId[z + 1] = ((UCHAR *)identifyData.ModelNumber)[z]; -- cgit v1.2.3 From 599540a85595bd5950354bd95f5ebf9c6e07c971 Mon Sep 17 00:00:00 2001 From: Kalle Pokki Date: Wed, 1 Nov 2006 09:52:41 +0200 Subject: [POWERPC] CPM_UART: Fix non-console transmit The SMC and SCC hardware transmitter is enabled at the wrong place. Simply writing twice to the non-console port, like $ echo asdf > /dev/ttyCPM1 $ echo asdf > /dev/ttyCPM1 puts the shell into endless uninterruptible sleep, since the transmitter is stopped after the first write, and is not enabled before the shutdown function of the second write. Thus the transmit buffers are never emptied. Signed-off-by: Kalle Pokki Signed-off-by: Vitaly Bordug Signed-off-by: Paul Mackerras --- drivers/serial/cpm_uart/cpm_uart_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 0abb544ae63d..32fd8c83bd8e 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -195,10 +195,8 @@ static void cpm_uart_start_tx(struct uart_port *port) if (cpm_uart_tx_pump(port) != 0) { if (IS_SMC(pinfo)) { smcp->smc_smcm |= SMCM_TX; - smcp->smc_smcmr |= SMCMR_TEN; } else { sccp->scc_sccm |= UART_SCCM_TX; - pinfo->sccp->scc_gsmrl |= SCC_GSMRL_ENT; } } } @@ -421,9 +419,10 @@ static int cpm_uart_startup(struct uart_port *port) /* Startup rx-int */ if (IS_SMC(pinfo)) { pinfo->smcp->smc_smcm |= SMCM_RX; - pinfo->smcp->smc_smcmr |= SMCMR_REN; + pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN); } else { pinfo->sccp->scc_sccm |= UART_SCCM_RX; + pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); } if (!(pinfo->flags & FLAG_CONSOLE)) -- cgit v1.2.3 From 0091cf5a6ae6e52fc95ceb53200975ef2c81c206 Mon Sep 17 00:00:00 2001 From: Kalle Pokki Date: Wed, 1 Nov 2006 15:08:13 +0200 Subject: [POWERPC] CPM_UART: Fix non-console initialisation The cpm_uart driver is initialised incorrectly, if there is a frame buffer console, and CONFIG_SERIAL_CPM_CONSOLE is defined. The driver fails to call cpm_uart_init_portdesc() and set_lineif() in this case. Signed-off-by: Kalle Pokki Signed-off-by: Vitaly Bordug Signed-off-by: Paul Mackerras --- drivers/serial/cpm_uart/cpm_uart.h | 2 +- drivers/serial/cpm_uart/cpm_uart_core.c | 11 ++++++----- drivers/serial/cpm_uart/cpm_uart_cpm1.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index a8f894c78194..69715e556506 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h @@ -88,7 +88,7 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; /* these are located in their respective files */ void cpm_line_cr_cmd(int line, int cmd); -int cpm_uart_init_portdesc(void); +int __init cpm_uart_init_portdesc(void); int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); void cpm_uart_freebuf(struct uart_cpm_port *pinfo); diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index 32fd8c83bd8e..7a3b97fdf8d1 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -1349,11 +1349,10 @@ static int cpm_uart_init(void) { pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n"); pr_info( "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n"); -#ifndef CONFIG_SERIAL_CPM_CONSOLE - ret = cpm_uart_init_portdesc(); - if (ret) - return ret; -#endif + + /* Don't run this again, if the console driver did it already */ + if (cpm_uart_nr == 0) + cpm_uart_init_portdesc(); cpm_reg.nr = cpm_uart_nr; ret = uart_register_driver(&cpm_reg); @@ -1365,6 +1364,8 @@ static int cpm_uart_init(void) { int con = cpm_uart_port_map[i]; cpm_uart_ports[con].port.line = i; cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF; + if (cpm_uart_ports[con].set_lineif) + cpm_uart_ports[con].set_lineif(&cpm_uart_ports[con]); uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port); } diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 95afc37297a8..08e55fdc882a 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c @@ -184,7 +184,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo) } /* Setup any dynamic params in the uart desc */ -int cpm_uart_init_portdesc(void) +int __init cpm_uart_init_portdesc(void) { pr_debug("CPM uart[-]:init portdesc\n"); -- cgit v1.2.3 From 0daa2303028a63dbd1b2e38f10854f0f7bf1ef9a Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 8 Nov 2006 19:51:01 -0800 Subject: [PATCH] bonding: lockdep annotation ============================================= [ INFO: possible recursive locking detected ] 2.6.17-1.2600.fc6 #1 Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c0bbddae4ec4..17a461152d39 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4692,6 +4692,8 @@ static int bond_check_params(struct bond_params *params) return 0; } +static struct lock_class_key bonding_netdev_xmit_lock_key; + /* Create a new bond based on the specified name and bonding parameters. * Caller must NOT hold rtnl_lock; we need to release it here before we * set up our sysfs entries. @@ -4727,6 +4729,9 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond if (res < 0) { goto out_bond; } + + lockdep_set_class(&bond_dev->_xmit_lock, &bonding_netdev_xmit_lock_key); + if (newbond) *newbond = bond_dev->priv; -- cgit v1.2.3 From ace48ffb5d6c927c5a98048d93543e1cae0eebd0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 8 Nov 2006 19:51:03 -0800 Subject: [PATCH] com20020 build fix com20020.c needs to export functions if either of the ISA or PCI modules are built as loadable modules. Or they could always be exported. WARNING: "com20020_found" [drivers/net/arcnet/com20020-pci.ko] undefined! WARNING: "com20020_check" [drivers/net/arcnet/com20020-pci.ko] undefined! Signed-off-by: Randy Dunlap Cc: Toralf Forster Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/arcnet/com20020.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c index 0dc70c7b7940..aa9dd8f11269 100644 --- a/drivers/net/arcnet/com20020.c +++ b/drivers/net/arcnet/com20020.c @@ -337,13 +337,16 @@ static void com20020_set_mc_list(struct net_device *dev) } } -#ifdef MODULE - +#if defined(CONFIG_ARCNET_COM20020_PCI_MODULE) || \ + defined(CONFIG_ARCNET_COM20020_ISA_MODULE) EXPORT_SYMBOL(com20020_check); EXPORT_SYMBOL(com20020_found); +#endif MODULE_LICENSE("GPL"); +#ifdef MODULE + int init_module(void) { BUGLVL(D_NORMAL) printk(VERSION); -- cgit v1.2.3 From 92b1f905637bbd79fcd430a09737fd97061eb405 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Wed, 8 Nov 2006 19:49:15 -0800 Subject: [PATCH] drivers cris: return on NULL dev_alloc_skb() If the next descriptor array entry cannot be allocated by dev_alloc_skb(), return immediately so it is not dereferenced later. We cannot register the device with a partial descriptor list. Cc: Mikael Starvik Signed-off-by: David Rientjes Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/cris/eth_v10.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c index 966b563e42bb..a03d781f6d0a 100644 --- a/drivers/net/cris/eth_v10.c +++ b/drivers/net/cris/eth_v10.c @@ -509,6 +509,8 @@ etrax_ethernet_init(void) * does not share cacheline with any other data (to avoid cache bug) */ RxDescList[i].skb = dev_alloc_skb(MAX_MEDIA_DATA_SIZE + 2 * L1_CACHE_BYTES); + if (!RxDescList[i].skb) + return -ENOMEM; RxDescList[i].descr.ctrl = 0; RxDescList[i].descr.sw_len = MAX_MEDIA_DATA_SIZE; RxDescList[i].descr.next = virt_to_phys(&RxDescList[i + 1]); -- cgit v1.2.3 From e033351d5359f348d2913eb83fbb37023d8f21af Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Sun, 12 Nov 2006 18:05:09 +0100 Subject: [WATCHDOG] Add iTCO vendor specific support Add vendor specific support to the intel TCO timer based watchdog devices. At this moment we only have additional support for some SuperMicro Inc. motherboards. Signed-off-by: Robert Seretny Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 8 + drivers/char/watchdog/Makefile | 2 +- drivers/char/watchdog/iTCO_vendor_support.c | 307 ++++++++++++++++++++++++++++ drivers/char/watchdog/iTCO_wdt.c | 29 ++- 4 files changed, 342 insertions(+), 4 deletions(-) create mode 100644 drivers/char/watchdog/iTCO_vendor_support.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index d3e99982b69a..a52ecad7d56c 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -340,6 +340,14 @@ config ITCO_WDT To compile this driver as a module, choose M here: the module will be called iTCO_wdt. +config ITCO_VENDOR_SUPPORT + bool "Intel TCO Timer/Watchdog Specific Vendor Support" + depends on ITCO_WDT + ---help--- + Add vendor specific support to the intel TCO timer based watchdog + devices. At this moment we only have additional support for some + SuperMicro Inc. motherboards. + config SC1200_WDT tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" depends on WATCHDOG && X86 diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index e6a9f6f1d4b7..81abdfa10a07 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -47,7 +47,7 @@ obj-$(CONFIG_IBMASR) += ibmasr.o obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o -obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o +obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o diff --git a/drivers/char/watchdog/iTCO_vendor_support.c b/drivers/char/watchdog/iTCO_vendor_support.c new file mode 100644 index 000000000000..415083990097 --- /dev/null +++ b/drivers/char/watchdog/iTCO_vendor_support.c @@ -0,0 +1,307 @@ +/* + * intel TCO vendor specific watchdog driver support + * + * (c) Copyright 2006 Wim Van Sebroeck . + * + * 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. + * + * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +/* Module and version information */ +#define DRV_NAME "iTCO_vendor_support" +#define DRV_VERSION "1.01" +#define DRV_RELDATE "11-Nov-2006" +#define PFX DRV_NAME ": " + +/* Includes */ +#include /* For module specific items */ +#include /* For new moduleparam's */ +#include /* For standard types (like size_t) */ +#include /* For the -ENODEV/... values */ +#include /* For printk/panic/... */ +#include /* For __init/__exit/... */ +#include /* For io-port access */ + +#include /* For inb/outb/... */ + +/* iTCO defines */ +#define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */ +#define TCOBASE acpibase + 0x60 /* TCO base address */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ + +/* List of vendor support modes */ +#define SUPERMICRO_OLD_BOARD 1 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ +#define SUPERMICRO_NEW_BOARD 2 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */ + +static int vendorsupport = 0; +module_param(vendorsupport, int, 0); +MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); + +/* + * Vendor Specific Support + */ + +/* + * Vendor Support: 1 + * Board: Super Micro Computer Inc. 370SSE+-OEM1/P3TSSE + * iTCO chipset: ICH2 + * + * Code contributed by: R. Seretny + * Documentation obtained by R. Seretny from SuperMicro Technical Support + * + * To enable Watchdog function: + * BIOS setup -> Power -> TCO Logic SMI Enable -> Within5Minutes + * This setting enables SMI to clear the watchdog expired flag. + * If BIOS or CPU fail which may cause SMI hang, then system will + * reboot. When application starts to use watchdog function, + * application has to take over the control from SMI. + * + * For P3TSSE, J36 jumper needs to be removed to enable the Watchdog + * function. + * + * Note: The system will reboot when Expire Flag is set TWICE. + * So, if the watchdog timer is 20 seconds, then the maximum hang + * time is about 40 seconds, and the minimum hang time is about + * 20.6 seconds. + */ + +static void supermicro_old_pre_start(unsigned long acpibase) +{ + unsigned long val32; + + val32 = inl(SMI_EN); + val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ + outl(val32, SMI_EN); /* Needed to activate watchdog */ +} + +static void supermicro_old_pre_stop(unsigned long acpibase) +{ + unsigned long val32; + + val32 = inl(SMI_EN); + val32 &= 0x00002000; /* Turn on SMI clearing watchdog */ + outl(val32, SMI_EN); /* Needed to deactivate watchdog */ +} + +static void supermicro_old_pre_keepalive(unsigned long acpibase) +{ + /* Reload TCO Timer (done in iTCO_wdt_keepalive) + */ + /* Clear "Expire Flag" (Bit 3 of TC01_STS register) */ + outb(0x08, TCO1_STS); +} + +/* + * Vendor Support: 2 + * Board: Super Micro Computer Inc. P4SBx, P4DPx + * iTCO chipset: ICH4 + * + * Code contributed by: R. Seretny + * Documentation obtained by R. Seretny from SuperMicro Technical Support + * + * To enable Watchdog function: + * 1. BIOS + * For P4SBx: + * BIOS setup -> Advanced -> Integrated Peripherals -> Watch Dog Feature + * For P4DPx: + * BIOS setup -> Advanced -> I/O Device Configuration -> Watch Dog + * This setting enables or disables Watchdog function. When enabled, the + * default watchdog timer is set to be 5 minutes (about 4’35”). It is + * enough to load and run the OS. The application (service or driver) has + * to take over the control once OS is running up and before watchdog + * expires. + * + * 2. JUMPER + * For P4SBx: JP39 + * For P4DPx: JP37 + * This jumper is used for safety. Closed is enabled. This jumper + * prevents user enables watchdog in BIOS by accident. + * + * To enable Watch Dog function, both BIOS and JUMPER must be enabled. + * + * The documentation lists motherboards P4SBx and P4DPx series as of + * 20-March-2002. However, this code works flawlessly with much newer + * motherboards, such as my X6DHR-8G2 (SuperServer 6014H-82). + * + * The original iTCO driver as written does not actually reset the + * watchdog timer on these machines, as a result they reboot after five + * minutes. + * + * NOTE: You may leave the Watchdog function disabled in the SuperMicro + * BIOS to avoid a "boot-race"... This driver will enable watchdog + * functionality even if it's disabled in the BIOS once the /dev/watchdog + * file is opened. + */ + +/* I/O Port's */ +#define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */ +#define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */ + +/* Control Register's */ +#define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */ +#define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */ + +#define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */ + +#define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */ + +#define SM_ENDWATCH 0xAA /* Watchdog lock control page */ + +#define SM_COUNTMODE 0xf5 /* Watchdog count mode select */ + /* (Bit 3: 0 = seconds, 1 = minutes */ + +#define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */ + +#define SM_RESETCONTROL 0xf7 /* Watchdog reset control */ + /* Bit 6: timer is reset by kbd interrupt */ + /* Bit 7: timer is reset by mouse interrupt */ + +static void supermicro_new_unlock_watchdog(void) +{ + outb(SM_WATCHPAGE, SM_REGINDEX); /* Write 0x87 to port 0x2e twice */ + outb(SM_WATCHPAGE, SM_REGINDEX); + + outb(SM_CTLPAGESW, SM_REGINDEX); /* Switch to watchdog control page */ + outb(SM_CTLPAGE, SM_DATAIO); +} + +static void supermicro_new_lock_watchdog(void) +{ + outb(SM_ENDWATCH, SM_REGINDEX); +} + +static void supermicro_new_pre_start(unsigned int heartbeat) +{ + unsigned int val; + + supermicro_new_unlock_watchdog(); + + /* Watchdog timer setting needs to be in seconds*/ + outb(SM_COUNTMODE, SM_REGINDEX); + val = inb(SM_DATAIO); + val &= 0xF7; + outb(val, SM_DATAIO); + + /* Write heartbeat interval to WDOG */ + outb (SM_WATCHTIMER, SM_REGINDEX); + outb((heartbeat & 255), SM_DATAIO); + + /* Make sure keyboard/mouse interrupts don't interfere */ + outb(SM_RESETCONTROL, SM_REGINDEX); + val = inb(SM_DATAIO); + val &= 0x3f; + outb(val, SM_DATAIO); + + /* enable watchdog by setting bit 0 of Watchdog Enable to 1 */ + outb(SM_WATCHENABLE, SM_REGINDEX); + val = inb(SM_DATAIO); + val |= 0x01; + outb(val, SM_DATAIO); + + supermicro_new_lock_watchdog(); +} + +static void supermicro_new_pre_stop(void) +{ + unsigned int val; + + supermicro_new_unlock_watchdog(); + + /* disable watchdog by setting bit 0 of Watchdog Enable to 0 */ + outb(SM_WATCHENABLE, SM_REGINDEX); + val = inb(SM_DATAIO); + val &= 0xFE; + outb(val, SM_DATAIO); + + supermicro_new_lock_watchdog(); +} + +static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat) +{ + supermicro_new_unlock_watchdog(); + + /* reset watchdog timeout to heartveat value */ + outb(SM_WATCHTIMER, SM_REGINDEX); + outb((heartbeat & 255), SM_DATAIO); + + supermicro_new_lock_watchdog(); +} + +/* + * Generic Support Functions + */ + +void iTCO_vendor_pre_start(unsigned long acpibase, + unsigned int heartbeat) +{ + if (vendorsupport == SUPERMICRO_OLD_BOARD) + supermicro_old_pre_start(acpibase); + else if (vendorsupport == SUPERMICRO_NEW_BOARD) + supermicro_new_pre_start(heartbeat); +} +EXPORT_SYMBOL(iTCO_vendor_pre_start); + +void iTCO_vendor_pre_stop(unsigned long acpibase) +{ + if (vendorsupport == SUPERMICRO_OLD_BOARD) + supermicro_old_pre_stop(acpibase); + else if (vendorsupport == SUPERMICRO_NEW_BOARD) + supermicro_new_pre_stop(); +} +EXPORT_SYMBOL(iTCO_vendor_pre_stop); + +void iTCO_vendor_pre_keepalive(unsigned long acpibase, unsigned int heartbeat) +{ + if (vendorsupport == SUPERMICRO_OLD_BOARD) + supermicro_old_pre_keepalive(acpibase); + else if (vendorsupport == SUPERMICRO_NEW_BOARD) + supermicro_new_pre_set_heartbeat(heartbeat); +} +EXPORT_SYMBOL(iTCO_vendor_pre_keepalive); + +void iTCO_vendor_pre_set_heartbeat(unsigned int heartbeat) +{ + if (vendorsupport == SUPERMICRO_NEW_BOARD) + supermicro_new_pre_set_heartbeat(heartbeat); +} +EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat); + +int iTCO_vendor_check_noreboot_on(void) +{ + switch(vendorsupport) { + case SUPERMICRO_OLD_BOARD: + return 0; + default: + return 1; + } +} +EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); + +static int __init iTCO_vendor_init_module(void) +{ + printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport); + return 0; +} + +static void __exit iTCO_vendor_exit_module(void) +{ + printk (KERN_INFO PFX "Module Unloaded\n"); +} + +module_init(iTCO_vendor_init_module); +module_exit(iTCO_vendor_exit_module); + +MODULE_AUTHOR("Wim Van Sebroeck , R. Seretny "); +MODULE_DESCRIPTION("Intel TCO Vendor Specific WatchDog Timer Driver Support"); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL"); + diff --git a/drivers/char/watchdog/iTCO_wdt.c b/drivers/char/watchdog/iTCO_wdt.c index b6f29cb8bd39..7eac922df867 100644 --- a/drivers/char/watchdog/iTCO_wdt.c +++ b/drivers/char/watchdog/iTCO_wdt.c @@ -48,8 +48,8 @@ /* Module and version information */ #define DRV_NAME "iTCO_wdt" -#define DRV_VERSION "1.00" -#define DRV_RELDATE "08-Oct-2006" +#define DRV_VERSION "1.01" +#define DRV_RELDATE "11-Nov-2006" #define PFX DRV_NAME ": " /* Includes */ @@ -189,6 +189,21 @@ static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); +/* iTCO Vendor Specific Support hooks */ +#ifdef CONFIG_ITCO_VENDOR_SUPPORT +extern void iTCO_vendor_pre_start(unsigned long, unsigned int); +extern void iTCO_vendor_pre_stop(unsigned long); +extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); +extern void iTCO_vendor_pre_set_heartbeat(unsigned int); +extern int iTCO_vendor_check_noreboot_on(void); +#else +#define iTCO_vendor_pre_start(acpibase, heartbeat) {} +#define iTCO_vendor_pre_stop(acpibase) {} +#define iTCO_vendor_pre_keepalive(acpibase,heartbeat) {} +#define iTCO_vendor_pre_set_heartbeat(heartbeat) {} +#define iTCO_vendor_check_noreboot_on() 1 /* 1=check noreboot; 0=don't check */ +#endif + /* * Some TCO specific functions */ @@ -249,6 +264,8 @@ static int iTCO_wdt_start(void) spin_lock(&iTCO_wdt_private.io_lock); + iTCO_vendor_pre_start(iTCO_wdt_private.ACPIBASE, heartbeat); + /* disable chipset's NO_REBOOT bit */ if (iTCO_wdt_unset_NO_REBOOT_bit()) { printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); @@ -273,6 +290,8 @@ static int iTCO_wdt_stop(void) spin_lock(&iTCO_wdt_private.io_lock); + iTCO_vendor_pre_stop(iTCO_wdt_private.ACPIBASE); + /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */ val = inw(TCO1_CNT); val |= 0x0800; @@ -293,6 +312,8 @@ static int iTCO_wdt_keepalive(void) { spin_lock(&iTCO_wdt_private.io_lock); + iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); + /* Reload the timer by writing to the TCO Timer Counter register */ if (iTCO_wdt_private.iTCO_version == 2) { outw(0x01, TCO_RLD); @@ -319,6 +340,8 @@ static int iTCO_wdt_set_heartbeat(int t) ((iTCO_wdt_private.iTCO_version == 1) && (tmrval > 0x03f))) return -EINVAL; + iTCO_vendor_pre_set_heartbeat(tmrval); + /* Write new heartbeat to watchdog */ if (iTCO_wdt_private.iTCO_version == 2) { spin_lock(&iTCO_wdt_private.io_lock); @@ -569,7 +592,7 @@ static int iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, } /* Check chipset's NO_REBOOT bit */ - if (iTCO_wdt_unset_NO_REBOOT_bit()) { + if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) { printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); ret = -ENODEV; /* Cannot reset NO_REBOOT bit */ goto out; -- cgit v1.2.3 From d027c4dc7d6e35a4e43dbcc178f0bf3359814306 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 3 Nov 2006 07:14:32 -0300 Subject: V4L/DVB (4795): Tda826x: use correct max frequency sparse "defined twice" warning Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda826x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda826x.c b/drivers/media/dvb/frontends/tda826x.c index eeab26bd36ed..34815b0b97e4 100644 --- a/drivers/media/dvb/frontends/tda826x.c +++ b/drivers/media/dvb/frontends/tda826x.c @@ -121,7 +121,7 @@ static struct dvb_tuner_ops tda826x_tuner_ops = { .info = { .name = "Philips TDA826X", .frequency_min = 950000, - .frequency_min = 2175000 + .frequency_max = 2175000 }, .release = tda826x_release, .sleep = tda826x_sleep, -- cgit v1.2.3 From ff97d93d6a311759db1b74b9b90dd6bcb8ce0aee Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Fri, 3 Nov 2006 10:45:52 -0300 Subject: V4L/DVB (4802): Cx88: fix remote control on WinFast 2000XP Expert fix remote control on WinFast 2000XP Expert by setting timing back to 1 ms, like it was in the original patch by Robert Reid. Signed-off-by: Hermann Pitton Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-input.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index ee48995a4ab5..57e1c024a547 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -202,13 +202,19 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->sampling = 1; break; case CX88_BOARD_WINFAST_DTV2000H: - case CX88_BOARD_WINFAST2000XP_EXPERT: ir_codes = ir_codes_winfast; ir->gpio_addr = MO_GP0_IO; ir->mask_keycode = 0x8f8; ir->mask_keyup = 0x100; ir->polling = 50; /* ms */ break; + case CX88_BOARD_WINFAST2000XP_EXPERT: + ir_codes = ir_codes_winfast; + ir->gpio_addr = MO_GP0_IO; + ir->mask_keycode = 0x8f8; + ir->mask_keyup = 0x100; + ir->polling = 1; /* ms */ + break; case CX88_BOARD_IODATA_GVBCTV7E: ir_codes = ir_codes_iodata_bctv7e; ir->gpio_addr = MO_GP0_IO; @@ -216,7 +222,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) ir->mask_keydown = 0x02; ir->polling = 5; /* ms */ break; - case CX88_BOARD_PROLINK_PLAYTVPVR: + case CX88_BOARD_PROLINK_PLAYTVPVR: case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO: ir_codes = ir_codes_pixelview; ir->gpio_addr = MO_GP1_IO; -- cgit v1.2.3 From ce48d5ecf3f52378064f317e0094b601508e9b3e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 5 Nov 2006 09:02:13 -0300 Subject: V4L/DVB (4804): Fix missing i2c dependency for saa7110 drivers/media/video/saa7110.c:112: undefined reference to `i2c_master_send' drivers/built-in.o: In function `saa7110_read': drivers/media/video/saa7110.c:130: undefined reference to `i2c_smbus_read_byte' drivers/media/video/saa7110.c:130: undefined reference to `i2c_smbus_read_byte' Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fbe5b6168cc2..bf267552941f 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -186,7 +186,7 @@ config VIDEO_KS0127 config VIDEO_SAA7110 tristate "Philips SAA7110 video decoder" - depends on VIDEO_V4L1 + depends on VIDEO_V4L1 && I2C ---help--- Support for the Philips SAA7110 video decoders. -- cgit v1.2.3 From 450efcfd2e1d941e302a8c89322fbfcef237be98 Mon Sep 17 00:00:00 2001 From: "pasky@ucw.cz" Date: Sun, 12 Nov 2006 14:22:32 -0300 Subject: V4L/DVB (4814): Remote support for Avermedia 777 I didn't test it personally since I don't have this card, but A16AR uses the same interface and that one certainly does work perfectly (see the next patch). This patch was originally sent in http://marc.theaimsgroup.com/?l=linux-video&m=114743413825375&w=2 https://www.redhat.com/mailman/private/video4linux-list/2006-May/msg00103.html but never got applied. This version has some trivial modifications and drops the weird gpio hack (it's not clear what practical purpose does it serve). Signed-off-by: Jose Alberto Reguero Signed-off-by: Petr Baudis Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 1 + drivers/media/video/saa7134/saa7134-input.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c9d8e3b9cc37..94324b3c34eb 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3718,6 +3718,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: + case SAA7134_BOARD_AVERMEDIA_777: /* case SAA7134_BOARD_SABRENT_SBTTVFM: */ /* not finished yet */ case SAA7134_BOARD_VIDEOMATE_TV_PVR: case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS: diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index ff5991136f4e..e8dcb6f9f8f1 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -194,6 +194,14 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; + case SAA7134_BOARD_AVERMEDIA_777: + ir_codes = ir_codes_avermedia; + mask_keycode = 0x02F200; + mask_keydown = 0x000400; + polling = 50; // ms + /* Without this we won't receive key up events */ + saa_setb(SAA7134_GPIO_GPMODE1, 0x1); + saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); case SAA7134_BOARD_KWORLD_TERMINATOR: ir_codes = ir_codes_pixelview; mask_keycode = 0x00001f; -- cgit v1.2.3 From 29e0f1a136d39c5683d998741911b769d0172d52 Mon Sep 17 00:00:00 2001 From: "pasky@ucw.cz" Date: Sun, 12 Nov 2006 14:23:32 -0300 Subject: V4L/DVB (4815): Remote support for Avermedia A16AR The remote as well as the GPIO interface is the same as what comes with 777. For an example of mplayer lirc configuration, see http://pasky.or.cz/~pasky/dev/v4l/lircrc Signed-off-by: Petr Baudis Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 2 +- drivers/media/video/saa7134/saa7134-input.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 94324b3c34eb..1a402e45912e 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3735,6 +3735,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_FLYDVBT_LR301: case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_PROTEUS_2309: + case SAA7134_BOARD_AVERMEDIA_A16AR: dev->has_remote = SAA7134_REMOTE_GPIO; break; case SAA7134_BOARD_FLYDVBS_LR300: @@ -3773,7 +3774,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_writeb(SAA7134_GPIO_GPMODE3, 0x08); saa_writeb(SAA7134_GPIO_GPSTATUS3, 0x00); break; - case SAA7134_BOARD_AVERMEDIA_A16AR: case SAA7134_BOARD_AVERMEDIA_CARDBUS: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index e8dcb6f9f8f1..7f62403b1953 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -185,7 +185,6 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_STUDIO_305: case SAA7134_BOARD_AVERMEDIA_STUDIO_307: case SAA7134_BOARD_AVERMEDIA_GO_007_FM: - case SAA7134_BOARD_AVERMEDIA_A16AR: ir_codes = ir_codes_avermedia; mask_keycode = 0x0007C8; mask_keydown = 0x000010; @@ -195,6 +194,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; case SAA7134_BOARD_AVERMEDIA_777: + case SAA7134_BOARD_AVERMEDIA_A16AR: ir_codes = ir_codes_avermedia; mask_keycode = 0x02F200; mask_keydown = 0x000400; -- cgit v1.2.3 From 0871a8849b80646074cd28b2b078c8e002e51282 Mon Sep 17 00:00:00 2001 From: "pasky@ucw.cz" Date: Sun, 12 Nov 2006 14:24:57 -0300 Subject: V4L/DVB (4816): Change tuner type for Avermedia A16AR This changes it from TDA8290 which is allegedly very unlikely to TD1316 which is allegedly very likely. I didn't get it to work with either, but expected that this got applied when Mauro sent it to me, so here it goes again; feel free to drop it to the floor. :-) Signed-off-by: Petr Baudis Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 1a402e45912e..51f0cfdcb680 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2969,7 +2969,7 @@ struct saa7134_board saa7134_boards[] = { /* Petr Baudis */ .name = "AVerMedia TV Hybrid A16AR", .audio_clock = 0x187de7, - .tuner_type = TUNER_PHILIPS_TDA8290, /* untested */ + .tuner_type = TUNER_PHILIPS_TD1316, /* untested */ .radio_type = TUNER_TEA5767, /* untested */ .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, -- cgit v1.2.3 From fef4fa1475db6a53237e29451c88c15167d69cc4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 9 Nov 2006 17:25:28 -0300 Subject: V4L/DVB (4817): Fix uses of "&&" where "&" was intended Fix uses of "&&" where "&" was intended in bttv-cards.c and tveeprom.c Signed-off-by: Jean Delvare Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 2 +- drivers/media/video/tveeprom.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index a84903e0d810..21ebe8f13815 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -4001,7 +4001,7 @@ static void __devinit init_PXC200(struct bttv *btv) * - sleep 1ms * - write 0x0E * read from GPIO_DATA into buf (uint_32) - * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 ) + * - if ( buf>>18 & 0x01 ) || ( buf>>19 & 0x01 != 0 ) * error. ERROR_CPLD_Check_Failed. */ /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index e6baaee038bf..6b9ef731b83a 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -468,7 +468,7 @@ void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, (eeprom_data[i+6] << 8) + (eeprom_data[i+7] << 16); - if ( (eeprom_data[i + 8] && 0xf0) && + if ( (eeprom_data[i + 8] & 0xf0) && (tvee->serial_number < 0xffffff) ) { tvee->MAC_address[0] = 0x00; tvee->MAC_address[1] = 0x0D; -- cgit v1.2.3 From 6f36fbb242442184d314e305199bb9a449be4f67 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 9 Nov 2006 17:36:44 -0300 Subject: V4L/DVB (4818): Flexcop-usb: fix debug printk .. fix debug printk. Why, oh why, one would want to do (u16 & 0xff) << 8 and print it with %02x format? Acked-by: Patrick Boettcher Signed-off-by: Alexey Dobriyan Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c index 2853ea1bdaf1..87fb75f0d1cf 100644 --- a/drivers/media/dvb/b2c2/flexcop-usb.c +++ b/drivers/media/dvb/b2c2/flexcop-usb.c @@ -246,7 +246,7 @@ static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb, wIndex = (chipaddr << 8 ) | addr; deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req, - ((wValue && 0xff) << 8),wValue >> 8,((wIndex && 0xff) << 8),wIndex >> 8); + wValue & 0xff, wValue >> 8, wIndex & 0xff, wIndex >> 8); len = usb_control_msg(fc_usb->udev,pipe, req, -- cgit v1.2.3 From d67afe5ed00070de0965bfc98de5f6ed3a80a73e Mon Sep 17 00:00:00 2001 From: David Miller Date: Fri, 10 Nov 2006 12:27:48 -0800 Subject: [PATCH] pci: don't try to remove sysfs files before they are setup. The PCI sysfs attributes are created after the initial PCI bus scan. With the addition of more return value checking and assertions in the device and sysfs layers we now can get dumps like this on sparc64: [ 20.135032] Call Trace: [ 20.135042] [0000000000537f88] pci_remove_bus_device+0x30/0xc0 [ 20.135076] [000000000078f890] pci_fill_in_pbm_cookies+0x98/0x440 [ 20.135109] [000000000042e828] sabre_scan_bus+0x230/0x400 [ 20.135139] [000000000078c710] pcibios_init+0x58/0xa0 [ 20.135159] [0000000000416f14] init+0x9c/0x2e0 [ 20.135190] [0000000000417a50] kernel_thread+0x38/0x60 [ 20.135211] [0000000000417170] rest_init+0x18/0x40 [ 20.135514] PCI0(PBMB): Bus running at 33MHz It's triggering because removal of the "config" PCI sysfs file for the device fails. On sparc64, after probing the device, we'll delete the PCI device via pci_remove_bus_device() if we cannot find the firmware device tree node corresponding to it. This is fine, but at this point the sysfs files for the PCI device won't be setup yet. So we should not try to do anything in pci_remove_sysfs_dev_files() if pci_sysfs_init() has not run yet. Signed-off-by: David S. Miller Acked-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pci/pci-sysfs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index a1d2e979b17f..f952bfea48a6 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -642,6 +642,9 @@ err: */ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) { + if (!sysfs_initialized) + return; + if (pdev->cfg_size < 4096) sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); else -- cgit v1.2.3 From 1a4b0fc503ff4149f5915be4aeb179b9453cf485 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Fri, 10 Nov 2006 12:27:49 -0800 Subject: [PATCH] mspec driver build fix Fix MSPEC driver to build for non SN2 enabled configs as the driver should work in cached and uncached modes (no fetchop) on these systems. In addition make MSPEC select IA64_UNCACHED_ALLOCATOR, which is required for it and move it to arch/ia64/Kconfig to avoid warnings on non ia64 architectures running allmodconfig. Once the Kconfig code is fixed, we can move it back. Signed-off-by: Jes Sorensen Cc: Fernando Luis Vzquez Cao Cc: "Luck, Tony" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/Kconfig | 9 +++++++++ drivers/char/Kconfig | 8 -------- drivers/char/mspec.c | 8 +++++++- include/asm-ia64/sn/addrs.h | 6 +++++- 4 files changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 14682396f7f7..683b12c6f76c 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -484,6 +484,15 @@ source "net/Kconfig" source "drivers/Kconfig" +config MSPEC + tristate "Memory special operations driver" + depends on IA64 + select IA64_UNCACHED_ALLOCATOR + help + If you have an ia64 and you want to enable memory special + operations support (formerly known as fetchop), say Y here, + otherwise say N. + source "fs/Kconfig" source "lib/Kconfig" diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 39a9f8cc6412..2af12fc45115 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -409,14 +409,6 @@ config SGI_MBCS If you have an SGI Altix with an attached SABrick say Y or M here, otherwise say N. -config MSPEC - tristate "Memory special operations driver" - depends on IA64 - help - If you have an ia64 and you want to enable memory special - operations support (formerly known as fetchop), say Y here, - otherwise say N. - source "drivers/serial/Kconfig" config UNIX98_PTYS diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 5c0dec39cf6c..235e89226112 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -72,7 +72,11 @@ enum { MSPEC_UNCACHED }; +#ifdef CONFIG_SGI_SN static int is_sn2; +#else +#define is_sn2 0 +#endif /* * One of these structures is allocated when an mspec region is mmaped. The @@ -211,7 +215,7 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) if (vdata->type == MSPEC_FETCHOP) paddr = TO_AMO(maddr); else - paddr = __pa(TO_CAC(maddr)); + paddr = maddr & ~__IA64_UNCACHED_OFFSET; pfn = paddr >> PAGE_SHIFT; @@ -335,6 +339,7 @@ mspec_init(void) * The fetchop device only works on SN2 hardware, uncached and cached * memory drivers should both be valid on all ia64 hardware */ +#ifdef CONFIG_SGI_SN if (ia64_platform_is("sn2")) { is_sn2 = 1; if (is_shub2()) { @@ -363,6 +368,7 @@ mspec_init(void) goto free_scratch_pages; } } +#endif ret = misc_register(&cached_miscdev); if (ret) { printk(KERN_ERR "%s: failed to register device %i\n", diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index 1d9efe541662..e715c794b186 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -136,9 +136,13 @@ */ #define TO_PHYS(x) (TO_PHYS_MASK & (x)) #define TO_CAC(x) (CAC_BASE | TO_PHYS(x)) +#ifdef CONFIG_SGI_SN #define TO_AMO(x) (AMO_BASE | TO_PHYS(x)) #define TO_GET(x) (GET_BASE | TO_PHYS(x)) - +#else +#define TO_AMO(x) ({ BUG(); x; }) +#define TO_GET(x) ({ BUG(); x; }) +#endif /* * Covert from processor physical address to II/TIO physical address: -- cgit v1.2.3 From 7947d2cc2c2e01125a393de83862d02b621999fe Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Fri, 10 Nov 2006 12:27:50 -0800 Subject: [PATCH] IPMI: Fix more && typos Fix improper use of "&&" when "&" was intended. Signed-off-by: Jean Delvare Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 0b07ca1b71fa..a41b8df24073 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1854,7 +1854,7 @@ static ssize_t provides_dev_sdrs_show(struct device *dev, struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 10, "%u\n", - bmc->id.device_revision && 0x80 >> 7); + (bmc->id.device_revision & 0x80) >> 7); } static ssize_t revision_show(struct device *dev, struct device_attribute *attr, @@ -1863,7 +1863,7 @@ static ssize_t revision_show(struct device *dev, struct device_attribute *attr, struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 20, "%u\n", - bmc->id.device_revision && 0x0F); + bmc->id.device_revision & 0x0F); } static ssize_t firmware_rev_show(struct device *dev, -- cgit v1.2.3 From e40c67597eac7a0b0e676867517b01a5a57f7b4b Mon Sep 17 00:00:00 2001 From: Wink Saville Date: Fri, 10 Nov 2006 12:27:52 -0800 Subject: [PATCH] Patch for nvidia divide by zero error for 7600 pci-express card The following patch resolves the divide by zero error I encountered on my system: http://marc.10east.com/?l=linux-fbdev-devel&m=116058257024413&w=2 I accomplished this by merging what I thought was appropriate from: http://webcvs.freedesktop.org/xorg/driver/xf86-video-nv/src/ Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_hw.c | 12 +++++++++--- drivers/video/nvidia/nv_setup.c | 18 +++++++++++++++++- drivers/video/nvidia/nv_type.h | 1 + drivers/video/nvidia/nvidia.c | 24 ++++++++++++------------ 4 files changed, 39 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c index 9ed640d35728..ea426115c6f9 100644 --- a/drivers/video/nvidia/nv_hw.c +++ b/drivers/video/nvidia/nv_hw.c @@ -145,12 +145,18 @@ static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk, if (par->Architecture >= NV_ARCH_40) { pll = NV_RD32(par->PMC, 0x4020); - P = (pll >> 16) & 0x03; + P = (pll >> 16) & 0x07; pll = NV_RD32(par->PMC, 0x4024); M = pll & 0xFF; N = (pll >> 8) & 0xFF; - MB = (pll >> 16) & 0xFF; - NB = (pll >> 24) & 0xFF; + if (((par->Chipset & 0xfff0) == 0x0290) || + ((par->Chipset & 0xfff0) == 0x0390)) { + MB = 1; + NB = 1; + } else { + MB = (pll >> 16) & 0xFF; + NB = (pll >> 24) & 0xFF; + } *MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P; pll = NV_RD32(par->PMC, 0x4000); diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index a18a9aebf05f..61dc46fecf2b 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -359,6 +359,7 @@ int NVCommonSetup(struct fb_info *info) case 0x0186: case 0x0187: case 0x018D: + case 0x0228: case 0x0286: case 0x028C: case 0x0316: @@ -382,6 +383,10 @@ int NVCommonSetup(struct fb_info *info) case 0x034C: case 0x0160: case 0x0166: + case 0x0169: + case 0x016B: + case 0x016C: + case 0x016D: case 0x00C8: case 0x00CC: case 0x0144: @@ -639,12 +644,23 @@ int NVCommonSetup(struct fb_info *info) par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1; par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033; - printk("Panel size is %i x %i\n", par->fpWidth, par->fpHeight); + printk("nvidiafb: Panel size is %i x %i\n", par->fpWidth, par->fpHeight); } if (monA) info->monspecs = *monA; + if (!par->FlatPanel || !par->twoHeads) + par->FPDither = 0; + + par->LVDS = 0; + if (par->FlatPanel && par->twoHeads) { + NV_WR32(par->PRAMDAC0, 0x08B0, 0x00010004); + if (par->PRAMDAC0[0x08b4] & 1) + par->LVDS = 1; + printk("nvidiafb: Panel is %s\n", par->LVDS ? "LVDS" : "TMDS"); + } + kfree(edidA); kfree(edidB); done: diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h index acdc26693402..86e65dea60d3 100644 --- a/drivers/video/nvidia/nv_type.h +++ b/drivers/video/nvidia/nv_type.h @@ -129,6 +129,7 @@ struct nvidia_par { int fpHeight; int PanelTweak; int paneltweak; + int LVDS; int pm_state; u32 crtcSync_read; u32 fpSyncs; diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index eb24107bcc81..538e947610e1 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1160,20 +1160,20 @@ static u32 __devinit nvidia_get_arch(struct fb_info *info) case 0x0340: /* GeForceFX 5700 */ arch = NV_ARCH_30; break; - case 0x0040: - case 0x00C0: - case 0x0120: + case 0x0040: /* GeForce 6800 */ + case 0x00C0: /* GeForce 6800 */ + case 0x0120: /* GeForce 6800 */ case 0x0130: - case 0x0140: - case 0x0160: - case 0x01D0: - case 0x0090: - case 0x0210: - case 0x0220: + case 0x0140: /* GeForce 6600 */ + case 0x0160: /* GeForce 6200 */ + case 0x01D0: /* GeForce 7200, 7300, 7400 */ + case 0x0090: /* GeForce 7800 */ + case 0x0210: /* GeForce 6800 */ + case 0x0220: /* GeForce 6200 */ case 0x0230: - case 0x0240: - case 0x0290: - case 0x0390: + case 0x0240: /* GeForce 6100 */ + case 0x0290: /* GeForce 7900 */ + case 0x0390: /* GeForce 7600 */ arch = NV_ARCH_40; break; case 0x0020: /* TNT, TNT2 */ -- cgit v1.2.3 From 09123d230a294cd3b860f4ea042235b988277f0a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 10 Nov 2006 12:27:57 -0800 Subject: [PATCH] SCSI core: always store >= 36 bytes of INQUIRY data This patch (as810c) copies a minimum of 36 bytes of INQUIRY data, even if the device claims that not all of them are valid. Often badly behaved devices put plausible data in the Vendor, Product, and Revision strings but set the Additional Length byte to a small value. Using potentially valid data is certainly better than allocating a short buffer and then reading beyond the end of it, which is what we do now. Signed-off-by: Alan Stern Cc: James Bottomley Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/scsi_scan.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index fd9e281c3bfe..94a274645f6f 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -631,12 +631,22 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, * scanning run at their own risk, or supply a user level program * that can correctly scan. */ - sdev->inquiry = kmalloc(sdev->inquiry_len, GFP_ATOMIC); - if (sdev->inquiry == NULL) { + + /* + * Copy at least 36 bytes of INQUIRY data, so that we don't + * dereference unallocated memory when accessing the Vendor, + * Product, and Revision strings. Badly behaved devices may set + * the INQUIRY Additional Length byte to a small value, indicating + * these strings are invalid, but often they contain plausible data + * nonetheless. It doesn't matter if the device sent < 36 bytes + * total, since scsi_probe_lun() initializes inq_result with 0s. + */ + sdev->inquiry = kmemdup(inq_result, + max_t(size_t, sdev->inquiry_len, 36), + GFP_ATOMIC); + if (sdev->inquiry == NULL) return SCSI_SCAN_NO_RESPONSE; - } - memcpy(sdev->inquiry, inq_result, sdev->inquiry_len); sdev->vendor = (char *) (sdev->inquiry + 8); sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); -- cgit v1.2.3 From c58121143f87930621c1a6fa9683b6862f2b42c9 Mon Sep 17 00:00:00 2001 From: Hoang-Nam Nguyen Date: Sun, 5 Nov 2006 21:42:56 +0100 Subject: IB/ehca: Use named constant for max mtu Define and use a constant EHCA_MAX_MTU instead hardcoded value. Signed-off-by: Hoang-Nam Nguyen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_av.c | 5 ++--- drivers/infiniband/hw/ehca/hipz_hw.h | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c index 3bac197f9014..214e2fdddeef 100644 --- a/drivers/infiniband/hw/ehca/ehca_av.c +++ b/drivers/infiniband/hw/ehca/ehca_av.c @@ -118,8 +118,7 @@ struct ib_ah *ehca_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) } memcpy(&av->av.grh.word_1, &gid, sizeof(gid)); } - /* for the time being we use a hard coded PMTU of 2048 Bytes */ - av->av.pmtu = 4; + av->av.pmtu = EHCA_MAX_MTU; /* dgid comes in grh.word_3 */ memcpy(&av->av.grh.word_3, &ah_attr->grh.dgid, @@ -193,7 +192,7 @@ int ehca_modify_ah(struct ib_ah *ah, struct ib_ah_attr *ah_attr) memcpy(&new_ehca_av.grh.word_1, &gid, sizeof(gid)); } - new_ehca_av.pmtu = 4; /* see also comment in create_ah() */ + new_ehca_av.pmtu = EHCA_MAX_MTU; memcpy(&new_ehca_av.grh.word_3, &ah_attr->grh.dgid, sizeof(ah_attr->grh.dgid)); diff --git a/drivers/infiniband/hw/ehca/hipz_hw.h b/drivers/infiniband/hw/ehca/hipz_hw.h index 3fc92b031c50..fad91368dc5a 100644 --- a/drivers/infiniband/hw/ehca/hipz_hw.h +++ b/drivers/infiniband/hw/ehca/hipz_hw.h @@ -45,6 +45,8 @@ #include "ehca_tools.h" +#define EHCA_MAX_MTU 4 + /* QP Table Entry Memory Map */ struct hipz_qptemm { u64 qpx_hcr; -- cgit v1.2.3 From f2c238a0c5e155acd49752c5fb93fb8d8534232b Mon Sep 17 00:00:00 2001 From: Hoang-Nam Nguyen Date: Sun, 5 Nov 2006 21:42:20 +0100 Subject: IB/ehca: Activate scaling code by default Change ehca's Kconfig to activates scaling code as default. After several measurements we saw that this feature prevents dropped packets (UD) in stress situation. Thus, enabling it helps to improve ehca's bandwidth through IPoIB. Signed-off-by: Hoang-Nam Nguyen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/Kconfig b/drivers/infiniband/hw/ehca/Kconfig index 922389b64394..727b10d89686 100644 --- a/drivers/infiniband/hw/ehca/Kconfig +++ b/drivers/infiniband/hw/ehca/Kconfig @@ -10,6 +10,7 @@ config INFINIBAND_EHCA config INFINIBAND_EHCA_SCALING bool "Scaling support (EXPERIMENTAL)" depends on IBMEBUS && INFINIBAND_EHCA && HOTPLUG_CPU && EXPERIMENTAL + default y ---help--- eHCA scaling support schedules the CQ callbacks to different CPUs. -- cgit v1.2.3 From 2ffcab6ae44b02679229ca1852526d0a6e062dd2 Mon Sep 17 00:00:00 2001 From: Tom Tucker Date: Wed, 8 Nov 2006 14:23:22 -0600 Subject: RDMA/amso1100: Fix unitialized pseudo_netdev accessed in c2_register_device Rework some load-time error handling: c2_register_device() leaked when it failed, and the function that called it didn't check the return code. Signed-off-by: Tom Tucker Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2.c | 3 ++- drivers/infiniband/hw/amso1100/c2_provider.c | 39 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2.c b/drivers/infiniband/hw/amso1100/c2.c index 9e7bd94b958a..27fe242ed435 100644 --- a/drivers/infiniband/hw/amso1100/c2.c +++ b/drivers/infiniband/hw/amso1100/c2.c @@ -1155,7 +1155,8 @@ static int __devinit c2_probe(struct pci_dev *pcidev, goto bail10; } - c2_register_device(c2dev); + if (c2_register_device(c2dev)) + goto bail10; return 0; diff --git a/drivers/infiniband/hw/amso1100/c2_provider.c b/drivers/infiniband/hw/amso1100/c2_provider.c index da98d9f71429..fef972752912 100644 --- a/drivers/infiniband/hw/amso1100/c2_provider.c +++ b/drivers/infiniband/hw/amso1100/c2_provider.c @@ -757,20 +757,17 @@ static struct net_device *c2_pseudo_netdev_init(struct c2_dev *c2dev) int c2_register_device(struct c2_dev *dev) { - int ret; + int ret = -ENOMEM; int i; /* Register pseudo network device */ dev->pseudo_netdev = c2_pseudo_netdev_init(dev); - if (dev->pseudo_netdev) { - ret = register_netdev(dev->pseudo_netdev); - if (ret) { - printk(KERN_ERR PFX - "Unable to register netdev, ret = %d\n", ret); - free_netdev(dev->pseudo_netdev); - return ret; - } - } + if (!dev->pseudo_netdev) + goto out3; + + ret = register_netdev(dev->pseudo_netdev); + if (ret) + goto out2; pr_debug("%s:%u\n", __FUNCTION__, __LINE__); strlcpy(dev->ibdev.name, "amso%d", IB_DEVICE_NAME_MAX); @@ -848,21 +845,25 @@ int c2_register_device(struct c2_dev *dev) ret = ib_register_device(&dev->ibdev); if (ret) - return ret; + goto out1; for (i = 0; i < ARRAY_SIZE(c2_class_attributes); ++i) { ret = class_device_create_file(&dev->ibdev.class_dev, c2_class_attributes[i]); - if (ret) { - unregister_netdev(dev->pseudo_netdev); - free_netdev(dev->pseudo_netdev); - ib_unregister_device(&dev->ibdev); - return ret; - } + if (ret) + goto out0; } + goto out3; - pr_debug("%s:%u\n", __FUNCTION__, __LINE__); - return 0; +out0: + ib_unregister_device(&dev->ibdev); +out1: + unregister_netdev(dev->pseudo_netdev); +out2: + free_netdev(dev->pseudo_netdev); +out3: + pr_debug("%s:%u ret=%d\n", __FUNCTION__, __LINE__, ret); + return ret; } void c2_unregister_device(struct c2_dev *dev) -- cgit v1.2.3 From b26c791e9ca3365616d40836000285931ca033d0 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 9 Nov 2006 21:02:26 +0100 Subject: RDMA/amso1100: Fix && typo Fix the AMSO1100 firmware version computation, which was broken due to "&&" being used where "&" should have. Signed-off-by: Jean Delvare Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_rnic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 21d9612a56cc..623dc95f91df 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -157,8 +157,8 @@ static int c2_rnic_query(struct c2_dev *c2dev, struct ib_device_attr *props) props->fw_ver = ((u64)be32_to_cpu(reply->fw_ver_major) << 32) | - ((be32_to_cpu(reply->fw_ver_minor) && 0xFFFF) << 16) | - (be32_to_cpu(reply->fw_ver_patch) && 0xFFFF); + ((be32_to_cpu(reply->fw_ver_minor) & 0xFFFF) << 16) | + (be32_to_cpu(reply->fw_ver_patch) & 0xFFFF); memcpy(&props->sys_image_guid, c2dev->netdev->dev_addr, 6); props->max_mr_size = 0xFFFFFFFF; props->page_size_cap = ~(C2_MIN_PAGESIZE-1); -- cgit v1.2.3 From 39798695b4bcc7b145f8910ca56195808d3a7637 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 13 Nov 2006 09:38:07 -0800 Subject: IB/mad: Fix race between cancel and receive completion When ib_cancel_mad() is called, it puts the canceled send on a list and schedules a "flushed" callback from process context. However, this leaves a window where a receive completion could be processed before the send is fully flushed. This is fine, except that ib_find_send_mad() will find the MAD and return it to the receive processing, which results in the sender getting both a successful receive and a "flushed" send completion for the same request. Understandably, this confuses the sender, which is expecting only one of these two callbacks, and leads to grief such as a use-after-free in IPoIB. Fix this by changing ib_find_send_mad() to return a send struct only if the status is still successful (and not "flushed"). The search of the send_list already had this check, so this patch just adds the same check to the search of the wait_list. Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 493f4c65c7a2..a72bcea46ff6 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1750,7 +1750,7 @@ ib_find_send_mad(struct ib_mad_agent_private *mad_agent_priv, */ (is_direct(wc->recv_buf.mad->mad_hdr.mgmt_class) || rcv_has_same_gid(mad_agent_priv, wr, wc))) - return wr; + return (wr->status == IB_WC_SUCCESS) ? wr : NULL; } /* -- cgit v1.2.3 From b71567312976305cc1ce7e9b71e7378c8bfcb40f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 13 Nov 2006 18:05:02 +0100 Subject: [PATCH] ide-cd: only set rq->errors SCSI style for block pc requests We should only set ->errors to CHECK_CONDITION and so on for requests that use this field in the SCSI manner. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/ide/ide-cd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index bddfebdf91d8..88214943d00a 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -724,7 +724,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) * if we have an error, pass back CHECK_CONDITION as the * scsi status byte */ - if (!rq->errors) + if (blk_pc_request(rq) && !rq->errors) rq->errors = SAM_STAT_CHECK_CONDITION; /* Check for tray open. */ -- cgit v1.2.3 From 4dd7406e9c7e7a5422425ef699780463490b8745 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 13 Nov 2006 09:50:11 -0800 Subject: [dvb saa7134] Fix missing 'break' for avermedia card case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 450efcfd2e1d941e302a8c89322fbfcef237be98 broke Avermedia 777 support. Added obvious missing "break" statement. Cc: José Suárez Cc: Michael Krufky Cc: Mauro Carvalho Chehab Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-input.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7f62403b1953..dee83552e681 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -202,6 +202,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) /* Without this we won't receive key up events */ saa_setb(SAA7134_GPIO_GPMODE1, 0x1); saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1); + break; case SAA7134_BOARD_KWORLD_TERMINATOR: ir_codes = ir_codes_pixelview; mask_keycode = 0x00001f; -- cgit v1.2.3 From b5bf24b94c65536d3cc2bf9039ab05b3967f7b7f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 8 Nov 2006 16:18:26 +0000 Subject: [PATCH] hpt37x: Check the enablebits Helps for PATA but SATA bridged devices lie and always set all the bits so will need the error handling fixes from Tejun. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt37x.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 7350443948c1..fce3fcdc7e79 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt37x" -#define DRV_VERSION "0.5" +#define DRV_VERSION "0.5.1" struct hpt_clock { u8 xfer_speed; @@ -453,7 +453,13 @@ static int hpt37x_pre_reset(struct ata_port *ap) { u8 scr2, ata66; struct pci_dev *pdev = to_pci_dev(ap->host->dev); - + static const struct pci_bits hpt37x_enable_bits[] = { + { 0x50, 1, 0x04, 0x04 }, + { 0x54, 1, 0x04, 0x04 } + }; + if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) + return -ENOENT; + pci_read_config_byte(pdev, 0x5B, &scr2); pci_write_config_byte(pdev, 0x5B, scr2 & ~0x01); /* Cable register now active */ @@ -488,10 +494,17 @@ static void hpt37x_error_handler(struct ata_port *ap) static int hpt374_pre_reset(struct ata_port *ap) { + static const struct pci_bits hpt37x_enable_bits[] = { + { 0x50, 1, 0x04, 0x04 }, + { 0x54, 1, 0x04, 0x04 } + }; u16 mcr3, mcr6; u8 ata66; - struct pci_dev *pdev = to_pci_dev(ap->host->dev); + + if (!pci_test_config_bits(pdev, &hpt37x_enable_bits[ap->port_no])) + return -ENOENT; + /* Do the extra channel work */ pci_read_config_word(pdev, 0x52, &mcr3); pci_read_config_word(pdev, 0x56, &mcr6); -- cgit v1.2.3 From 3f9dd27a22ff79b6b6c4eccd19e4063bff0ddc7e Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 10 Nov 2006 22:52:46 +0300 Subject: [PATCH] pata_artop: fix "& (1 >>" typo Signed-off-by: Alexey Dobriyan Signed-off-by: Jeff Garzik --- drivers/ata/pata_artop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 690828eb5226..96a098020a8f 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -92,7 +92,7 @@ static int artop6260_pre_reset(struct ata_port *ap) return -ENOENT; pci_read_config_byte(pdev, 0x49, &tmp); - if (tmp & (1 >> ap->port_no)) + if (tmp & (1 << ap->port_no)) ap->cbl = ATA_CBL_PATA40; else ap->cbl = ATA_CBL_PATA80; -- cgit v1.2.3 From 253b92ecbd3d2e9f5a79fc7632c89ac74bff16c4 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 14 Nov 2006 09:55:41 -0500 Subject: libata: fix double-completion on error A curious thing happens, however, when ata_qc_new_init fails to get an ata_queued_cmd: First, ata_qc_new_init handles the failure like this: cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1); done(cmd); Then, we return to ata_scsi_translate and do this: err_mem: cmd->result = (DID_ERROR << 16); done(cmd); It appears to me that first we set a status code indicating that we're ok but the device queue is full and finish the command, but then we blow away that status code and replace it with an error flag and finish the command a second time! That does not seem to be desirable behavior since we merely want the I/O to wait until a command slot frees up, not send errors up the block layer. In the err_mem case, we should simply exit out of ata_scsi_translate instead. Signed-off-by: Darrick J. Wong Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7af2a4ba4990..5c1fc467fc7f 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1612,9 +1612,9 @@ early_finish: err_did: ata_qc_free(qc); -err_mem: cmd->result = (DID_ERROR << 16); done(cmd); +err_mem: DPRINTK("EXIT - internal\n"); return 0; -- cgit v1.2.3 From d8f7975159f35846754d3845c9701b612c5c0624 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 14 Nov 2006 02:03:26 -0800 Subject: [PATCH] revert "PCI: quirk for IBM Dock II cardbus controllers" Fix http://bugzilla.kernel.org/show_bug.cgi?id=7264 We need to target this quirk a little more tightly, using the T20 DMI string. Cc: Pavel Kysilka Acked-by: Kristen Carlson Accardi Cc: Greg Kroah-Hartman Cc: Dominik Brodowski Cc: Daniel Ritz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pci/quirks.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 204b1c8e972b..5b4483811691 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1460,33 +1460,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x2609, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); -/* - * Fixup the cardbus bridges on the IBM Dock II docking station - */ -static void __devinit quirk_ibm_dock2_cardbus(struct pci_dev *dev) -{ - u32 val; - - /* - * tie the 2 interrupt pins to INTA, and configure the - * multifunction routing register to handle this. - */ - if ((dev->subsystem_vendor == PCI_VENDOR_ID_IBM) && - (dev->subsystem_device == 0x0148)) { - printk(KERN_INFO "PCI: Found IBM Dock II Cardbus Bridge " - "applying quirk\n"); - pci_read_config_dword(dev, 0x8c, &val); - val = ((val & 0xffffff00) | 0x1002); - pci_write_config_dword(dev, 0x8c, val); - pci_read_config_dword(dev, 0x80, &val); - val = ((val & 0x00ffff00) | 0x2864c077); - pci_write_config_dword(dev, 0x80, val); - } -} - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1420, - quirk_ibm_dock2_cardbus); - static void __devinit quirk_netmos(struct pci_dev *dev) { unsigned int num_parallel = (dev->subsystem_device & 0xf0) >> 4; -- cgit v1.2.3 From 6a34b57bec41c95f1e38f700cd9b81324baaffc7 Mon Sep 17 00:00:00 2001 From: Nicolas Kaiser Date: Tue, 14 Nov 2006 02:03:28 -0800 Subject: [PATCH] drivers/ide: stray bracket Stray bracket in debug code. Signed-off-by: Nicolas Kaiser Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/legacy/hd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c index b1d5291531b7..45ed03591cd8 100644 --- a/drivers/ide/legacy/hd.c +++ b/drivers/ide/legacy/hd.c @@ -459,7 +459,7 @@ ok_to_read: #ifdef DEBUG printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", req->rq_disk->disk_name, req->sector, req->nr_sectors, - req->buffer+512)); + req->buffer+512); #endif if (req->current_nr_sectors <= 0) end_request(req, 1); -- cgit v1.2.3 From d6e89cb6cd3a10eb203914093642f580c20476d4 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Tue, 14 Nov 2006 02:03:30 -0800 Subject: [PATCH] nvidiafb: fix unreachable code in nv10GetConfig Fix binary/logical operator typo which leads to unreachable code. Noticed while looking at other issues; I don't have the relevant hardware to test this. Signed-off-by: Nathan Lynch Cc: "Antonino A. Daplas" Acked-by: James Simmons Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nv_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c index 61dc46fecf2b..eab3e282a4de 100644 --- a/drivers/video/nvidia/nv_setup.c +++ b/drivers/video/nvidia/nv_setup.c @@ -262,7 +262,7 @@ static void nv10GetConfig(struct nvidia_par *par) #endif dev = pci_find_slot(0, 1); - if ((par->Chipset && 0xffff) == 0x01a0) { + if ((par->Chipset & 0xffff) == 0x01a0) { int amt = 0; pci_read_config_dword(dev, 0x7c, &amt); -- cgit v1.2.3 From a4625085445b86951d8482c0cdd6d52719f7c323 Mon Sep 17 00:00:00 2001 From: Brian King Date: Mon, 13 Nov 2006 16:32:36 -0600 Subject: [PATCH] libata: Convert from module_init to subsys_initcall When building a monolithic kernel, the load order of drivers does not work for SAS libata users, resulting in a kernel oops. Convert libata to use subsys_initcall instead of module_init, which ensures that libata gets loaded before any LLDD. This is the same thing that scsi core does to solve the problem. The load order problem was observed on ipr SAS adapters and should exist for other SAS users as well. Signed-off-by: Brian King Acked-by: Jeff Garzik Signed-off-by: Linus Torvalds --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index a8fd0c3e59b3..915a55a6cc14 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5957,7 +5957,7 @@ static void __exit ata_exit(void) destroy_workqueue(ata_aux_wq); } -module_init(ata_init); +subsys_initcall(ata_init); module_exit(ata_exit); static unsigned long ratelimit_time; -- cgit v1.2.3 From b369c2cfa47bc0ad495a95fe9a17c9888781d615 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 14 Nov 2006 12:36:03 +0100 Subject: [PATCH] cciss: fix iostat cciss needs to call disk_stat_add() for iostat to work. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/block/cciss.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 6ffe2b2bdacc..4105c3bf3476 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1300,6 +1300,12 @@ static void cciss_softirq_done(struct request *rq) complete_buffers(rq->bio, rq->errors); + if (blk_fs_request(rq)) { + const int rw = rq_data_dir(rq); + + disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors); + } + #ifdef CCISS_DEBUG printk("Done with %p\n", rq); #endif /* CCISS_DEBUG */ -- cgit v1.2.3 From 1f794b6082a5ff88f7c48d1634056026acf806f4 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 14 Nov 2006 12:36:45 +0100 Subject: [PATCH] cpqarray: fix iostat cpqarray needs to call disk_stat_add() for iostat to work. Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/block/cpqarray.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 570d2f049323..d5f519ebbc08 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -998,6 +998,7 @@ static inline void complete_buffers(struct bio *bio, int ok) */ static inline void complete_command(cmdlist_t *cmd, int timeout) { + struct request *rq = cmd->rq; int ok=1; int i, ddir; @@ -1029,12 +1030,18 @@ static inline void complete_command(cmdlist_t *cmd, int timeout) pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr, cmd->req.sg[i].size, ddir); - complete_buffers(cmd->rq->bio, ok); + complete_buffers(rq->bio, ok); - add_disk_randomness(cmd->rq->rq_disk); + if (blk_fs_request(rq)) { + const int rw = rq_data_dir(rq); - DBGPX(printk("Done with %p\n", cmd->rq);); - end_that_request_last(cmd->rq, ok ? 1 : -EIO); + disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors); + } + + add_disk_randomness(rq->rq_disk); + + DBGPX(printk("Done with %p\n", rq);); + end_that_request_last(rq, ok ? 1 : -EIO); } /* -- cgit v1.2.3 From c387fd85f84b9d89a75596325d8d6a0f730baf64 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 15 Nov 2006 00:30:17 +0100 Subject: [PATCH] Char: isicom, fix close bug port is dereferenced even if it is NULL. Dereference it _after_ the check if (!port)... Thanks Eric for reporting this. This fixes http://bugzilla.kernel.org/show_bug.cgi?id=7527 Signed-off-by: Jiri Slaby Signed-off-by: Linus Torvalds --- drivers/char/isicom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index e9e9bf31c369..58c955e390b3 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1062,11 +1062,12 @@ static void isicom_shutdown_port(struct isi_port *port) static void isicom_close(struct tty_struct *tty, struct file *filp) { struct isi_port *port = tty->driver_data; - struct isi_board *card = port->card; + struct isi_board *card; unsigned long flags; if (!port) return; + card = port->card; if (isicom_paranoia_check(port, tty->name, "isicom_close")) return; -- cgit v1.2.3 From d31e817183a4c1ee2e5fc0635ac075381f5c4419 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Thu, 16 Nov 2006 14:00:57 +1100 Subject: [PATCH] powerpc: windfarm shall request it's sub modules The windfarm code, in it's current incarnation, uses request_module() to load the various submodules it needs for a given platform so that only the main platform control module needs to be modprobed. However, it was missing various bits. This fixes it. In the future, we'll use some hotplug mecanisms to try to get all of this auto-loaded on the platforms where it matters but that isn't ready yet. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- drivers/macintosh/windfarm_pm112.c | 11 +++++++++++ drivers/macintosh/windfarm_pm81.c | 1 + drivers/macintosh/windfarm_pm91.c | 1 + 3 files changed, 13 insertions(+) (limited to 'drivers') diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c index fa4b13f89369..b3fbb45bc90a 100644 --- a/drivers/macintosh/windfarm_pm112.c +++ b/drivers/macintosh/windfarm_pm112.c @@ -685,6 +685,17 @@ static int __init wf_pm112_init(void) ++nr_cores; printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n"); + +#ifdef MODULE + request_module("windfarm_smu_controls"); + request_module("windfarm_smu_sensors"); + request_module("windfarm_smu_sat"); + request_module("windfarm_lm75_sensor"); + request_module("windfarm_max6690_sensor"); + request_module("windfarm_cpufreq_clamp"); + +#endif /* MODULE */ + platform_driver_register(&wf_pm112_driver); return 0; } diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index 2a944851b8e1..f24fa734046a 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c @@ -788,6 +788,7 @@ static int __init wf_smu_init(void) request_module("windfarm_smu_controls"); request_module("windfarm_smu_sensors"); request_module("windfarm_lm75_sensor"); + request_module("windfarm_cpufreq_clamp"); #endif /* MODULE */ platform_driver_register(&wf_smu_driver); diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 9961a67b4f85..26eee69ebe6d 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c @@ -719,6 +719,7 @@ static int __init wf_smu_init(void) request_module("windfarm_smu_controls"); request_module("windfarm_smu_sensors"); request_module("windfarm_lm75_sensor"); + request_module("windfarm_cpufreq_clamp"); #endif /* MODULE */ platform_driver_register(&wf_smu_driver); -- cgit v1.2.3 From 0ccead1869444891ae6b41f2c5fc8498521c908e Mon Sep 17 00:00:00 2001 From: Gary Zambrano Date: Tue, 14 Nov 2006 16:34:00 -0800 Subject: [TG3]: Increase 5906 firmware poll time. Newer 5906 bootcode needs about 7ms to finish resetting so the poll firmware loop was changed to maximum 20ms. Signed-off-by: Gary Zambrano Signed-off-by: Michael Chan Acked-by: Jeff Garzik Signed-off-by: David S. Miller --- drivers/net/tg3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 06e4f77b0988..6e86866bd3fa 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -4728,10 +4728,11 @@ static int tg3_poll_fw(struct tg3 *tp) u32 val; if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - for (i = 0; i < 400; i++) { + /* Wait up to 20ms for init done. */ + for (i = 0; i < 200; i++) { if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE) return 0; - udelay(10); + udelay(100); } return -ENODEV; } -- cgit v1.2.3 From c7835a77c86422d276b0d1a4c70924d933014c13 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 15 Nov 2006 21:14:42 -0800 Subject: [TG3]: Disable TSO on 5906 if CLKREQ is enabled. Due to hardware errata, TSO must be disabled if the PCI Express clock request is enabled on 5906. The chip may hang when transmitting TSO frames if CLKREQ is enabled. Update version to 3.69. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 20 ++++++++++++++++---- include/linux/pci_regs.h | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 6e86866bd3fa..1dbdd6bb587b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.68" -#define DRV_MODULE_RELDATE "November 02, 2006" +#define DRV_MODULE_VERSION "3.69" +#define DRV_MODULE_RELDATE "November 15, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -10366,7 +10366,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) u32 pci_state_reg, grc_misc_cfg; u32 val; u16 pci_cmd; - int err; + int err, pcie_cap; /* Force memory write invalidate off. If we leave it on, * then on 5700_BX chips we have to enable a workaround. @@ -10541,8 +10541,19 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE; - if (pci_find_capability(tp->pdev, PCI_CAP_ID_EXP) != 0) + pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP); + if (pcie_cap != 0) { tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { + u16 lnkctl; + + pci_read_config_word(tp->pdev, + pcie_cap + PCI_EXP_LNKCTL, + &lnkctl); + if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) + tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2; + } + } /* If we have an AMD 762 or VIA K8T800 chipset, write * reordering to the mailbox registers done by the host @@ -11809,6 +11820,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 || tp->pci_chip_rev_id == CHIPREV_ID_5705_A0 || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 || (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { tp->tg3_flags2 &= ~TG3_FLG2_TSO_CAPABLE; } else { diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index c312a12ad2d6..c321316f1bc7 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -371,6 +371,7 @@ #define PCI_EXP_DEVSTA_TRPND 0x20 /* Transactions Pending */ #define PCI_EXP_LNKCAP 12 /* Link Capabilities */ #define PCI_EXP_LNKCTL 16 /* Link Control */ +#define PCI_EXP_LNKCTL_CLKREQ_EN 0x100 /* Enable clkreq */ #define PCI_EXP_LNKSTA 18 /* Link Status */ #define PCI_EXP_SLTCAP 20 /* Slot Capabilities */ #define PCI_EXP_SLTCTL 24 /* Slot Control */ -- cgit v1.2.3 From b48f5457b4e9d64d9c1117a4ece247d98b4db49f Mon Sep 17 00:00:00 2001 From: "Zhang, Yanmin" Date: Thu, 16 Nov 2006 01:19:08 -0800 Subject: [PATCH] ipmi: use platform_device_add() instead of platform_device_register() to register device allocated dynamically I got below warning when running 2.6.19-rc5-mm1 on my ia64 machine. WARNING at lib/kobject.c:172 kobject_init() Call Trace: [] show_stack+0x40/0xa0 sp=e0000002ff9f7bc0 bsp=e0000002ff9f0d10 [] dump_stack+0x30/0x60 sp=e0000002ff9f7d90 bsp=e0000002ff9f0cf8 [] kobject_init+0x90/0x160 sp=e0000002ff9f7d90 bsp=e0000002ff9f0cd0 [] device_initialize+0x40/0x1c0 sp=e0000002ff9f7da0 bsp=e0000002ff9f0cb0 [] platform_device_register+0x20/0x60 sp=e0000002ff9f7dd0 bsp=e0000002ff9f0c90 [] try_smi_init+0xbc0/0x11e0 sp=e0000002ff9f7dd0 bsp=e0000002ff9f0c50 [] init_ipmi_si+0xaa0/0x12e0 sp=e0000002ff9f7de0 bsp=e0000002ff9f0bd8 [] init+0x350/0x780 sp=e0000002ff9f7e00 bsp=e0000002ff9f0ba8 [] kernel_thread_helper+0x30/0x60 sp=e0000002ff9f7e30 bsp=e0000002ff9f0b80 [] start_kernel_thread+0x20/0x40 sp=e0000002ff9f7e30 bsp=e0000002ff9f0b80 WARNING at lib/kobject.c:172 kobject_init() Call Trace: [] show_stack+0x40/0xa0 sp=e0000002ff9f7b40 bsp=e0000002ff9f0db0 [] dump_stack+0x30/0x60 sp=e0000002ff9f7d10 bsp=e0000002ff9f0d98 [] kobject_init+0x90/0x160 sp=e0000002ff9f7d10 bsp=e0000002ff9f0d70 [] device_initialize+0x40/0x1c0 sp=e0000002ff9f7d20 bsp=e0000002ff9f0d50 [] platform_device_register+0x20/0x60 sp=e0000002ff9f7d50 bsp=e0000002ff9f0d30 [] ipmi_register_smi+0xcc0/0x18e0 sp=e0000002ff9f7d50 bsp=e0000002ff9f0c90 [] try_smi_init+0xc60/0x11e0 sp=e0000002ff9f7dd0 bsp=e0000002ff9f0c50 [] init_ipmi_si+0xaa0/0x12e0 sp=e0000002ff9f7de0 bsp=e0000002ff9f0bd8 [] init+0x350/0x780 sp=e0000002ff9f7e00 bsp=e0000002ff9f0ba8 [] kernel_thread_helper+0x30/0x60 sp=e0000002ff9f7e30 bsp=e0000002ff9f0b80 [] start_kernel_thread+0x20/0x40 sp=e0000002ff9f7e30 bsp=e0000002ff9f0b80 The root cause is the device struct is initialized twice. If the device is allocated dynamically by platform_device_alloc, platform_device_alloc will initialize struct device, then, platform_device_add should be used to register the device. The difference between platform_device_register and platform_device_add is platform_device_register will initiate the device while platform_device_add won't. Signed-off-by: Zhang Yanmin Cc: Corey Minyard Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index a41b8df24073..c47add8e47df 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -2118,7 +2118,7 @@ static int ipmi_bmc_register(ipmi_smi_t intf) dev_set_drvdata(&bmc->dev->dev, bmc); kref_init(&bmc->refcount); - rv = platform_device_register(bmc->dev); + rv = platform_device_add(bmc->dev); mutex_unlock(&ipmidriver_mutex); if (rv) { printk(KERN_ERR diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index abc5149e30e8..bb1fac104fda 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2346,7 +2346,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->dev = &new_smi->pdev->dev; new_smi->dev->driver = &ipmi_driver; - rv = platform_device_register(new_smi->pdev); + rv = platform_device_add(new_smi->pdev); if (rv) { printk(KERN_ERR "ipmi_si_intf:" -- cgit v1.2.3 From 84a763e3d1a47fa9308b8817f265e936e5f1000a Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 16 Nov 2006 01:19:11 -0800 Subject: [PATCH] pnx4008: rename driver Make the drivers' names less generic to avoid possible confusion in future, as was requested by Russell King. Signed-off-by: Vitaly Wool Acked-by: James Simmons Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pnx4008/pnxrgbfb.c | 2 +- drivers/video/pnx4008/sdum.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index 7d9453c91a42..bf36b68856dd 100644 --- a/drivers/video/pnx4008/pnxrgbfb.c +++ b/drivers/video/pnx4008/pnxrgbfb.c @@ -191,7 +191,7 @@ err: static struct platform_driver rgbfb_driver = { .driver = { - .name = "rgbfb", + .name = "pnx4008-rgbfb", }, .probe = rgbfb_probe, .remove = rgbfb_remove, diff --git a/drivers/video/pnx4008/sdum.c b/drivers/video/pnx4008/sdum.c index 51f0ecc2a511..d23bf0d659b6 100644 --- a/drivers/video/pnx4008/sdum.c +++ b/drivers/video/pnx4008/sdum.c @@ -848,7 +848,7 @@ static int sdum_remove(struct platform_device *pdev) static struct platform_driver sdum_driver = { .driver = { - .name = "sdum", + .name = "pnx4008-sdum", }, .probe = sdum_probe, .remove = sdum_remove, -- cgit v1.2.3 From 3b9c10dc59eaaef23e5a47110c20fb554f7dba28 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 16 Nov 2006 01:19:14 -0800 Subject: [PATCH] pnx4008:fix NULL dereference in rgbfb Fix possible NULL dereference in pnxrgbfb. Signed-off-by: Vitaly Wool Cc: James Simmons Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pnx4008/pnxrgbfb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index bf36b68856dd..f29e66e2d774 100644 --- a/drivers/video/pnx4008/pnxrgbfb.c +++ b/drivers/video/pnx4008/pnxrgbfb.c @@ -154,7 +154,8 @@ static int __devinit rgbfb_probe(struct platform_device *pdev) goto err1; } - if (!fb_get_options("pnxrgbfb", &option) && !strcmp(option, "nocursor")) + if (!fb_get_options("pnxrgbfb", &option) && option && + !strcmp(option, "nocursor")) rgbfb_ops.fb_cursor = no_cursor; info->node = -1; -- cgit v1.2.3 From 3b46f0396c76a61526dec57a782a061c197ac337 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Thu, 16 Nov 2006 01:19:17 -0800 Subject: [PATCH] set default video mode on PowerBook Wallstreet Finally add the third PowerBook Wallstreet 233MHz model to the list of known display resolutions. Without this change, a 640x480 video mode is used. A workaround so far was to boot with 'video=atyfb:vmode:14' Signed-off-by: Olaf Hering Cc: Benjamin Herrenschmidt Cc: "Antonino A. Daplas" Cc: Solomon Peachy Cc: James Simmons Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/atyfb_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index b77b30923928..e815b354c09d 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -406,7 +406,7 @@ static struct { { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 }, - { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, + { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 }, { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL }, -- cgit v1.2.3 From e757bef270e21453bf507df200e2fb477c076da6 Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Thu, 16 Nov 2006 01:19:19 -0800 Subject: [PATCH] IB/ipath - fix driver build for platforms with PCI, but not HT The PCI Express and Hypertransport chip-specific source files should only be built when the kernel has the capability of actually compiling them. This fixes the driver build on, for example, ia64. Signed-off-by: Bryan O'Sullivan Cc: "Eric W. Biederman" Cc: Roland Dreier Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/ipath/Kconfig | 2 +- drivers/infiniband/hw/ipath/Makefile | 5 +++-- drivers/infiniband/hw/ipath/ipath_driver.c | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig index 574a678e7fdd..5ca471ac6542 100644 --- a/drivers/infiniband/hw/ipath/Kconfig +++ b/drivers/infiniband/hw/ipath/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_IPATH tristate "QLogic InfiniPath Driver" - depends on PCI_MSI && 64BIT && INFINIBAND + depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND ---help--- This is a driver for QLogic InfiniPath host channel adapters, including InfiniBand verbs support. This driver allows these diff --git a/drivers/infiniband/hw/ipath/Makefile b/drivers/infiniband/hw/ipath/Makefile index 5e29cb0095e5..7dc10551cf18 100644 --- a/drivers/infiniband/hw/ipath/Makefile +++ b/drivers/infiniband/hw/ipath/Makefile @@ -10,8 +10,6 @@ ib_ipath-y := \ ipath_eeprom.o \ ipath_file_ops.o \ ipath_fs.o \ - ipath_iba6110.o \ - ipath_iba6120.o \ ipath_init_chip.o \ ipath_intr.o \ ipath_keys.o \ @@ -31,5 +29,8 @@ ib_ipath-y := \ ipath_verbs_mcast.o \ ipath_verbs.o +ib_ipath-$(CONFIG_HT_IRQ) += ipath_iba6110.o +ib_ipath-$(CONFIG_PCI_MSI) += ipath_iba6120.o + ib_ipath-$(CONFIG_X86_64) += ipath_wc_x86_64.o ib_ipath-$(CONFIG_PPC64) += ipath_wc_ppc64.o diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 09a13c1fc46a..1aeddb48e355 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -390,12 +390,16 @@ static int __devinit ipath_init_one(struct pci_dev *pdev, /* setup the chip-specific functions, as early as possible. */ switch (ent->device) { +#ifdef CONFIG_HT_IRQ case PCI_DEVICE_ID_INFINIPATH_HT: ipath_init_iba6110_funcs(dd); break; +#endif +#ifdef CONFIG_PCI_MSI case PCI_DEVICE_ID_INFINIPATH_PE800: ipath_init_iba6120_funcs(dd); break; +#endif default: ipath_dev_err(dd, "Found unknown QLogic deviceid 0x%x, " "failing\n", ent->device); -- cgit v1.2.3 From 4c1b6d18bf2fdeb5ac725126c6928aaa98c8e22f Mon Sep 17 00:00:00 2001 From: Arnaud Giersch Date: Thu, 16 Nov 2006 01:19:21 -0800 Subject: [PATCH] parport: fix compilation failure Fix compilation failure. Signed-off-by: Arnaud Giersch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/parport/parport_ip32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/parport/parport_ip32.c b/drivers/parport/parport_ip32.c index e3e19277030a..ec44efdbb84e 100644 --- a/drivers/parport/parport_ip32.c +++ b/drivers/parport/parport_ip32.c @@ -780,7 +780,7 @@ static irqreturn_t parport_ip32_interrupt(int irq, void *dev_id) enum parport_ip32_irq_mode irq_mode = priv->irq_mode; switch (irq_mode) { case PARPORT_IP32_IRQ_FWD: - parport_generic_irq(irq, p, regs); + parport_generic_irq(irq, p); break; case PARPORT_IP32_IRQ_HERE: parport_ip32_wakeup(p); -- cgit v1.2.3 From 6897083abfb0156b533ab8ac42c47f68c550ca9e Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Thu, 16 Nov 2006 01:19:25 -0800 Subject: [PATCH] dell_rbu: fix error check platform_device_register_simple() returns error code as pointer when it fails. The return value should be checked by IS_ERR(). Cc: Abhay Salunke Signed-off-by: Akinobu Mita Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/firmware/dell_rbu.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index 08b161798443..fc702e40bd43 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -705,17 +705,16 @@ static struct bin_attribute rbu_packet_size_attr = { static int __init dcdrbu_init(void) { - int rc = 0; + int rc; spin_lock_init(&rbu_data.lock); init_packet_head(); - rbu_device = - platform_device_register_simple("dell_rbu", -1, NULL, 0); - if (!rbu_device) { + rbu_device = platform_device_register_simple("dell_rbu", -1, NULL, 0); + if (IS_ERR(rbu_device)) { printk(KERN_ERR "dell_rbu:%s:platform_device_register_simple " "failed\n", __FUNCTION__); - return -EIO; + return PTR_ERR(rbu_device); } rc = sysfs_create_bin_file(&rbu_device->dev.kobj, &rbu_data_attr); -- cgit v1.2.3 From 097b8457dafe7efc22201b4062e2d1e82e494067 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 16 Nov 2006 01:19:31 -0800 Subject: [PATCH] scsi: clear garbage after CDBs on SG_IO ATAPI devices transfer fixed number of bytes for CDBs (12 or 16). Some ATAPI devices choke when shorter CDB is used and the left bytes contain garbage. Block SG_IO cleared left bytes but SCSI SG_IO didn't. This patch makes SCSI SG_IO clear it and simplify CDB clearing in block SG_IO. Signed-off-by: Tejun Heo Cc: Mathieu Fluhr Cc: James Bottomley Cc: Douglas Gilbert Acked-by: Jens Axboe Cc: Acked-by: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/scsi_ioctl.c | 3 +-- drivers/scsi/scsi_lib.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index a19338e6215d..e55a75621437 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -286,9 +286,8 @@ static int sg_io(struct file *file, request_queue_t *q, * fill in request structure */ rq->cmd_len = hdr->cmd_len; + memset(rq->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memcpy(rq->cmd, cmd, hdr->cmd_len); - if (sizeof(rq->cmd) != hdr->cmd_len) - memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len); memset(sense, 0, sizeof(sense)); rq->sense = sense; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index d2c02df12fdc..3ac4890ce086 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -410,6 +410,7 @@ int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd, goto free_req; req->cmd_len = cmd_len; + memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */ memcpy(req->cmd, cmd, req->cmd_len); req->sense = sioc->sense; req->sense_len = 0; -- cgit v1.2.3 From 073ae841d6a5098f7c6e17fc1f329350d950d1ce Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 16 Nov 2006 10:59:12 +0200 Subject: IPoIB: Clear high octet in QP number IPoIB assumes that high (reserved) octet in the hardware address is 0, and copies it into the QPN. This violates RFC 4391 (which requires that the high 8 bits are ignored on receive), and will result in an invalid QPN being used when interoperating with IPoIB connected mode. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1eaf00e9862c..85522daeb946 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -49,6 +49,8 @@ #include +#define IPOIB_QPN(ha) (be32_to_cpup((__be32 *) ha) & 0xffffff) + MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("IP-over-InfiniBand net driver"); MODULE_LICENSE("Dual BSD/GPL"); @@ -520,8 +522,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) memcpy(&neigh->dgid.raw, &path->pathrec.dgid.raw, sizeof(union ib_gid)); - ipoib_send(dev, skb, path->ah, - be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); + ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha)); } else { neigh->ah = NULL; __skb_queue_tail(&neigh->queue, skb); @@ -599,8 +600,7 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev, ipoib_dbg(priv, "Send unicast ARP to %04x\n", be16_to_cpu(path->pathrec.dlid)); - ipoib_send(dev, skb, path->ah, - be32_to_cpup((__be32 *) phdr->hwaddr)); + ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr)); } else if ((path->query || !path_rec_start(dev, path)) && skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) { /* put pseudoheader back on for next time */ @@ -661,8 +661,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } - ipoib_send(dev, skb, neigh->ah, - be32_to_cpup((__be32 *) skb->dst->neighbour->ha)); + ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha)); goto out; } @@ -694,7 +693,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) IPOIB_GID_FMT "\n", skb->dst ? "neigh" : "dst", be16_to_cpup((__be16 *) skb->data), - be32_to_cpup((__be32 *) phdr->hwaddr), + IPOIB_QPN(phdr->hwaddr), IPOIB_GID_RAW_ARG(phdr->hwaddr + 4)); dev_kfree_skb_any(skb); ++priv->stats.tx_dropped; @@ -777,7 +776,7 @@ static void ipoib_neigh_destructor(struct neighbour *n) ipoib_dbg(priv, "neigh_destructor for %06x " IPOIB_GID_FMT "\n", - be32_to_cpup((__be32 *) n->ha), + IPOIB_QPN(n->ha), IPOIB_GID_RAW_ARG(n->ha + 4)); spin_lock_irqsave(&priv->lock, flags); -- cgit v1.2.3 From 3da2495c0a92723d58cacaaff48dc60a29ddaae6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 14 Nov 2006 16:28:01 -0500 Subject: OHCI: disallow autostop when wakeup is not available This patch (as822) prevents the OHCI autostop mechanism from kicking in if the root hub is not able or not allowed to issue wakeup requests. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 6f113596af66..da09e7930c1b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -422,7 +422,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (time_after_eq (jiffies, + } else if (device_may_wakeup(&hcd->self.root_hub->dev) + && time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & -- cgit v1.2.3 From 40c36092f75ae2026e35feb4f85caa143b64423a Mon Sep 17 00:00:00 2001 From: Kjell Myksvoll Date: Sun, 22 Oct 2006 23:26:42 +0200 Subject: USB: ftdi_sio: adds vendor/product id for a RFID construction kit Adds the vendor and prodcut id for a RFID construction kit from the Elektor Electronics magazine, september 2006. From: Kjell Myksvoll Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bd76b4c11fcc..c971d7873792 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -511,6 +511,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13M_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13S_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TACTRIX_OPENPORT_13U_PID) }, + { USB_DEVICE(ELEKTOR_VID, ELEKTOR_FT323R_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f0edb87d2dd5..30921f558ee1 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -174,10 +174,16 @@ */ #define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ +/* + * FTDI USB UART chips used in construction projects from the + * Elektor Electronics magazine (http://elektor-electronics.co.uk) + */ +#define ELEKTOR_VID 0x0C7D +#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ + /* * DSS-20 Sync Station for Sony Ericsson P800 */ - #define FTDI_DSS20_PID 0xFC82 /* -- cgit v1.2.3 From fad14a0da885714c8610982045a6d04a4886865e Mon Sep 17 00:00:00 2001 From: Frank Sievertsen Date: Fri, 20 Oct 2006 09:43:53 +0200 Subject: USB: ftdi driver pid for dmx-interfaces Please add a usb pid to the ftdi_sio driver. The pid is used by dmx4all dmx-interfaces (for stage lighting). The interfaces are using the usb-id 0403:c850. I added the id to the driver and it works perfectly. I added a patch for linux 2.6.18.1, too. From: Frank Sievertsen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c971d7873792..c186b4e73c72 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -311,6 +311,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_ACTZWAVE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IPLUS_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DMX4ALL) }, { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 30921f558ee1..bae117d359af 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -55,6 +55,9 @@ /* iPlus device */ #define FTDI_IPLUS_PID 0xD070 /* Product Id */ +/* DMX4ALL DMX Interfaces */ +#define FTDI_DMX4ALL 0xC850 + /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ -- cgit v1.2.3 From 51b5bce8c253b82d4789161cc3b0c74bee313bb1 Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Thu, 2 Nov 2006 23:14:10 -0800 Subject: USB: Fix UCR-61S2B unusual_dev entry Recently this entry's bcd scope was narrowed so as not to falsly apply to bcd's other than 0x0110. But while it breaks those of a larger bcd, it is still needed for those of a smaller bcd - so this changes the lower bcd limit to 0x0000. Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bc1ac07bf6ce..e87fb538b74c 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1323,8 +1323,10 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. + * Devices with bcd > 110 seem to not need it while those + * with bcd < 110 appear to need it. */ -UNUSUAL_DEV( 0x1019, 0x0c55, 0x0110, 0x0110, +UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110, "Desknote", "UCR-61S2B", US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, -- cgit v1.2.3 From 583ceada075597a5b6acab1140d61ac81586a2a6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Oct 2006 12:04:22 -0400 Subject: USB: OHCI: fix root-hub resume bug When a suspended OHCI controller sees a port's status change, it sets both the Root-Hub-Status-Change and the Resume-Detect bits in the Interrupt Status register. Processing both these bits, the driver tries to resume the root hub twice! This patch (as807) fixes the bug by ignoring RD if RHSC is set. It also prints a slightly more informative log message when a remote-wakeup event occurs. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 25 +++++++++++++++---------- drivers/usb/host/ohci-hub.c | 3 ++- 2 files changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 9be6b303e784..ea4714e557e4 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -715,13 +715,6 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) return IRQ_NOTMINE; } - if (ints & OHCI_INTR_RHSC) { - ohci_vdbg (ohci, "rhsc\n"); - ohci->next_statechange = jiffies + STATECHANGE_DELAY; - ohci_writel (ohci, OHCI_INTR_RHSC, ®s->intrstatus); - usb_hcd_poll_rh_status(hcd); - } - if (ints & OHCI_INTR_UE) { disable (ohci); ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n"); @@ -731,9 +724,21 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) ohci_usb_reset (ohci); } - if (ints & OHCI_INTR_RD) { - ohci_vdbg (ohci, "resume detect\n"); - ohci_writel (ohci, OHCI_INTR_RD, ®s->intrstatus); + if (ints & OHCI_INTR_RHSC) { + ohci_vdbg(ohci, "rhsc\n"); + ohci->next_statechange = jiffies + STATECHANGE_DELAY; + ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, + ®s->intrstatus); + usb_hcd_poll_rh_status(hcd); + } + + /* For connect and disconnect events, we expect the controller + * to turn on RHSC along with RD. But for remote wakeup events + * this might not happen. + */ + else if (ints & OHCI_INTR_RD) { + ohci_vdbg(ohci, "resume detect\n"); + ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); hcd->poll_rh = 1; if (ohci->autostop) { spin_lock (&ohci->lock); diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index da09e7930c1b..6995ea36f2e8 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -169,7 +169,8 @@ __acquires(ohci->lock) break; case OHCI_USB_RESUME: /* HCFS changes sometime after INTR_RD */ - ohci_info (ohci, "wakeup\n"); + ohci_info(ohci, "%swakeup\n", + autostopped ? "auto-" : ""); break; case OHCI_USB_OPER: /* this can happen after resuming a swsusp snapshot */ -- cgit v1.2.3 From bb7eef6eea53633a8a49f014fd27c08f7d5fda1a Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Wed, 8 Nov 2006 19:58:07 -0800 Subject: USB: correct keymapping on Powerbook built-in USB ISO keyboards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit similar to the version in adbhid_input_register(): The '<>' key and the '^°' key on a german keyboard is swapped. Provide correct keys to userland, external USB keyboards will not work correctly when the 'badmap'/'goodmap' workarounds from xkeyboard-config are used. It is expected that distributions drop the badmap/goodmap part from keycodes/macintosh in the xkeyboard-config package. This is probably 2.6.18.x material, if major distros settle on 2.6.18. Signed-off-by: Olaf Hering Cc: Dmitry Torokhov Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 4 ++-- drivers/usb/input/hid-input.c | 17 +++++++++++++++++ drivers/usb/input/hid.h | 1 + 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6daf85c6eeee..8fde85c4905c 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1797,10 +1797,10 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 9a808a3b4d37..68e7ebb978a9 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c @@ -121,6 +121,12 @@ static struct hidinput_key_translation powerbook_numlock_keys[] = { { } }; +static struct hidinput_key_translation powerbook_iso_keyboard[] = { + { KEY_GRAVE, KEY_102ND }, + { KEY_102ND, KEY_GRAVE }, + { } +}; + static int usbhid_pb_fnmode = 1; module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); MODULE_PARM_DESC(pb_fnmode, @@ -195,6 +201,14 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, } } + if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) { + trans = find_translation(powerbook_iso_keyboard, usage->code); + if (trans) { + input_event(input, usage->type, trans->to, value); + return 1; + } + } + return 0; } @@ -210,6 +224,9 @@ static void hidinput_pb_setup(struct input_dev *input) for (trans = powerbook_numlock_keys; trans->from; trans++) set_bit(trans->to, input->keybit); + + for (trans = powerbook_iso_keyboard; trans->from; trans++) + set_bit(trans->to, input->keybit); } #else static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 9b50effef758..0e76e6dcac37 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -260,6 +260,7 @@ struct hid_item { #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 #define HID_QUIRK_INVERT_HWHEEL 0x00004000 +#define HID_QUIRK_POWERBOOK_ISO_KEYBOARD 0x00008000 /* * This is the global environment of the parser. This information is -- cgit v1.2.3 From a3878f11ed29c50b7da1336adcac089e9c741fc2 Mon Sep 17 00:00:00 2001 From: Jan Mate Date: Wed, 8 Nov 2006 19:58:04 -0800 Subject: USB Storage: unusual_devs.h entry for Sony Ericsson P990i USB Storage: this patch adds support for Sony Ericsson P990i Signed-off-by: Jan Mate Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e87fb538b74c..cc701e88d386 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1320,6 +1320,13 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), +/* Reported by Jan Mate */ +UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, + "Sony Ericsson", + "P990i", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. -- cgit v1.2.3 From a7dc4eeac8f18de5fc6bea1a0f46e67f42b83509 Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Sun, 12 Nov 2006 11:22:42 +0100 Subject: USB: hid-core: Add quirk for new Apple keyboard/trackpad The new Core2 Duo MacBook Pro have a new keyboard+trackpad device. The following patch adds the needed HID quirk for the Fn key. Signed-off-by: Julien BLACHE Signed-off-by: Vojtech Pavlik Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 8fde85c4905c..6d08a3bcc952 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1802,6 +1802,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, -- cgit v1.2.3 From 70708f2c2a3c164e9aa80345919a22c838b3b314 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Mon, 6 Nov 2006 16:33:07 +0300 Subject: usb-storage: Remove duplicated unusual_devs.h entries for Sony Ericsson P990i For some reason the unusual_devs.h entry for Sony Ericsson P990i had three identical copies in a wrong place in the file in addition to the correct entry. Signed-off-by: Sergey Vlasov Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index cc701e88d386..efb047f431e8 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1306,27 +1306,6 @@ UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -/* Reported by Jan Mate */ -UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, - "Sony Ericsson", - "P990i", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - -/* Reported by Jan Mate */ -UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, - "Sony Ericsson", - "P990i", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - -/* Reported by Jan Mate */ -UNUSUAL_DEV( 0x0fce, 0xe030, 0x0000, 0x0000, - "Sony Ericsson", - "P990i", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* Reported by Kevin Cernekee * Tested on hardware version 1.10. * Entry is needed only for the initializer function override. -- cgit v1.2.3 From 6ab16a9029b0b26c23a4806d90ca76be6d6beae3 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 7 Nov 2006 10:16:25 +0100 Subject: USB: Fixed outdated usb_get_device_descriptor() documentation usb_get_device_descriptor() used to convert several descriptor fields to host CPU's byte order. Now that it doesn't convert them anymore, update the documentation to reflect this. Signed-off-by: Laurent Pinchart Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index fccd1952bad3..7729c0744886 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -828,10 +828,7 @@ char *usb_cache_string(struct usb_device *udev, int index) * Context: !in_interrupt () * * Updates the copy of the device descriptor stored in the device structure, - * which dedicates space for this purpose. Note that several fields are - * converted to the host CPU's byte order: the USB version (bcdUSB), and - * vendors product and version fields (idVendor, idProduct, and bcdDevice). - * That lets device drivers compare against non-byteswapped constants. + * which dedicates space for this purpose. * * Not exported, only for use by the core. If drivers really want to read * the device descriptor directly, they can call usb_get_descriptor() with -- cgit v1.2.3 From 0029908ba9661ef26f7020309966aae23c2027b8 Mon Sep 17 00:00:00 2001 From: Alex Sanks Date: Sun, 29 Oct 2006 16:38:31 -0800 Subject: USB: ipaq: Add HTC Modem Support Adds support for HTC Smart Phones in modem mode (as opposed to sync mode). Loads and works with pppd on my T-Mobile SDA. Signed-off-by: Alex Sanks Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipaq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 6238aff1e772..d72cf8bc7f76 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -320,6 +320,7 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x0B05, 0x9200) }, /* ASUS USB Sync */ { USB_DEVICE(0x0B05, 0x9202) }, /* ASUS USB Sync */ { USB_DEVICE(0x0BB4, 0x00CE) }, /* HTC USB Sync */ + { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC USB Modem */ { USB_DEVICE(0x0BB4, 0x0A01) }, /* PocketPC USB Sync */ { USB_DEVICE(0x0BB4, 0x0A02) }, /* PocketPC USB Sync */ { USB_DEVICE(0x0BB4, 0x0A03) }, /* PocketPC USB Sync */ -- cgit v1.2.3 From 5a3fcf5c7f035de8e2b28d144d67b7bebac8a723 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Tue, 7 Nov 2006 00:31:51 +0100 Subject: USB: auerswald possible memleak fix fix possible memory leak in auerbuf_setup(). Regards, Mariusz Kozlowski Signed-off-by: Mariusz Kozlowski Signed-off-by: Wolfgang Muees Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/auerswald.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 0be9d62d62ae..e4971d6aaafb 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -780,7 +780,7 @@ static int auerbuf_setup (pauerbufctl_t bcp, unsigned int numElements, unsigned bl_fail:/* not enough memory. Free allocated elements */ dbg ("auerbuf_setup: no more memory"); - kfree(bep); + auerbuf_free(bep); auerbuf_free_buffers (bcp); return -ENOMEM; } -- cgit v1.2.3 From e45413eb708c1cf21082764457692c8eeac0ca97 Mon Sep 17 00:00:00 2001 From: Amol Lad Date: Thu, 5 Oct 2006 14:26:02 +0400 Subject: W1: ioremap balanced with iounmap ioremap must be balanced with iounmap in error path. Please consider for 2.6.19. Signed-off-by: Amol Lad Signed-off-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/masters/matrox_w1.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c index 2788b8ca9bb1..6f9d880ab2e9 100644 --- a/drivers/w1/masters/matrox_w1.c +++ b/drivers/w1/masters/matrox_w1.c @@ -215,6 +215,8 @@ static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_devi return 0; err_out_free_device: + if (dev->virt_addr) + iounmap(dev->virt_addr); kfree(dev); return err; -- cgit v1.2.3 From d355c3c23ce56ab83e41f2bfb30d02fb90618530 Mon Sep 17 00:00:00 2001 From: Dennis Stosberg Date: Mon, 13 Nov 2006 09:15:20 +0100 Subject: aoe: Add forgotten NULL at end of attribute list in aoeblk.c This caused the system to stall when the aoe module was loaded. The error was introduced in commit 4ca5224f3ea4779054d96e885ca9b3980801ce13 Signed-off-by: Dennis Stosberg Signed-off-by: Greg Kroah-Hartman --- drivers/block/aoe/aoeblk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index d433f27e0ce2..aa25f8b09fe3 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -68,6 +68,7 @@ static struct attribute *aoe_attrs[] = { &disk_attr_mac.attr, &disk_attr_netif.attr, &disk_attr_fwver.attr, + NULL }; static const struct attribute_group attr_group = { -- cgit v1.2.3 From 4f71c5de19c27f2198105d3b26b398494d5c353b Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 17 Nov 2006 15:35:00 +1100 Subject: [PATCH] Fix radeon DDC regression When radeonfb was changed to use the new "generic" ddc, a bit of code initializing the GPIO lines was lost, causing it to not work if the firmware didn't configure them properly, which seems to happen on some cards. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_i2c.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/aty/radeon_i2c.c index 676754520099..869725a13c21 100644 --- a/drivers/video/aty/radeon_i2c.c +++ b/drivers/video/aty/radeon_i2c.c @@ -139,7 +139,13 @@ void radeon_delete_i2c_busses(struct radeonfb_info *rinfo) int radeon_probe_i2c_connector(struct radeonfb_info *rinfo, int conn, u8 **out_edid) { - u8 *edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); + u32 reg = rinfo->i2c[conn-1].ddc_reg; + u8 *edid; + + OUTREG(reg, INREG(reg) & + ~(VGA_DDC_DATA_OUTPUT | VGA_DDC_CLK_OUTPUT)); + + edid = fb_ddc_read(&rinfo->i2c[conn-1].adapter); if (out_edid) *out_edid = edid; -- cgit v1.2.3 From 4be703906cffd5902028d20626e636ba21fb0b61 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 16 Nov 2006 22:18:28 -0800 Subject: Fix generic fb_ddc i2c edid probe msg Benh points out that the msgs[0].flags entry never got initialized, and since it's an automatic stack allocation, it could have any random value, which is bad. Rewrite the initializer to explicitly initialize all fields of the small i2c_msg structure array we generate. Just to keep it all obvious, let's handle msgs[1].buf in the same initializer while we're at it, instead of initializing that one separately later. Signed-off-by: Linus Torvalds --- drivers/video/fb_ddc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fb_ddc.c b/drivers/video/fb_ddc.c index 3aa6ebf68f17..f836137a0eda 100644 --- a/drivers/video/fb_ddc.c +++ b/drivers/video/fb_ddc.c @@ -20,26 +20,26 @@ static unsigned char *fb_do_probe_ddc_edid(struct i2c_adapter *adapter) { unsigned char start = 0x0; + unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL); struct i2c_msg msgs[] = { { .addr = DDC_ADDR, + .flags = 0, .len = 1, .buf = &start, }, { .addr = DDC_ADDR, .flags = I2C_M_RD, .len = EDID_LENGTH, + .buf = buf, } }; - unsigned char *buf; - buf = kmalloc(EDID_LENGTH, GFP_KERNEL); if (!buf) { dev_warn(&adapter->dev, "unable to allocate memory for EDID " "block.\n"); return NULL; } - msgs[1].buf = buf; if (i2c_transfer(adapter, msgs, 2) == 2) return buf; -- cgit v1.2.3 From 1d08811d0c05cd54a778f45588ec22eee027ff89 Mon Sep 17 00:00:00 2001 From: Jan-Benedict Glaw Date: Fri, 17 Nov 2006 10:32:04 +0100 Subject: lkkbd: Remove my old snail-mail address I moved to a different town and my old snail-mail address is invalid now. Also, there's no need at all to have any address like that in the sources, so remove it completely. Signed-off-by: Jan-Benedict Glaw --- drivers/input/keyboard/lkkbd.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 708d5a1bc3d2..979b93e33da7 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c @@ -59,11 +59,6 @@ * 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 - * - * Should you need to contact me, the author, you can do so either by - * email or by paper mail: - * Jan-Benedict Glaw, Lilienstraße 16, 33790 Hörste (near Halle/Westf.), - * Germany. */ #include -- cgit v1.2.3 From 825d3748c1b5f9272e4f9769f1c2da85174ece28 Mon Sep 17 00:00:00 2001 From: Thomas Koeller Date: Mon, 14 Aug 2006 21:55:29 +0200 Subject: [WATCHDOG] MIPS RM9000 on-chip watchdog device This is a driver for the on-chip watchdog device found on some MIPS RM9000 processors. Signed-off-by: Thomas Koeller Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/Kconfig | 10 + drivers/char/watchdog/Makefile | 1 + drivers/char/watchdog/rm9k_wdt.c | 431 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 442 insertions(+) create mode 100644 drivers/char/watchdog/rm9k_wdt.c (limited to 'drivers') diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig index a52ecad7d56c..ea09d0c974ea 100644 --- a/drivers/char/watchdog/Kconfig +++ b/drivers/char/watchdog/Kconfig @@ -575,6 +575,16 @@ config INDYDOG timer expired and no process has written to /dev/watchdog during that time. +config WDT_RM9K_GPI + tristate "RM9000/GPI hardware watchdog" + depends on WATCHDOG && CPU_RM9000 + help + Watchdog implementation using the GPI hardware found on + PMC-Sierra RM9xxx CPUs. + + To compile this driver as a module, choose M here: the + module will be called rm9k_wdt. + # S390 Architecture config ZVM_WATCHDOG diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile index 81abdfa10a07..2cd8ff8d10ac 100644 --- a/drivers/char/watchdog/Makefile +++ b/drivers/char/watchdog/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o # MIPS Architecture obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o # S390 Architecture diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c new file mode 100644 index 000000000000..8cd12ab9bff4 --- /dev/null +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -0,0 +1,431 @@ +/* + * Watchdog implementation for GPI h/w found on PMC-Sierra RM9xxx + * chips. + * + * Copyright (C) 2004 by Basler Vision Technologies AG + * Author: Thomas Koeller + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define CLOCK 125000000 +#define MAX_TIMEOUT_SECONDS 32 +#define CPCCR 0x0080 +#define CPGIG1SR 0x0044 +#define CPGIG1ER 0x0054 + + + +/* Function prototypes */ +static int __init wdt_gpi_probe(struct device *); +static int __exit wdt_gpi_remove(struct device *); +static void wdt_gpi_set_timeout(unsigned int); +static int wdt_gpi_open(struct inode *, struct file *); +static int wdt_gpi_release(struct inode *, struct file *); +static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); +static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); +static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); +static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); +static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); + + + + +static const char wdt_gpi_name[] = "wdt_gpi"; +static atomic_t opencnt; +static int expect_close; +static int locked = 0; + + + +/* These are set from device resources */ +static void __iomem * wd_regs; +static unsigned int wd_irq, wd_ctr; + + + +/* Module arguments */ +static int timeout = MAX_TIMEOUT_SECONDS; +module_param(timeout, int, 0444); +static unsigned long resetaddr = 0xbffdc200; +module_param(resetaddr, ulong, 0444); +static unsigned long flagaddr = 0xbffdc104; +module_param(flagaddr, ulong, 0444); +static int powercycle = 0; +module_param(powercycle, bool, 0444); + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0444); + + + +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = wdt_gpi_open, + .release = wdt_gpi_release, + .write = wdt_gpi_write, + .unlocked_ioctl = wdt_gpi_ioctl, +}; + +static struct miscdevice miscdev = { + .minor = WATCHDOG_MINOR, + .name = wdt_gpi_name, + .fops = &fops, +}; + +static struct device_driver wdt_gpi_driver = { + .name = (char *) wdt_gpi_name, + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .probe = wdt_gpi_probe, + .remove = __exit_p(wdt_gpi_remove), + .shutdown = NULL, + .suspend = NULL, + .resume = NULL, +}; + +static struct notifier_block wdt_gpi_shutdown = { + .notifier_call = wdt_gpi_notify, +}; + + + +static const struct resource * +wdt_gpi_get_resource(struct platform_device *pdv, const char *name, + unsigned int type) +{ + char buf[80]; + if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) + return NULL; + return platform_get_resource_byname(pdv, type, buf); +} + + + +/* No hotplugging on the platform bus - use __init */ +static int __init wdt_gpi_probe(struct device *dev) +{ + int res; + struct platform_device * const pdv = to_platform_device(dev); + const struct resource + * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, + IORESOURCE_MEM), + * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ, + IORESOURCE_IRQ), + * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER, + 0); + + if (unlikely(!rr || !ri || !rc)) + return -ENXIO; + + wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start); + if (unlikely(!wd_regs)) + return -ENOMEM; + wd_irq = ri->start; + wd_ctr = rc->start; + res = misc_register(&miscdev); + if (res) + iounmap(wd_regs); + else + register_reboot_notifier(&wdt_gpi_shutdown); + return res; +} + + + +static int __exit wdt_gpi_remove(struct device *dev) +{ + int res; + + unregister_reboot_notifier(&wdt_gpi_shutdown); + res = misc_deregister(&miscdev); + iounmap(wd_regs); + wd_regs = NULL; + return res; +} + + +static void wdt_gpi_set_timeout(unsigned int to) +{ + u32 reg; + const u32 wdval = (to * CLOCK) & ~0x0000000f; + + lock_titan_regs(); + reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); + titan_writel(reg, CPCCR); + wmb(); + __raw_writel(wdval, wd_regs + 0x0000); + wmb(); + titan_writel(reg | (0x2 << (wd_ctr * 4)), CPCCR); + wmb(); + titan_writel(reg | (0x5 << (wd_ctr * 4)), CPCCR); + iob(); + unlock_titan_regs(); +} + + + +static int wdt_gpi_open(struct inode *i, struct file *f) +{ + int res; + u32 reg; + + if (unlikely(0 > atomic_dec_if_positive(&opencnt))) + return -EBUSY; + + expect_close = 0; + if (locked) { + module_put(THIS_MODULE); + free_irq(wd_irq, &miscdev); + locked = 0; + } + + res = request_irq(wd_irq, wdt_gpi_irqhdl, SA_SHIRQ | SA_INTERRUPT, + wdt_gpi_name, &miscdev); + if (unlikely(res)) + return res; + + wdt_gpi_set_timeout(timeout); + + lock_titan_regs(); + reg = titan_readl(CPGIG1ER); + titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER); + iob(); + unlock_titan_regs(); + + printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n", + wdt_gpi_name, timeout); + return 0; +} + + + +static int wdt_gpi_release(struct inode *i, struct file *f) +{ + if (nowayout) { + printk(KERN_NOTICE "%s: no way out - watchdog left running\n", + wdt_gpi_name); + __module_get(THIS_MODULE); + locked = 1; + } else { + if (expect_close) { + u32 reg; + + lock_titan_regs(); + reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); + titan_writel(reg, CPCCR); + reg = titan_readl(CPGIG1ER); + titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER); + iob(); + unlock_titan_regs(); + free_irq(wd_irq, &miscdev); + printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); + } else { + printk(KERN_NOTICE "%s: unexpected close() -" + " watchdog left running\n", + wdt_gpi_name); + wdt_gpi_set_timeout(timeout); + __module_get(THIS_MODULE); + locked = 1; + } + } + + atomic_inc(&opencnt); + return 0; +} + + + +static ssize_t +wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) +{ + char val; + + wdt_gpi_set_timeout(timeout); + expect_close = (s > 0) && !get_user(val, d) && (val == 'V'); + return s ? 1 : 0; +} + + + +static long +wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + long res = -ENOTTY; + const long size = _IOC_SIZE(cmd); + int stat; + static struct watchdog_info wdinfo = { + .identity = "RM9xxx/GPI watchdog", + .firmware_version = 0, + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING + }; + + if (unlikely(_IOC_TYPE(cmd) != WATCHDOG_IOCTL_BASE)) + return -ENOTTY; + + if ((_IOC_DIR(cmd) & _IOC_READ) + && !access_ok(VERIFY_WRITE, arg, size)) + return -EFAULT; + + if ((_IOC_DIR(cmd) & _IOC_WRITE) + && !access_ok(VERIFY_READ, arg, size)) + return -EFAULT; + + expect_close = 0; + + switch (cmd) { + case WDIOC_GETSUPPORT: + wdinfo.options = nowayout ? + WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : + WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; + res = __copy_to_user((void __user *)arg, &wdinfo, size) ? + -EFAULT : size; + break; + + case WDIOC_GETSTATUS: + break; + + case WDIOC_GETBOOTSTATUS: + stat = (*(volatile char *) flagaddr & 0x01) + ? WDIOF_CARDRESET : 0; + res = __copy_to_user((void __user *)arg, &stat, size) ? + -EFAULT : size; + break; + + case WDIOC_SETOPTIONS: + break; + + case WDIOC_KEEPALIVE: + wdt_gpi_set_timeout(timeout); + res = size; + break; + + case WDIOC_SETTIMEOUT: + { + int val; + if (unlikely(__copy_from_user(&val, (const void __user *) arg, + size))) { + res = -EFAULT; + break; + } + + if (val > 32) + val = 32; + timeout = val; + wdt_gpi_set_timeout(val); + res = size; + printk("%s: timeout set to %u seconds\n", + wdt_gpi_name, timeout); + } + break; + + case WDIOC_GETTIMEOUT: + res = __copy_to_user((void __user *) arg, &timeout, size) ? + -EFAULT : size; + break; + } + + return res; +} + + + + +static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) +{ + if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) + return IRQ_NONE; + __raw_writel(0x1, wd_regs + 0x0008); + + + printk(KERN_WARNING "%s: watchdog expired - resetting system\n", + wdt_gpi_name); + + *(volatile char *) flagaddr |= 0x01; + *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2; + iob(); + while (1) + cpu_relax(); +} + + + +static int +wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) +{ + if(code == SYS_DOWN || code == SYS_HALT) { + u32 reg; + + lock_titan_regs(); + reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); + titan_writel(reg, CPCCR); + reg = titan_readl(CPGIG1ER); + titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER); + iob(); + unlock_titan_regs(); + } + return NOTIFY_DONE; +} + + + +static int __init wdt_gpi_init_module(void) +{ + atomic_set(&opencnt, 1); + if (timeout > MAX_TIMEOUT_SECONDS) + timeout = MAX_TIMEOUT_SECONDS; + return driver_register(&wdt_gpi_driver); +} + + + +static void __exit wdt_gpi_cleanup_module(void) +{ + driver_unregister(&wdt_gpi_driver); +} + +module_init(wdt_gpi_init_module); +module_exit(wdt_gpi_cleanup_module); + + + +MODULE_AUTHOR("Thomas Koeller "); +MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices"); +MODULE_VERSION("0.1"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); +MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset"); +MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); +MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); -- cgit v1.2.3 From cd57eeab7c4c108ce6e84545bdf37ae91b930781 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 17 Nov 2006 21:51:35 +0100 Subject: [WATCHDOG] MIPS RM9000 on-chip watchdog device - patch 1 Locate parameter descriptions close to parameter definition - not in bottom of file. Signed-off-by: Sam Ravnborg Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/rm9k_wdt.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 8cd12ab9bff4..da3fc63bca61 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -45,7 +45,6 @@ #define CPGIG1ER 0x0054 - /* Function prototypes */ static int __init wdt_gpi_probe(struct device *); static int __exit wdt_gpi_remove(struct device *); @@ -59,33 +58,37 @@ static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); - - static const char wdt_gpi_name[] = "wdt_gpi"; static atomic_t opencnt; static int expect_close; static int locked = 0; - /* These are set from device resources */ static void __iomem * wd_regs; static unsigned int wd_irq, wd_ctr; - /* Module arguments */ static int timeout = MAX_TIMEOUT_SECONDS; module_param(timeout, int, 0444); +MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); + static unsigned long resetaddr = 0xbffdc200; module_param(resetaddr, ulong, 0444); +MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset"); + static unsigned long flagaddr = 0xbffdc104; module_param(flagaddr, ulong, 0444); +MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); + static int powercycle = 0; module_param(powercycle, bool, 0444); +MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, bool, 0444); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); @@ -424,8 +427,4 @@ MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices"); MODULE_VERSION("0.1"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds"); -MODULE_PARM_DESC(resetaddr, "Address to write to to force a reset"); -MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); -MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); + -- cgit v1.2.3 From 97846e3ccbcbcc966e23a91b0d190efd1f889c9b Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 17 Nov 2006 23:15:48 +0100 Subject: [WATCHDOG] MIPS RM9000 on-chip watchdog device - patch 2 Reorganize source code so that it is structured as follows: - Function prototypes - Local variables - Module arguments - Interrupt handler - Watchdog functions - /dev/watchdog operations - Shutdown notifier - Kernel interfaces - Init & exit procedures - Device driver init & exit Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/rm9k_wdt.c | 216 ++++++++++++++++++--------------------- 1 file changed, 101 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index da3fc63bca61..1aad9138f714 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -46,8 +46,7 @@ /* Function prototypes */ -static int __init wdt_gpi_probe(struct device *); -static int __exit wdt_gpi_remove(struct device *); +static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); static void wdt_gpi_set_timeout(unsigned int); static int wdt_gpi_open(struct inode *, struct file *); static int wdt_gpi_release(struct inode *, struct file *); @@ -55,7 +54,8 @@ static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); -static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); +static int __init wdt_gpi_probe(struct device *); +static int __exit wdt_gpi_remove(struct device *); static const char wdt_gpi_name[] = "wdt_gpi"; @@ -91,93 +91,26 @@ module_param(nowayout, bool, 0444); MODULE_PARM_DESC(nowayout, "Watchdog cannot be disabled once started"); - -static struct file_operations fops = { - .owner = THIS_MODULE, - .open = wdt_gpi_open, - .release = wdt_gpi_release, - .write = wdt_gpi_write, - .unlocked_ioctl = wdt_gpi_ioctl, -}; - -static struct miscdevice miscdev = { - .minor = WATCHDOG_MINOR, - .name = wdt_gpi_name, - .fops = &fops, -}; - -static struct device_driver wdt_gpi_driver = { - .name = (char *) wdt_gpi_name, - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .probe = wdt_gpi_probe, - .remove = __exit_p(wdt_gpi_remove), - .shutdown = NULL, - .suspend = NULL, - .resume = NULL, -}; - -static struct notifier_block wdt_gpi_shutdown = { - .notifier_call = wdt_gpi_notify, -}; - - - -static const struct resource * -wdt_gpi_get_resource(struct platform_device *pdv, const char *name, - unsigned int type) -{ - char buf[80]; - if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) - return NULL; - return platform_get_resource_byname(pdv, type, buf); -} - - - -/* No hotplugging on the platform bus - use __init */ -static int __init wdt_gpi_probe(struct device *dev) +/* Interrupt handler */ +static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) { - int res; - struct platform_device * const pdv = to_platform_device(dev); - const struct resource - * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, - IORESOURCE_MEM), - * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ, - IORESOURCE_IRQ), - * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER, - 0); - - if (unlikely(!rr || !ri || !rc)) - return -ENXIO; - - wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start); - if (unlikely(!wd_regs)) - return -ENOMEM; - wd_irq = ri->start; - wd_ctr = rc->start; - res = misc_register(&miscdev); - if (res) - iounmap(wd_regs); - else - register_reboot_notifier(&wdt_gpi_shutdown); - return res; -} - + if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) + return IRQ_NONE; + __raw_writel(0x1, wd_regs + 0x0008); -static int __exit wdt_gpi_remove(struct device *dev) -{ - int res; + printk(KERN_WARNING "%s: watchdog expired - resetting system\n", + wdt_gpi_name); - unregister_reboot_notifier(&wdt_gpi_shutdown); - res = misc_deregister(&miscdev); - iounmap(wd_regs); - wd_regs = NULL; - return res; + *(volatile char *) flagaddr |= 0x01; + *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2; + iob(); + while (1) + cpu_relax(); } +/* Watchdog functions */ static void wdt_gpi_set_timeout(unsigned int to) { u32 reg; @@ -197,7 +130,7 @@ static void wdt_gpi_set_timeout(unsigned int to) } - +/* /dev/watchdog operations */ static int wdt_gpi_open(struct inode *i, struct file *f) { int res; @@ -231,8 +164,6 @@ static int wdt_gpi_open(struct inode *i, struct file *f) return 0; } - - static int wdt_gpi_release(struct inode *i, struct file *f) { if (nowayout) { @@ -267,8 +198,6 @@ static int wdt_gpi_release(struct inode *i, struct file *f) return 0; } - - static ssize_t wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) { @@ -279,8 +208,6 @@ wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) return s ? 1 : 0; } - - static long wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) { @@ -362,27 +289,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) } - - -static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) -{ - if (!unlikely(__raw_readl(wd_regs + 0x0008) & 0x1)) - return IRQ_NONE; - __raw_writel(0x1, wd_regs + 0x0008); - - - printk(KERN_WARNING "%s: watchdog expired - resetting system\n", - wdt_gpi_name); - - *(volatile char *) flagaddr |= 0x01; - *(volatile char *) resetaddr = powercycle ? 0x01 : 0x2; - iob(); - while (1) - cpu_relax(); -} - - - +/* Shutdown notifier*/ static int wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) { @@ -401,6 +308,89 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) } +/* Kernel interfaces */ +static struct file_operations fops = { + .owner = THIS_MODULE, + .open = wdt_gpi_open, + .release = wdt_gpi_release, + .write = wdt_gpi_write, + .unlocked_ioctl = wdt_gpi_ioctl, +}; + +static struct miscdevice miscdev = { + .minor = WATCHDOG_MINOR, + .name = wdt_gpi_name, + .fops = &fops, +}; + +static struct notifier_block wdt_gpi_shutdown = { + .notifier_call = wdt_gpi_notify, +}; + + +/* Init & exit procedures */ +static const struct resource * +wdt_gpi_get_resource(struct platform_device *pdv, const char *name, + unsigned int type) +{ + char buf[80]; + if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) + return NULL; + return platform_get_resource_byname(pdv, type, buf); +} + +/* No hotplugging on the platform bus - use __init */ +static int __init wdt_gpi_probe(struct device *dev) +{ + int res; + struct platform_device * const pdv = to_platform_device(dev); + const struct resource + * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, + IORESOURCE_MEM), + * const ri = wdt_gpi_get_resource(pdv, WDT_RESOURCE_IRQ, + IORESOURCE_IRQ), + * const rc = wdt_gpi_get_resource(pdv, WDT_RESOURCE_COUNTER, + 0); + + if (unlikely(!rr || !ri || !rc)) + return -ENXIO; + + wd_regs = ioremap_nocache(rr->start, rr->end + 1 - rr->start); + if (unlikely(!wd_regs)) + return -ENOMEM; + wd_irq = ri->start; + wd_ctr = rc->start; + res = misc_register(&miscdev); + if (res) + iounmap(wd_regs); + else + register_reboot_notifier(&wdt_gpi_shutdown); + return res; +} + +static int __exit wdt_gpi_remove(struct device *dev) +{ + int res; + + unregister_reboot_notifier(&wdt_gpi_shutdown); + res = misc_deregister(&miscdev); + iounmap(wd_regs); + wd_regs = NULL; + return res; +} + + +/* Device driver init & exit */ +static struct device_driver wdt_gpi_driver = { + .name = (char *) wdt_gpi_name, + .bus = &platform_bus_type, + .owner = THIS_MODULE, + .probe = wdt_gpi_probe, + .remove = __exit_p(wdt_gpi_remove), + .shutdown = NULL, + .suspend = NULL, + .resume = NULL, +}; static int __init wdt_gpi_init_module(void) { @@ -410,8 +400,6 @@ static int __init wdt_gpi_init_module(void) return driver_register(&wdt_gpi_driver); } - - static void __exit wdt_gpi_cleanup_module(void) { driver_unregister(&wdt_gpi_driver); @@ -420,8 +408,6 @@ static void __exit wdt_gpi_cleanup_module(void) module_init(wdt_gpi_init_module); module_exit(wdt_gpi_cleanup_module); - - MODULE_AUTHOR("Thomas Koeller "); MODULE_DESCRIPTION("Basler eXcite watchdog driver for gpi devices"); MODULE_VERSION("0.1"); -- cgit v1.2.3 From 414a675964e5636b53b37827b646138f166507d3 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 17 Nov 2006 23:36:08 +0100 Subject: [WATCHDOG] MIPS RM9000 on-chip watchdog device - patch 3 Move start and stop code into seperate functions Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/rm9k_wdt.c | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 1aad9138f714..22aab8703eda 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -111,6 +111,30 @@ static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) /* Watchdog functions */ +static void wdt_gpi_start(void) +{ + u32 reg; + + lock_titan_regs(); + reg = titan_readl(CPGIG1ER); + titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER); + iob(); + unlock_titan_regs(); +} + +static void wdt_gpi_stop(void) +{ + u32 reg; + + lock_titan_regs(); + reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); + titan_writel(reg, CPCCR); + reg = titan_readl(CPGIG1ER); + titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER); + iob(); + unlock_titan_regs(); +} + static void wdt_gpi_set_timeout(unsigned int to) { u32 reg; @@ -134,7 +158,6 @@ static void wdt_gpi_set_timeout(unsigned int to) static int wdt_gpi_open(struct inode *i, struct file *f) { int res; - u32 reg; if (unlikely(0 > atomic_dec_if_positive(&opencnt))) return -EBUSY; @@ -152,12 +175,7 @@ static int wdt_gpi_open(struct inode *i, struct file *f) return res; wdt_gpi_set_timeout(timeout); - - lock_titan_regs(); - reg = titan_readl(CPGIG1ER); - titan_writel(reg | (0x100 << wd_ctr), CPGIG1ER); - iob(); - unlock_titan_regs(); + wdt_gpi_start(); printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n", wdt_gpi_name, timeout); @@ -173,15 +191,7 @@ static int wdt_gpi_release(struct inode *i, struct file *f) locked = 1; } else { if (expect_close) { - u32 reg; - - lock_titan_regs(); - reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); - titan_writel(reg, CPCCR); - reg = titan_readl(CPGIG1ER); - titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER); - iob(); - unlock_titan_regs(); + wdt_gpi_stop(); free_irq(wd_irq, &miscdev); printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); } else { @@ -293,17 +303,9 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) static int wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) { - if(code == SYS_DOWN || code == SYS_HALT) { - u32 reg; - - lock_titan_regs(); - reg = titan_readl(CPCCR) & ~(0xf << (wd_ctr * 4)); - titan_writel(reg, CPCCR); - reg = titan_readl(CPGIG1ER); - titan_writel(reg & ~(0x100 << wd_ctr), CPGIG1ER); - iob(); - unlock_titan_regs(); - } + if (code == SYS_DOWN || code == SYS_HALT) + wdt_gpi_stop(); + return NOTIFY_DONE; } -- cgit v1.2.3 From d5d06ff7f181c06ef8c94b353ae3fef8f06b3085 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Fri, 17 Nov 2006 23:50:06 +0100 Subject: [WATCHDOG] MIPS RM9000 on-chip watchdog device - patch 4 a number of small patches: - include notifier.h include file - re-arrange prototype functions - remove =0 initializations - change printk logging levels to what's used in other drivers - /dev/watchdog is a VFS so use nonseekable_open - Style: Instead of "if (constant op function_or_variable)" we prefer "if (function_or_variable op constant)" - arg is a __user pointer - use MAX_TIMEOUT_SECONDS instead of 32 in WDIOC_SETTIMEOUT Signed-off-by: Randy Dunlap Signed-off-by: Wim Van Sebroeck --- drivers/char/watchdog/rm9k_wdt.c | 42 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/rm9k_wdt.c b/drivers/char/watchdog/rm9k_wdt.c index 22aab8703eda..ec3909371c21 100644 --- a/drivers/char/watchdog/rm9k_wdt.c +++ b/drivers/char/watchdog/rm9k_wdt.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -47,13 +48,15 @@ /* Function prototypes */ static irqreturn_t wdt_gpi_irqhdl(int, void *, struct pt_regs *); +static void wdt_gpi_start(void); +static void wdt_gpi_stop(void); static void wdt_gpi_set_timeout(unsigned int); static int wdt_gpi_open(struct inode *, struct file *); static int wdt_gpi_release(struct inode *, struct file *); static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); -static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); +static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); static int __init wdt_gpi_probe(struct device *); static int __exit wdt_gpi_remove(struct device *); @@ -61,7 +64,7 @@ static int __exit wdt_gpi_remove(struct device *); static const char wdt_gpi_name[] = "wdt_gpi"; static atomic_t opencnt; static int expect_close; -static int locked = 0; +static int locked; /* These are set from device resources */ @@ -82,7 +85,7 @@ static unsigned long flagaddr = 0xbffdc104; module_param(flagaddr, ulong, 0444); MODULE_PARM_DESC(flagaddr, "Address to write to boot flags to"); -static int powercycle = 0; +static int powercycle; module_param(powercycle, bool, 0444); MODULE_PARM_DESC(powercycle, "Cycle power if watchdog expires"); @@ -99,7 +102,7 @@ static irqreturn_t wdt_gpi_irqhdl(int irq, void *ctxt, struct pt_regs *regs) __raw_writel(0x1, wd_regs + 0x0008); - printk(KERN_WARNING "%s: watchdog expired - resetting system\n", + printk(KERN_CRIT "%s: watchdog expired - resetting system\n", wdt_gpi_name); *(volatile char *) flagaddr |= 0x01; @@ -155,11 +158,11 @@ static void wdt_gpi_set_timeout(unsigned int to) /* /dev/watchdog operations */ -static int wdt_gpi_open(struct inode *i, struct file *f) +static int wdt_gpi_open(struct inode *inode, struct file *file) { int res; - if (unlikely(0 > atomic_dec_if_positive(&opencnt))) + if (unlikely(atomic_dec_if_positive(&opencnt) < 0)) return -EBUSY; expect_close = 0; @@ -179,13 +182,13 @@ static int wdt_gpi_open(struct inode *i, struct file *f) printk(KERN_INFO "%s: watchdog started, timeout = %u seconds\n", wdt_gpi_name, timeout); - return 0; + return nonseekable_open(inode, file); } -static int wdt_gpi_release(struct inode *i, struct file *f) +static int wdt_gpi_release(struct inode *inode, struct file *file) { if (nowayout) { - printk(KERN_NOTICE "%s: no way out - watchdog left running\n", + printk(KERN_INFO "%s: no way out - watchdog left running\n", wdt_gpi_name); __module_get(THIS_MODULE); locked = 1; @@ -195,7 +198,7 @@ static int wdt_gpi_release(struct inode *i, struct file *f) free_irq(wd_irq, &miscdev); printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); } else { - printk(KERN_NOTICE "%s: unexpected close() -" + printk(KERN_CRIT "%s: unexpected close() -" " watchdog left running\n", wdt_gpi_name); wdt_gpi_set_timeout(timeout); @@ -224,6 +227,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) long res = -ENOTTY; const long size = _IOC_SIZE(cmd); int stat; + void __user *argp = (void __user *)arg; static struct watchdog_info wdinfo = { .identity = "RM9xxx/GPI watchdog", .firmware_version = 0, @@ -248,8 +252,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) wdinfo.options = nowayout ? WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; - res = __copy_to_user((void __user *)arg, &wdinfo, size) ? - -EFAULT : size; + res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size; break; case WDIOC_GETSTATUS: @@ -258,7 +261,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case WDIOC_GETBOOTSTATUS: stat = (*(volatile char *) flagaddr & 0x01) ? WDIOF_CARDRESET : 0; - res = __copy_to_user((void __user *)arg, &stat, size) ? + res = __copy_to_user(argp, &stat, size) ? -EFAULT : size; break; @@ -273,24 +276,23 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) case WDIOC_SETTIMEOUT: { int val; - if (unlikely(__copy_from_user(&val, (const void __user *) arg, - size))) { + if (unlikely(__copy_from_user(&val, argp, size))) { res = -EFAULT; break; } - if (val > 32) - val = 32; + if (val > MAX_TIMEOUT_SECONDS) + val = MAX_TIMEOUT_SECONDS; timeout = val; wdt_gpi_set_timeout(val); res = size; - printk("%s: timeout set to %u seconds\n", + printk(KERN_INFO "%s: timeout set to %u seconds\n", wdt_gpi_name, timeout); } break; case WDIOC_GETTIMEOUT: - res = __copy_to_user((void __user *) arg, &timeout, size) ? + res = __copy_to_user(argp, &timeout, size) ? -EFAULT : size; break; } @@ -299,7 +301,7 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) } -/* Shutdown notifier*/ +/* Shutdown notifier */ static int wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) { -- cgit v1.2.3 From b976fe19acc565e5137e6f12af7b6633a23e6b7c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 17 Nov 2006 19:31:09 -0800 Subject: Revert "ACPI: created a dedicated workqueue for notify() execution" This reverts commit 37605a6900f6b4d886d995751fcfeef88c4e462c. Again. This same bug has now been introduced twice: it was done earlier by commit b8d35192c55fb055792ff0641408eaaec7c88988, only to be reverted last time in commit 72945b2b90a5554975b8f72673ab7139d232a121. We must NOT try to queue up notify handlers to another thread than the normal ACPI execution thread, because the notifications on some systems seem to just keep on accumulating until we run out of memory and/or threads. Keeping events within the one deferred execution thread automatically throttles the events properly. At least the Compaq N620c will lock up completely on the first thermal event without this patch reverted. Cc: David Brownell Cc: Len Brown Cc: Alexey Starikovskiy Signed-off-by: Linus Torvalds --- drivers/acpi/osl.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c84286cbbe25..068fe4f100b0 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -73,7 +73,6 @@ static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -static struct workqueue_struct *kacpi_notify_wq; acpi_status acpi_os_initialize(void) { @@ -92,9 +91,8 @@ acpi_status acpi_os_initialize1(void) return AE_NULL_ENTRY; } kacpid_wq = create_singlethread_workqueue("kacpid"); - kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); BUG_ON(!kacpid_wq); - BUG_ON(!kacpi_notify_wq); + return AE_OK; } @@ -106,7 +104,6 @@ acpi_status acpi_os_terminate(void) } destroy_workqueue(kacpid_wq); - destroy_workqueue(kacpi_notify_wq); return AE_OK; } @@ -569,7 +566,10 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ static void acpi_os_execute_deferred(void *context) { - struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; + struct acpi_os_dpc *dpc = NULL; + + + dpc = (struct acpi_os_dpc *)context; if (!dpc) { printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); return; @@ -604,12 +604,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, struct acpi_os_dpc *dpc; struct work_struct *task; + ACPI_FUNCTION_TRACE("os_queue_for_execution"); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) - return AE_BAD_PARAMETER; + return_ACPI_STATUS(AE_BAD_PARAMETER); /* * Allocate/initialize DPC structure. Note that this memory will be @@ -622,20 +624,26 @@ acpi_status acpi_os_execute(acpi_execute_type type, * from the same memory. */ - dpc = kmalloc(sizeof(struct acpi_os_dpc) + - sizeof(struct work_struct), GFP_ATOMIC); + dpc = + kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), + GFP_ATOMIC); if (!dpc) - return AE_NO_MEMORY; + return_ACPI_STATUS(AE_NO_MEMORY); + dpc->function = function; dpc->context = context; + task = (void *)(dpc + 1); INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - if (!queue_work((type == OSL_NOTIFY_HANDLER)? - kacpi_notify_wq : kacpid_wq, task)) { - status = AE_ERROR; + + if (!queue_work(kacpid_wq, task)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Call to queue_work() failed.\n")); kfree(dpc); + status = AE_ERROR; } - return status; + + return_ACPI_STATUS(status); } EXPORT_SYMBOL(acpi_os_execute); -- cgit v1.2.3 From dfbc9e9d33adb1ac9910dd7f8ceb911947039a52 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Sat, 18 Nov 2006 22:19:34 -0800 Subject: [PATCH] pcmcia: fix 'rmmod pcmcia' with unbound devices Having unbound PCMCIA devices: doing a 'find /sys' after a 'rmmod pcmcia' gives an oops because the pcmcia_device is not unregisterd from the driver core. fixes bugzilla #7481 Signed-off-by: Daniel Ritz Dominik Brodowski Cc: Pavol Gono Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0f701921c13e..a20d84d707d9 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1271,6 +1271,9 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev, socket->pcmcia_state.dead = 1; pccard_register_pcmcia(socket, NULL); + /* unregister any unbound devices */ + pcmcia_card_remove(socket, NULL); + pcmcia_put_socket(socket); return; -- cgit v1.2.3 From a6cd2d94e1072a5756b5e5ab647d3223cba7e555 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 18 Nov 2006 22:19:36 -0800 Subject: [PATCH] i2c-ixp4xx: fix ") != 0))" typo i2c_bit_add_bus() returns -E; -E != 0 => err = 1 probe fails with positive error code Signed-off-by: Alexey Dobriyan Cc: Deepak Saxena Acked-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/i2c-ixp4xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index 1ce01fb0ac09..05fffb9415a2 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c @@ -137,7 +137,8 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) gpio_line_set(gpio->scl_pin, 0); gpio_line_set(gpio->sda_pin, 0); - if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) { + err = i2c_bit_add_bus(&drv_data->adapter); + if (err != 0) printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id); kfree(drv_data); -- cgit v1.2.3 From ffb3d1348605816de10d4e57281e02f606508b6c Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 18 Nov 2006 22:19:39 -0800 Subject: [PATCH] scx200_acb: handle PCI errors Signed-off-by: Jeff Garzik Signed-off-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/i2c/busses/scx200_acb.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index 32aab0d34ee9..714bae780953 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -494,11 +494,12 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev, iface->pdev = pdev; iface->bar = bar; - pci_enable_device_bars(iface->pdev, 1 << iface->bar); + rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar); + if (rc) + goto errout_free; rc = pci_request_region(iface->pdev, iface->bar, iface->adapter.name); - - if (rc != 0) { + if (rc) { printk(KERN_ERR NAME ": can't allocate PCI BAR %d\n", iface->bar); goto errout_free; -- cgit v1.2.3 From f0c69c4ee796a2d2277c3a000e24f29a25a00060 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sat, 18 Nov 2006 22:19:41 -0800 Subject: [PATCH] ftape: fix printk format warnings Fix printk format warnings: drivers/char/ftape/zftape/zftape-buffers.c:87: warning: format '%d' expects type 'int', but argument 3 has type 'size_t' drivers/char/ftape/zftape/zftape-buffers.c:104: warning: format '%d' expects type 'int', but argument 3 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ftape/zftape/zftape-buffers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ftape/zftape/zftape-buffers.c b/drivers/char/ftape/zftape/zftape-buffers.c index da06f138334e..7ebce2ec7897 100644 --- a/drivers/char/ftape/zftape/zftape-buffers.c +++ b/drivers/char/ftape/zftape/zftape-buffers.c @@ -85,7 +85,7 @@ int zft_vmalloc_once(void *new, size_t size) peak_memory = used_memory; } TRACE_ABORT(0, ft_t_noise, - "allocated buffer @ %p, %d bytes", *(void **)new, size); + "allocated buffer @ %p, %zd bytes", *(void **)new, size); } int zft_vmalloc_always(void *new, size_t size) { @@ -101,7 +101,7 @@ void zft_vfree(void *old, size_t size) if (*(void **)old) { vfree(*(void **)old); used_memory -= size; - TRACE(ft_t_noise, "released buffer @ %p, %d bytes", + TRACE(ft_t_noise, "released buffer @ %p, %zd bytes", *(void **)old, size); *(void **)old = NULL; } -- cgit v1.2.3 From 49a1cd00b599d12c3f397e5a32f81f6e2aab0d74 Mon Sep 17 00:00:00 2001 From: Toralf Foerster Date: Sat, 18 Nov 2006 22:19:41 -0800 Subject: [PATCH] fix build error for HISAX_NETJET Fix a build error for the enter:now PCI card. Signed-off-by: Toralf Foerster Acked-by: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/hisax/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index eb57a988e048..cfd2718a490d 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig @@ -344,7 +344,7 @@ config HISAX_HFC_SX config HISAX_ENTERNOW_PCI bool "Formula-n enter:now PCI card" - depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) + depends on HISAX_NETJET && PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || FRV)) help This enables HiSax support for the Formula-n enter:now PCI ISDN card. -- cgit v1.2.3 From b3438f8266cb1f5010085ac47d7ad6a36a212164 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 20 Nov 2006 11:47:18 -0800 Subject: Add "pure_initcall" for static variable initialization This is a quick hack to overcome the fact that SRCU currently does not allow static initializers, and we need to sometimes initialize those things before any other initializers (even "core" ones) can do so. Currently we don't allow this at all for modules, and the only user that needs is right now is cpufreq. As reported by Thomas Gleixner: "Commit b4dfdbb3c707474a2254c5b4d7e62be31a4b7da9 ("[PATCH] cpufreq: make the transition_notifier chain use SRCU breaks cpu frequency notification users, which register the callback > on core_init level." Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Arjan van de Ven Cc: Andrew Morton , Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 2 +- include/asm-generic/vmlinux.lds.h | 2 ++ include/linux/init.h | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 86e69b7f9122..dd0c2623e27b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -59,7 +59,7 @@ static int __init init_cpufreq_transition_notifier_list(void) srcu_init_notifier_head(&cpufreq_transition_notifier_list); return 0; } -core_initcall(init_cpufreq_transition_notifier_list); +pure_initcall(init_cpufreq_transition_notifier_list); static LIST_HEAD(cpufreq_governor_list); static DEFINE_MUTEX (cpufreq_governor_mutex); diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 9d873163a7ab..e60d6f21fa62 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -215,6 +215,8 @@ .notes : { *(.note.*) } :note #define INITCALLS \ + *(.initcall0.init) \ + *(.initcall0s.init) \ *(.initcall1.init) \ *(.initcall1s.init) \ *(.initcall2.init) \ diff --git a/include/linux/init.h b/include/linux/init.h index ff40ea118e3a..5eb5d24b7680 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -93,6 +93,14 @@ extern void setup_arch(char **); static initcall_t __initcall_##fn##id __attribute_used__ \ __attribute__((__section__(".initcall" level ".init"))) = fn +/* + * A "pure" initcall has no dependencies on anything else, and purely + * initializes variables that couldn't be statically initialized. + * + * This only exists for built-in code, not for modules. + */ +#define pure_initcall(fn) __define_initcall("0",fn,1) + #define core_initcall(fn) __define_initcall("1",fn,1) #define core_initcall_sync(fn) __define_initcall("1s",fn,1s) #define postcore_initcall(fn) __define_initcall("2",fn,2) -- cgit v1.2.3 From 3f5a6ca31c334011fd929501a078424c0d3f71be Mon Sep 17 00:00:00 2001 From: Bryan O'Sullivan Date: Mon, 20 Nov 2006 10:54:34 -0800 Subject: IB/ipath: Depend on CONFIG_NET ipath uses skb functions and won't build without CONFIG_NET. Spotted by Randy Dunlap. Signed-off-by: Bryan O'Sullivan Acked-by: Randy Dunlap Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/Kconfig b/drivers/infiniband/hw/ipath/Kconfig index 5ca471ac6542..90c14543677d 100644 --- a/drivers/infiniband/hw/ipath/Kconfig +++ b/drivers/infiniband/hw/ipath/Kconfig @@ -1,6 +1,6 @@ config INFINIBAND_IPATH tristate "QLogic InfiniPath Driver" - depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND + depends on (PCI_MSI || HT_IRQ) && 64BIT && INFINIBAND && NET ---help--- This is a driver for QLogic InfiniPath host channel adapters, including InfiniBand verbs support. This driver allows these -- cgit v1.2.3 From 6af6e1efb161ffe36e718b1fd58385710879af7c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 21 Nov 2006 16:58:59 -0500 Subject: [PATCH] Fix CPU_FREQ_GOV_ONDEMAND=y compile error The ONDEMAND governor needs FREQ_TABLE Signed-off-by: Mattia Dongili Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- drivers/cpufreq/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 2cc71b66231e..491779af8d55 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -107,6 +107,7 @@ config CPU_FREQ_GOV_USERSPACE config CPU_FREQ_GOV_ONDEMAND tristate "'ondemand' cpufreq policy governor" + select CPU_FREQ_TABLE help 'ondemand' - This driver adds a dynamic cpufreq policy governor. The governor does a periodic polling and -- cgit v1.2.3 From 12862086f24d7382b24379bbcbe0dadf12ca5945 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Tue, 21 Nov 2006 17:44:31 -0800 Subject: [TG3]: Add missing unlock in tg3_open() error path. Sparse noticed a locking imbalance in tg3_open(). This patch adds an unlock to one of the error paths, so that tg3_open() always exits without the lock held. Signed-off-by: Ira W. Snyder Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1dbdd6bb587b..c20bb998e0e5 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -6979,8 +6979,10 @@ static int tg3_open(struct net_device *dev) tg3_full_lock(tp, 0); err = tg3_set_power_state(tp, PCI_D0); - if (err) + if (err) { + tg3_full_unlock(tp); return err; + } tg3_disable_ints(tp); tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; -- cgit v1.2.3 From 7d915a38985d2826acbdc9dc9cca8a93e23e5278 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Nov 2006 09:37:54 -0800 Subject: [AGP] Fix intel 965 AGP memory mapping function This introduces a i965-specific "mask_memory()" function that knows about the extended physical addresses that the i965 supports. This allows us to correctly map in physical memory in the >4GB range into the GTT. Also simplify/clean-up the i965 case for the aperture sizing by just returning the fixed 512kB size from "fetch_size()". We don't really care that not all of the aperture may be visible - the only thing that cares about the aperture size is the Intel "stolen memory" calculation, which depends on the fixed size. Cc: Keith Packard Cc: Eric Anholt Cc: Dave Jones Signed-off-by: Linus Torvalds --- drivers/char/agp/intel-agp.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index d1ede7db5a12..aceece71a85d 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -387,11 +387,7 @@ static void intel_i830_init_gtt_entries(void) /* We obtain the size of the GTT, which is also stored (for some * reason) at the top of stolen memory. Then we add 4KB to that * for the video BIOS popup, which is also stored in there. */ - - if (IS_I965) - size = 512 + 4; - else - size = agp_bridge->driver->fetch_size() + 4; + size = agp_bridge->driver->fetch_size() + 4; if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { @@ -805,6 +801,26 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge) return 0; } + +/* + * The i965 supports 36-bit physical addresses, but to keep + * the format of the GTT the same, the bits that don't fit + * in a 32-bit word are shifted down to bits 4..7. + * + * Gcc is smart enough to notice that "(addr >> 28) & 0xf0" + * is always zero on 32-bit architectures, so no need to make + * this conditional. + */ +static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, + unsigned long addr, int type) +{ + /* Shift high bits down */ + addr |= (addr >> 28) & 0xf0; + + /* Type checking must be done elsewhere */ + return addr | bridge->driver->masks[type].mask; +} + static int intel_i965_fetch_size(void) { struct aper_size_info_fixed *values; @@ -832,7 +848,8 @@ static int intel_i965_fetch_size(void) agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); - return values[offset].size; + /* The i965 GTT is always sized as if it had a 512kB aperture size */ + return 512; } /* The intel i965 automatically initializes the agp aperture during POST. @@ -1584,7 +1601,7 @@ static struct agp_bridge_driver intel_i965_driver = { .fetch_size = intel_i965_fetch_size, .cleanup = intel_i915_cleanup, .tlb_flush = intel_i810_tlbflush, - .mask_memory = intel_i810_mask_memory, + .mask_memory = intel_i965_mask_memory, .masks = intel_i810_masks, .agp_enable = intel_i810_agp_enable, .cache_flush = global_cache_flush, -- cgit v1.2.3 From 66c669baa7d70b8d135da67f36c8dba12cea71b8 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 22 Nov 2006 14:55:29 -0800 Subject: [AGP] Allocate AGP pages with GFP_DMA32 by default Not all graphic page remappers support physical addresses over the 4GB mark for remapping, so while some do (the AMD64 GART always did, and I just fixed the i965 to do so properly), we're safest off just forcing GFP_DMA32 allocations to make sure graphics pages get allocated in the low 32-bit address space by default. AGP sub-drivers that really care, and can do better, could just choose to implement their own allocator (or we could add another "64-bit safe" default allocator for their use), but quite frankly, you're not likely to care in practice. So for now, this trivial change means that we won't be allocating pages that we can't map correctly by mistake on x86-64. [ On traditional 32-bit x86, this could never happen, because GFP_KERNEL would never allocate any highmem memory anyway ] Acked-by: Andi Kleen Acked-by: Dave Jones Cc: Eric Anholt Cc: Keith Packard Signed-off-by: Linus Torvalds --- drivers/char/agp/generic.c | 2 +- drivers/char/agp/intel-agp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c39200161688..5ff457b41efb 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -1054,7 +1054,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) { struct page * page; - page = alloc_page(GFP_KERNEL); + page = alloc_page(GFP_KERNEL | GFP_DMA32); if (page == NULL) return NULL; diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index aceece71a85d..555b3a8ab49c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -169,7 +169,7 @@ static void *i8xx_alloc_pages(void) { struct page * page; - page = alloc_pages(GFP_KERNEL, 2); + page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2); if (page == NULL) return NULL; -- cgit v1.2.3 From 0916bd3ebb7cefdd0f432e8491abe24f4b5a101e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 22 Nov 2006 20:42:01 -0500 Subject: [PATCH] Correct bound checking from the value returned from _PPC method. processor_perflib.c::acpi_processor_ppc_notifier() check if the value returned by the processor's _PPC method is 0 and return failed if so. This is wrong since 0 indicate that the bios think the processor can go to the highest frequency. This patch for example fix the HP NX 6125 to allow its highest frequency to be available. Signed-off-by: Bruno Ducrot Cc: "Pallipadi, Venkatesh" Signed-off-by: Dave Jones Signed-off-by: Linus Torvalds --- drivers/acpi/processor_perflib.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 7ba5e49ab302..6fd174a37149 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -83,10 +83,8 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, goto out; ppc = (unsigned int)pr->performance_platform_limit; - if (!ppc) - goto out; - if (ppc > pr->performance->state_count) + if (ppc >= pr->performance->state_count) goto out; cpufreq_verify_within_limits(policy, 0, -- cgit v1.2.3 From 0b1082efb92eedb28e982cfae526267ebdcf5622 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 23 Nov 2006 13:28:50 +0100 Subject: [PATCH] Fix i2c-ixp4xx compile (missing brace) Fix recent i2c-ixp4xx compilation breakage. Sorry for overlooking it. Signed-off-by: Jean Delvare Signed-off-by: Linus Torvalds --- drivers/i2c/busses/i2c-ixp4xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c index 05fffb9415a2..68fe863f9d54 100644 --- a/drivers/i2c/busses/i2c-ixp4xx.c +++ b/drivers/i2c/busses/i2c-ixp4xx.c @@ -138,7 +138,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev) gpio_line_set(gpio->sda_pin, 0); err = i2c_bit_add_bus(&drv_data->adapter); - if (err != 0) + if (err) { printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id); kfree(drv_data); -- cgit v1.2.3 From 8e4d9dcb4205dd43c4297168022ed0c6874fb918 Mon Sep 17 00:00:00 2001 From: Daniel Ritz Date: Sat, 25 Nov 2006 11:09:17 -0800 Subject: [PATCH] fix "pcmcia: fix 'rmmod pcmcia' with unbound devices" Add required locking to dfbc9e9d33adb1ac9910dd7f8ceb911947039a52 Signed-off-by: Daniel Ritz Cc: Dominik Brodowski Cc: Pavol Gono Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/ds.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index a20d84d707d9..21d83a895b21 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -1272,7 +1272,9 @@ static void pcmcia_bus_remove_socket(struct class_device *class_dev, pccard_register_pcmcia(socket, NULL); /* unregister any unbound devices */ + mutex_lock(&socket->skt_mutex); pcmcia_card_remove(socket, NULL); + mutex_unlock(&socket->skt_mutex); pcmcia_put_socket(socket); -- cgit v1.2.3 From 2601a46474db2dcbc08ee690e56f08a10abe65cb Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 25 Nov 2006 11:09:27 -0800 Subject: [PATCH] rtc framework handles periodic irqs The RTC framework has an irq_set_freq() method that should be used to manage the periodic IRQ frequency, but the current ioctl logic doesn't know how to do that. This patch teaches it how. This means that drivers implementing irq_set_freq() will automatically support RTC_IRQP_{READ,SET} ioctls; that logic doesn't need duplication within the driver. [akpm@osdl.org: export rtc_irq_set_freq] Signed-off-by: David Brownell Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 1 + drivers/rtc/rtc-dev.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 579cd667b16f..4783ec68fb3c 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -265,3 +265,4 @@ int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int } return err; } +EXPORT_SYMBOL_GPL(rtc_irq_set_freq); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 583789c66cdb..3109865e8d73 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -214,7 +214,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, struct rtc_wkalrm alarm; void __user *uarg = (void __user *) arg; - /* check that the calles has appropriate permissions + /* check that the calling task has appropriate permissions * for certain ioctls. doing this check here is useful * to avoid duplicate code in each driver. */ @@ -299,6 +299,17 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, err = rtc_set_time(class_dev, &tm); break; + + case RTC_IRQP_READ: + if (ops->irq_set_freq) + err = put_user(rtc->irq_freq, (unsigned long *) arg); + break; + + case RTC_IRQP_SET: + if (ops->irq_set_freq) + err = rtc_irq_set_freq(class_dev, rtc->irq_task, arg); + break; + #if 0 case RTC_EPOCH_SET: #ifndef rtc_epoch -- cgit v1.2.3 From d728b1e69fd5829ec2ab2434381e5a268d4f684a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 25 Nov 2006 11:09:28 -0800 Subject: [PATCH] rtc class locking bugfixes I got a lockdep warning when running "rtctest" so I though it'd be good to see what was up. - The warning was for rtc->irq_task_lock, gotten from rtc_update_irq() by irq handlerss ... but in a handful of other cases, grabbed without blocking IRQs. - Some callers to rtc_update_irq() were not ensuring IRQs were blocked, yet the routine expects that; make sure all callers block IRQs. It would appear that RTC API tests haven't been part of anyone's kernel regression test suite recently, at least not with lockdep running. Signed-off-by: David Brownell Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 15 +++++++++++---- drivers/rtc/rtc-at91.c | 3 ++- drivers/rtc/rtc-dev.c | 12 +++++++----- drivers/rtc/rtc-ds1553.c | 3 ++- drivers/rtc/rtc-test.c | 2 ++ 5 files changed, 24 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4783ec68fb3c..6f11f6dfdd9d 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -145,6 +145,13 @@ int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_set_alarm); +/** + * rtc_update_irq - report RTC periodic, alarm, and/or update irqs + * @class_dev: the rtc's class device + * @num: how many irqs are being reported (usually one) + * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF + * Context: in_interrupt(), irqs blocked + */ void rtc_update_irq(struct class_device *class_dev, unsigned long num, unsigned long events) { @@ -201,12 +208,12 @@ int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) if (task == NULL || task->func == NULL) return -EINVAL; - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == NULL) { rtc->irq_task = task; retval = 0; } - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); return retval; } @@ -216,10 +223,10 @@ void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task) { struct rtc_device *rtc = to_rtc_device(class_dev); - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task == task) rtc->irq_task = NULL; - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); } EXPORT_SYMBOL_GPL(rtc_irq_unregister); diff --git a/drivers/rtc/rtc-at91.c b/drivers/rtc/rtc-at91.c index bd61e99540a3..5c8addcaf1fb 100644 --- a/drivers/rtc/rtc-at91.c +++ b/drivers/rtc/rtc-at91.c @@ -292,7 +292,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev) AT91_RTC_CALEV); ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_SHARED, "at91_rtc", pdev); + IRQF_DISABLED | IRQF_SHARED, + "at91_rtc", pdev); if (ret) { printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", AT91_ID_SYS); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 3109865e8d73..814b9e1873f5 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -61,7 +61,9 @@ static void rtc_uie_task(void *data) int err; err = rtc_read_time(&rtc->class_dev, &tm); - spin_lock_irq(&rtc->irq_lock); + + local_irq_disable(); + spin_lock(&rtc->irq_lock); if (rtc->stop_uie_polling || err) { rtc->uie_task_active = 0; } else if (rtc->oldsecs != tm.tm_sec) { @@ -74,11 +76,11 @@ static void rtc_uie_task(void *data) } else if (schedule_work(&rtc->uie_task) == 0) { rtc->uie_task_active = 0; } - spin_unlock_irq(&rtc->irq_lock); + spin_unlock(&rtc->irq_lock); if (num) rtc_update_irq(&rtc->class_dev, num, RTC_UF | RTC_IRQF); + local_irq_enable(); } - static void rtc_uie_timer(unsigned long data) { struct rtc_device *rtc = (struct rtc_device *)data; @@ -238,10 +240,10 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, /* avoid conflicting IRQ users */ if (cmd == RTC_PIE_ON || cmd == RTC_PIE_OFF || cmd == RTC_IRQP_SET) { - spin_lock(&rtc->irq_task_lock); + spin_lock_irq(&rtc->irq_task_lock); if (rtc->irq_task) err = -EBUSY; - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irq(&rtc->irq_task_lock); if (err < 0) return err; diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c index 78552e6e76aa..001eb1123a65 100644 --- a/drivers/rtc/rtc-ds1553.c +++ b/drivers/rtc/rtc-ds1553.c @@ -340,7 +340,8 @@ static int __init ds1553_rtc_probe(struct platform_device *pdev) if (pdata->irq >= 0) { writeb(0, ioaddr + RTC_INTERRUPTS); - if (request_irq(pdata->irq, ds1553_rtc_interrupt, IRQF_SHARED, + if (request_irq(pdata->irq, ds1553_rtc_interrupt, + IRQF_DISABLED | IRQF_SHARED, pdev->name, pdev) < 0) { dev_warn(&pdev->dev, "interrupt not available.\n"); pdata->irq = -1; diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index bc4bd24508a2..6ef9c62d5032 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -99,6 +99,7 @@ static ssize_t test_irq_store(struct device *dev, struct rtc_device *rtc = platform_get_drvdata(plat_dev); retval = count; + local_irq_disable(); if (strncmp(buf, "tick", 4) == 0) rtc_update_irq(&rtc->class_dev, 1, RTC_PF | RTC_IRQF); else if (strncmp(buf, "alarm", 5) == 0) @@ -107,6 +108,7 @@ static ssize_t test_irq_store(struct device *dev, rtc_update_irq(&rtc->class_dev, 1, RTC_UF | RTC_IRQF); else retval = -EINVAL; + local_irq_enable(); return retval; } -- cgit v1.2.3 From 17ad78e59a0334d64c3a37f964b15ab9918313c7 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 25 Nov 2006 11:09:29 -0800 Subject: [PATCH] drivers/rtc/rtc-rs5c372.c: fix a NULL dereference The correct order is: NULL check before dereference This was a guaranteed NULL dereference with debugging enabled since rs5c372_sysfs_show_osc() does actually pass NULL... Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Acked-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-rs5c372.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index 2a86632580f1..a44fe4efa216 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -126,13 +126,13 @@ static int rs5c372_get_trim(struct i2c_client *client, int *osc, int *trim) return -EIO; } - dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim); - if (osc) *osc = (buf & RS5C372_TRIM_XSL) ? 32000 : 32768; - if (trim) + if (trim) { *trim = buf & RS5C372_TRIM_MASK; + dev_dbg(&client->dev, "%s: raw trim=%x\n", __FUNCTION__, *trim); + } return 0; } -- cgit v1.2.3 From 82189b9807e05ea8d1f69de5bf92eaf244a0eb12 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Sat, 25 Nov 2006 11:09:30 -0800 Subject: [PATCH] Fix device_attribute memory leak in device_del dev->devt_attr is allocated in device_add() but it is never freed in device_del() in the drivers/base/core.c file (reported by kmemleak). Signed-off-by: Catalin Marinas Acked-by: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 68ad11af22b4..002fde46d38d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -591,8 +591,10 @@ void device_del(struct device * dev) if (parent) klist_del(&dev->knode_parent); - if (dev->devt_attr) + if (dev->devt_attr) { device_remove_file(dev, dev->devt_attr); + kfree(dev->devt_attr); + } if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); -- cgit v1.2.3 From a1b26c32af51d0fd82754bc06b495dd03c2f2d58 Mon Sep 17 00:00:00 2001 From: Jeremy Higdon Date: Sat, 25 Nov 2006 11:09:33 -0800 Subject: [PATCH] sgiioc4: Disable module unload This patch removes a module_exit function that sgiioc4 should not have had. It seems that the IDE layer doesn't support submodule unloading. sgiioc4 was the only driver in drivers/ide/pci that had an exit function. After an unload, the devices would stay around and the next attempt to reference would crash... Signed-off-by: Jeremy Higdon Acked-by: "Bartlomiej Zolnierkiewicz" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/pci/sgiioc4.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 244f7eb7006d..cfad09accf52 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -768,14 +768,7 @@ ioc4_ide_init(void) return ioc4_register_submodule(&ioc4_ide_submodule); } -static void __devexit -ioc4_ide_exit(void) -{ - ioc4_unregister_submodule(&ioc4_ide_submodule); -} - late_initcall(ioc4_ide_init); /* Call only after IDE init is done */ -module_exit(ioc4_ide_exit); MODULE_AUTHOR("Aniket Malatpure/Jeremy Higdon"); MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card"); -- cgit v1.2.3 From 5e66b0b5f187c811419ff10cfb5668c028a64d57 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Sat, 25 Nov 2006 11:09:35 -0800 Subject: [PATCH] tlclk: fix platform_device_register_simple() error check The return value of platform_device_register_simple() should be checked by IS_ERR(). This patch also fix misc_register() error case. Because misc_register() returns error code. Cc: Sebastien Bouchard Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tlclk.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 2444a0e24b31..244d30a03fef 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c @@ -792,15 +792,14 @@ static int __init tlclk_init(void) ret = misc_register(&tlclk_miscdev); if (ret < 0) { printk(KERN_ERR "tlclk: misc_register returns %d.\n", ret); - ret = -EBUSY; goto out3; } tlclk_device = platform_device_register_simple("telco_clock", -1, NULL, 0); - if (!tlclk_device) { + if (IS_ERR(tlclk_device)) { printk(KERN_ERR "tlclk: platform_device_register failed.\n"); - ret = -EBUSY; + ret = PTR_ERR(tlclk_device); goto out4; } -- cgit v1.2.3 From 9dce447a542d8b4bedf13d6a4c4fc6737240372e Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Sat, 25 Nov 2006 11:09:38 -0800 Subject: [PATCH] usb: ati remote memleak fix This is a bug. When checking for ati_remote->outbuf we free freeing ati_remote->inbuf so we end up freeing ati_remote->inbuf twice. Also the checks for 'ati_remote->inbuf != NULL' and 'ati_remote->outbuf != NULL' are redundant as usb_buffer_free() does this. Signed-off-by: Mariusz Kozlowski Acked-by: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/input/ati_remote.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index f659f3028ad2..787b847d38cc 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -636,13 +636,11 @@ static void ati_remote_free_buffers(struct ati_remote *ati_remote) if (ati_remote->out_urb) usb_free_urb(ati_remote->out_urb); - if (ati_remote->inbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->inbuf, ati_remote->inbuf_dma); + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->inbuf, ati_remote->inbuf_dma); - if (ati_remote->outbuf) - usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, - ati_remote->inbuf, ati_remote->outbuf_dma); + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->outbuf, ati_remote->outbuf_dma); } static void ati_remote_input_init(struct ati_remote *ati_remote) -- cgit v1.2.3 From 95f6134e175fd69ab3f088f7a09adbd3fd3548e1 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 23 Nov 2006 11:48:28 -0800 Subject: [6PACK]: Masking bug in 6pack driver. Looks like a broken masking to me, binary not is used where bitwise not was intended. Signed-off-by: Jean Delvare Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- drivers/net/hamradio/6pack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 86b3bb9bec2d..92420f007b97 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -914,7 +914,7 @@ static void decode_prio_command(struct sixpack *sp, unsigned char cmd) printk(KERN_DEBUG "6pack: protocol violation\n"); else sp->status = 0; - cmd &= !SIXP_RX_DCD_MASK; + cmd &= ~SIXP_RX_DCD_MASK; } sp->status = cmd & SIXP_PRIO_DATA_MASK; } else { /* output watchdog char if idle */ -- cgit v1.2.3 From c4e46b9567669eb5e1182d4b12c2d889ce27da64 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 16 Nov 2006 18:31:04 -0300 Subject: V4L/DVB (4831): Fix tuning on older budget DVBS cards. Fixes to DISEQC on these cards inadvertently broke normal tone/voltage signalling. This restores the necessary function. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e58f0391e9d1..e28617bd5641 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -382,6 +382,7 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; + budget->dvb_frontend->ops.set_tone = budget_set_tone; break; } break; -- cgit v1.2.3 From bc495b66d048d64a9b8aeb49ca8405f4687ca123 Mon Sep 17 00:00:00 2001 From: Oliver Endriss Date: Sun, 19 Nov 2006 02:15:37 -0300 Subject: V4L/DVB (4840): Budget: diseqc_method module parameter for cards with subsystem-id 13c2:1003 New module parameter diseqc_method for cards with subsystem-id 13c2:1003. - 0: unreliable method, can be used by all board revisions (default) - 1: reliable method, works for newer board layouts only The parameter has no effect for cards with other subsystem-ids. Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index e28617bd5641..56f1c80defc6 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c @@ -46,6 +46,10 @@ #include "lnbp21.h" #include "bsru6.h" +static int diseqc_method; +module_param(diseqc_method, int, 0444); +MODULE_PARM_DESC(diseqc_method, "Select DiSEqC method for subsystem id 13c2:1003, 0: default, 1: more reliable (for newer revisions only)"); + static void Set22K (struct budget *budget, int state) { struct saa7146_dev *dev=budget->dev; @@ -382,7 +386,11 @@ static void frontend_init(struct budget *budget) if (budget->dvb_frontend) { budget->dvb_frontend->ops.tuner_ops.set_params = alps_bsru6_tuner_set_params; budget->dvb_frontend->tuner_priv = &budget->i2c_adap; - budget->dvb_frontend->ops.set_tone = budget_set_tone; + if (budget->dev->pci->subsystem_device == 0x1003 && diseqc_method == 0) { + budget->dvb_frontend->ops.diseqc_send_master_cmd = budget_diseqc_send_master_cmd; + budget->dvb_frontend->ops.diseqc_send_burst = budget_diseqc_send_burst; + budget->dvb_frontend->ops.set_tone = budget_set_tone; + } break; } break; -- cgit v1.2.3 From 30d9464c76743160612e7de0b2f5f656c78915d3 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 16 Nov 2006 22:12:40 -0300 Subject: V4L/DVB (4832): Fix uninitialised variable in dvb_frontend_swzigzag Spotted by coverity/Adrian Bunk. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 53304e6991ac..a2ab2eebfc68 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -348,7 +348,7 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra static void dvb_frontend_swzigzag(struct dvb_frontend *fe) { - fe_status_t s; + fe_status_t s = 0; struct dvb_frontend_private *fepriv = fe->frontend_priv; /* if we've got no parameters, just keep idling */ -- cgit v1.2.3 From a5bbc7d94cf1dcb2100eeaf68791a401ad7ce54d Mon Sep 17 00:00:00 2001 From: Ira Snyder Date: Mon, 20 Nov 2006 07:20:48 -0300 Subject: V4L/DVB (4849): Add missing spin_unlock to saa6588 decoder driver Sparse noticed a lock imbalance in read_from_buf(). Further inspection shows that the lock should not be held when the function exits. This adds a spin_unlock_irqrestore(), so that every exit path of the read_from_buf() function is consistent. The unlock was missing on an error path. Signed-off-by: Ira W. Snyder Signed-off-by: Hans J. Koch Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa6588.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index a81285ca7d5b..7b9859c33018 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -212,8 +212,10 @@ static void read_from_buf(struct saa6588 *s, struct rds_command *a) if (rd_blocks > s->block_count) rd_blocks = s->block_count; - if (!rd_blocks) + if (!rd_blocks) { + spin_unlock_irqrestore(&s->lock, flags); return; + } for (i = 0; i < rd_blocks; i++) { if (block_to_user_buf(s, buf_ptr)) { -- cgit v1.2.3 From 5718bbd2d92b9c2aa2f5700e4d3ed9d72f72f47e Mon Sep 17 00:00:00 2001 From: Luca Risolia Date: Tue, 21 Nov 2006 08:13:59 -0300 Subject: V4L/DVB (4865): Fix: Slot 0 not NULL on disconnecting SN9C10x PC Camera The patch fix bug 5748. Signed-off-by: Luca Risolia Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/et61x251/et61x251_core.c | 3 +-- drivers/media/video/sn9c102/sn9c102_core.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index f786ab11d2cd..86e353b26b53 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c @@ -1182,8 +1182,6 @@ static void et61x251_release_resources(struct et61x251_device* cam) video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); - usb_put_dev(cam->usbdev); - mutex_unlock(&et61x251_sysfs_lock); kfree(cam->control_buffer); @@ -1275,6 +1273,7 @@ static int et61x251_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { et61x251_release_resources(cam); + usb_put_dev(cam->usbdev); mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index a4702d3c2aca..42fb60d985b9 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -1462,8 +1462,6 @@ static void sn9c102_release_resources(struct sn9c102_device* cam) video_set_drvdata(cam->v4ldev, NULL); video_unregister_device(cam->v4ldev); - usb_put_dev(cam->usbdev); - mutex_unlock(&sn9c102_sysfs_lock); kfree(cam->control_buffer); @@ -1555,6 +1553,7 @@ static int sn9c102_release(struct inode* inode, struct file* filp) if (cam->state & DEV_DISCONNECTED) { sn9c102_release_resources(cam); + usb_put_dev(cam->usbdev); mutex_unlock(&cam->dev_mutex); kfree(cam); return 0; -- cgit v1.2.3 From f7668162a366d1ce0fe84122d11108e13a8ce950 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 25 Nov 2006 09:40:28 -0300 Subject: V4L/DVB (4885): Improve saa711x check The old code would accept any device on the same i2c address as the saa711x chips as an saa711x. However, this fails with saa717x chips, which use that same address and so are misdetected as a saa7111. Now check whether the chip is really a saa711x model. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7115.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c index c5719f7bd1ac..f28398dd9d93 100644 --- a/drivers/media/video/saa7115.c +++ b/drivers/media/video/saa7115.c @@ -1464,8 +1464,6 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) client->driver = &i2c_driver_saa711x; snprintf(client->name, sizeof(client->name) - 1, "saa7115"); - v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1); - for (i=0;i<0x0f;i++) { saa711x_write(client, 0, i); name[i] = (saa711x_read(client, 0) &0x0f) +'0'; @@ -1477,6 +1475,13 @@ static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind) saa711x_write(client, 0, 5); chip_id = saa711x_read(client, 0) & 0x0f; + /* Check whether this chip is part of the saa711x series */ + if (memcmp(name, "1f711", 5)) { + v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n", + address << 1, name); + return 0; + } + snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id); v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name); -- cgit v1.2.3 From 221a09d5c4cb8384d9be74db60f37a5752675255 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Wed, 22 Nov 2006 18:01:21 -0300 Subject: V4L/DVB (4874): Fix oops on symbol rate==0 The tda10086 causes an oops (divide by zero) if a zero symbol rate is used; this prevents this. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/tda10086.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/tda10086.c b/drivers/media/dvb/frontends/tda10086.c index 7456b0b9976b..4c27a2d90a38 100644 --- a/drivers/media/dvb/frontends/tda10086.c +++ b/drivers/media/dvb/frontends/tda10086.c @@ -441,6 +441,10 @@ static int tda10086_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa dprintk ("%s\n", __FUNCTION__); + // check for invalid symbol rate + if (fe_params->u.qpsk.symbol_rate < 500000) + return -EINVAL; + // calculate the updated frequency (note: we convert from Hz->kHz) tmp64 = tda10086_read_byte(state, 0x52); tmp64 |= (tda10086_read_byte(state, 0x51) << 8); -- cgit v1.2.3 From c31f571d9f42fa2e89148811730fe3dc64943a6e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 22 Nov 2006 12:39:43 +0900 Subject: [PATCH] libata: don't schedule EH on wcache on/off if old EH Do not schedule EH for revalidation on wcache on/off if old EH. Old EH cannot handle it and will result in WARN_ON()'s and oops. This closes bug #7412. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 5c1fc467fc7f..22643c0d9a56 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1451,6 +1451,7 @@ nothing_to_do: static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) { + struct ata_port *ap = qc->ap; struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; int need_sense = (qc->err_mask != 0); @@ -1459,11 +1460,12 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE * cache */ - if (!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && + if (ap->ops->error_handler && + !need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && ((qc->tf.feature == SETFEATURES_WC_ON) || (qc->tf.feature == SETFEATURES_WC_OFF))) { - qc->ap->eh_info.action |= ATA_EH_REVALIDATE; - ata_port_schedule_eh(qc->ap); + ap->eh_info.action |= ATA_EH_REVALIDATE; + ata_port_schedule_eh(ap); } /* For ATA pass thru (SAT) commands, generate a sense block if @@ -1490,8 +1492,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) } } - if (need_sense && !qc->ap->ops->error_handler) - ata_dump_status(qc->ap->id, &qc->result_tf); + if (need_sense && !ap->ops->error_handler) + ata_dump_status(ap->id, &qc->result_tf); qc->scsidone(cmd); -- cgit v1.2.3 From f33d625f40e3b803c4cdea3219abb96cabf5ea03 Mon Sep 17 00:00:00 2001 From: Jason Gaston Date: Tue, 21 Nov 2006 16:55:58 -0800 Subject: [PATCH] ahci: AHCI mode SATA patch for Intel ICH9 This patch adds the Intel ICH9 AHCI controller DID's for SATA support. Signed-off-by: Jason Gaston Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 234197e57e9e..f510e1196dc6 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -314,6 +314,17 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x2824), board_ahci }, /* ICH8 */ { PCI_VDEVICE(INTEL, 0x2829), board_ahci }, /* ICH8M */ { PCI_VDEVICE(INTEL, 0x282a), board_ahci }, /* ICH8M */ + { PCI_VDEVICE(INTEL, 0x2922), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2923), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2924), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2925), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2927), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x2929), board_ahci }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292a), board_ahci }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292b), board_ahci }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x292f), board_ahci }, /* ICH9M */ + { PCI_VDEVICE(INTEL, 0x294d), board_ahci }, /* ICH9 */ + { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ /* JMicron */ { PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */ -- cgit v1.2.3 From 08475a1920aa7acc535324d6991b830fa7625bd8 Mon Sep 17 00:00:00 2001 From: Brian King Date: Mon, 20 Nov 2006 13:51:56 -0600 Subject: [PATCH] libata: Fixup ata_sas_queuecmd to handle __ata_scsi_queuecmd failure Fixes ata_sas_queuecmd to properly handle a failure from __ata_scsi_queuecmd. Signed-off-by: Brian King Signed-off-by: Jeff Garzik --- drivers/ata/libata-scsi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 22643c0d9a56..47ea111d5ace 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3347,20 +3347,23 @@ EXPORT_SYMBOL_GPL(ata_sas_slave_configure); * @ap: ATA port to which the command is being sent * * RETURNS: - * Zero. + * Return value from __ata_scsi_queuecmd() if @cmd can be queued, + * 0 otherwise. */ int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), struct ata_port *ap) { + int rc = 0; + ata_scsi_dump_cdb(ap, cmd); if (likely(ata_scsi_dev_enabled(ap->device))) - __ata_scsi_queuecmd(cmd, done, ap->device); + rc = __ata_scsi_queuecmd(cmd, done, ap->device); else { cmd->result = (DID_BAD_TARGET << 16); done(cmd); } - return 0; + return rc; } EXPORT_SYMBOL_GPL(ata_sas_queuecmd); -- cgit v1.2.3 From a68077defb3337342981a0d3a4df3380496a8a87 Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Wed, 22 Nov 2006 00:06:06 +0000 Subject: [PATCH] zd1211rw: Fix of a locking bug This patch fixes the bug as reported in the kernel bug tracker under the id 7244. The bug was simply that the interrupt lock has been locked outside an interrupt without blocking the interrupt. Signed-off-by: Ulrich Kunitz Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 3faaeb2b7c89..a15b09549245 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -366,15 +366,6 @@ error: return r; } -static void disable_read_regs_int(struct zd_usb *usb) -{ - struct zd_usb_interrupt *intr = &usb->intr; - - spin_lock(&intr->lock); - intr->read_regs_enabled = 0; - spin_unlock(&intr->lock); -} - #define urb_dev(urb) (&(urb)->dev->dev) static inline void handle_regs_int(struct urb *urb) @@ -1156,10 +1147,19 @@ static void prepare_read_regs_int(struct zd_usb *usb) { struct zd_usb_interrupt *intr = &usb->intr; - spin_lock(&intr->lock); + spin_lock_irq(&intr->lock); intr->read_regs_enabled = 1; INIT_COMPLETION(intr->read_regs.completion); - spin_unlock(&intr->lock); + spin_unlock_irq(&intr->lock); +} + +static void disable_read_regs_int(struct zd_usb *usb) +{ + struct zd_usb_interrupt *intr = &usb->intr; + + spin_lock_irq(&intr->lock); + intr->read_regs_enabled = 0; + spin_unlock_irq(&intr->lock); } static int get_results(struct zd_usb *usb, u16 *values, @@ -1171,7 +1171,7 @@ static int get_results(struct zd_usb *usb, u16 *values, struct read_regs_int *rr = &intr->read_regs; struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; - spin_lock(&intr->lock); + spin_lock_irq(&intr->lock); r = -EIO; /* The created block size seems to be larger than expected. @@ -1204,7 +1204,7 @@ static int get_results(struct zd_usb *usb, u16 *values, r = 0; error_unlock: - spin_unlock(&intr->lock); + spin_unlock_irq(&intr->lock); return r; } -- cgit v1.2.3 From a88556a4b24baff99f5d2a2a05202c4aca44ea05 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 28 Nov 2006 14:16:37 -0500 Subject: Revert "[PATCH] zd1211rw: Removed unneeded packed attributes" This reverts commit 4e1bbd846d00a245dcf78b6b331d8a9afed8e6d7. Quoth Daniel Drake : "A user reported that commit 4e1bbd846d00a245dcf78b6b331d8a9afed8e6d7 (Remove unneeded packed attributes) breaks the zd1211rw driver on ARM." Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_ieee80211.h | 2 +- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- drivers/net/wireless/zd1211rw/zd_mac.h | 4 ++-- drivers/net/wireless/zd1211rw/zd_usb.h | 14 +++++++------- 4 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h index f63245b0d966..36329890dfec 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h @@ -64,7 +64,7 @@ struct cck_plcp_header { u8 service; __le16 length; __le16 crc16; -}; +} __attribute__((packed)); static inline u8 zd_cck_plcp_header_rate(const struct cck_plcp_header *header) { diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a7d29bddb298..e5fedf968c19 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -721,7 +721,7 @@ struct zd_rt_hdr { u8 rt_rate; u16 rt_channel; u16 rt_chbitmask; -}; +} __attribute__((packed)); static void fill_rt_header(void *buffer, struct zd_mac *mac, const struct ieee80211_rx_stats *stats, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index b8ea3de7924a..e4dd40a6fec3 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -82,7 +82,7 @@ struct zd_ctrlset { struct rx_length_info { __le16 length[3]; __le16 tag; -}; +} __attribute__((packed)); #define RX_LENGTH_INFO_TAG 0x697e @@ -93,7 +93,7 @@ struct rx_status { u8 signal_quality_ofdm; u8 decryption_type; u8 frame_status; -}; +} __attribute__((packed)); /* rx_status field decryption_type */ #define ZD_RX_NO_WEP 0 diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h index e81a2d3cfffd..317d37c36679 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/zd1211rw/zd_usb.h @@ -74,17 +74,17 @@ enum control_requests { struct usb_req_read_regs { __le16 id; __le16 addr[0]; -}; +} __attribute__((packed)); struct reg_data { __le16 addr; __le16 value; -}; +} __attribute__((packed)); struct usb_req_write_regs { __le16 id; struct reg_data reg_writes[0]; -}; +} __attribute__((packed)); enum { RF_IF_LE = 0x02, @@ -101,7 +101,7 @@ struct usb_req_rfwrite { /* RF2595: 24 */ __le16 bit_values[0]; /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ -}; +} __attribute__((packed)); /* USB interrupt */ @@ -118,12 +118,12 @@ enum usb_int_flags { struct usb_int_header { u8 type; /* must always be 1 */ u8 id; -}; +} __attribute__((packed)); struct usb_int_regs { struct usb_int_header hdr; struct reg_data regs[0]; -}; +} __attribute__((packed)); struct usb_int_retry_fail { struct usb_int_header hdr; @@ -131,7 +131,7 @@ struct usb_int_retry_fail { u8 _dummy; u8 addr[ETH_ALEN]; u8 ibss_wakeup_dest; -}; +} __attribute__((packed)); struct read_regs_int { struct completion completion; -- cgit v1.2.3 From 967bf623e9f5eecfb056b1ba7e0efd74a21c9c3a Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Tue, 28 Nov 2006 23:11:52 +0000 Subject: [PATCH] Fix Intel/Sharp command set erase suspend bug When we sleep and wait for a suspended operation to be resumed, go back and check until it's ready -- don't just continue after the first time we're woken. This can cause file system corruption. Signed-off-by: Joakim Tjernlund Signed-off-by: David Woodhouse Signed-off-by: Linus Torvalds --- drivers/mtd/chips/cfi_cmdset_0001.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 7ea49a0d5ec3..296159ec5189 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -1087,7 +1087,7 @@ static int inval_cache_and_wait_for_operation( } spin_lock(chip->mutex); - if (chip->state != chip_state) { + while (chip->state != chip_state) { /* Someone's suspended the operation: sleep */ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); -- cgit v1.2.3 From 41669553353554211310cdb23079d58af1fda41e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 29 Nov 2006 11:33:14 +0900 Subject: [PATCH] ahci: ignore PORT_IRQ_IF_ERR on JMB controllers JMicron AHCI controllers set PORT_IRQ_IF_ERR on device errors. The IRQ status bit indicates interface error or protocol mismatch and ahci driver interprets it into AC_ERR_ATA_BUS. So, whenever an ATAPI device raises check condition, ahci interprets it as ATA bus error and thus resets it which, in turn, raises check condition thus creating a reset loop and rendering the device unuseable. This patch makes JMB controllers ignore PORT_IRQ_IF_ERR when interpreting error condition. Signed-off-by: Tejun Heo Cc: Justin Tsai --- drivers/ata/ahci.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index f510e1196dc6..bddb14e91d3c 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -78,6 +78,7 @@ enum { board_ahci = 0, board_ahci_vt8251 = 1, + board_ahci_ign_iferr = 2, /* global controller registers */ HOST_CAP = 0x00, /* host capabilities */ @@ -168,6 +169,7 @@ enum { /* ap->flags bits */ AHCI_FLAG_RESET_NEEDS_CLO = (1 << 24), AHCI_FLAG_NO_NCQ = (1 << 25), + AHCI_FLAG_IGN_IRQ_IF_ERR = (1 << 26), /* ignore IRQ_IF_ERR */ }; struct ahci_cmd_hdr { @@ -295,6 +297,17 @@ static const struct ata_port_info ahci_port_info[] = { .udma_mask = 0x7f, /* udma0-6 ; FIXME */ .port_ops = &ahci_ops, }, + /* board_ahci_ign_iferr */ + { + .sht = &ahci_sht, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | + ATA_FLAG_SKIP_D2H_BSY | + AHCI_FLAG_IGN_IRQ_IF_ERR, + .pio_mask = 0x1f, /* pio0-4 */ + .udma_mask = 0x7f, /* udma0-6 ; FIXME */ + .port_ops = &ahci_ops, + }, }; static const struct pci_device_id ahci_pci_tbl[] = { @@ -327,11 +340,11 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */ /* JMicron */ - { PCI_VDEVICE(JMICRON, 0x2360), board_ahci }, /* JMicron JMB360 */ - { PCI_VDEVICE(JMICRON, 0x2361), board_ahci }, /* JMicron JMB361 */ - { PCI_VDEVICE(JMICRON, 0x2363), board_ahci }, /* JMicron JMB363 */ - { PCI_VDEVICE(JMICRON, 0x2365), board_ahci }, /* JMicron JMB365 */ - { PCI_VDEVICE(JMICRON, 0x2366), board_ahci }, /* JMicron JMB366 */ + { PCI_VDEVICE(JMICRON, 0x2360), board_ahci_ign_iferr }, /* JMB360 */ + { PCI_VDEVICE(JMICRON, 0x2361), board_ahci_ign_iferr }, /* JMB361 */ + { PCI_VDEVICE(JMICRON, 0x2363), board_ahci_ign_iferr }, /* JMB363 */ + { PCI_VDEVICE(JMICRON, 0x2365), board_ahci_ign_iferr }, /* JMB365 */ + { PCI_VDEVICE(JMICRON, 0x2366), board_ahci_ign_iferr }, /* JMB366 */ /* ATI */ { PCI_VDEVICE(ATI, 0x4380), board_ahci }, /* ATI SB600 non-raid */ @@ -980,6 +993,10 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) /* analyze @irq_stat */ ata_ehi_push_desc(ehi, "irq_stat 0x%08x", irq_stat); + /* some controllers set IRQ_IF_ERR on device errors, ignore it */ + if (ap->flags & AHCI_FLAG_IGN_IRQ_IF_ERR) + irq_stat &= ~PORT_IRQ_IF_ERR; + if (irq_stat & PORT_IRQ_TF_ERR) err_mask |= AC_ERR_DEV; -- cgit v1.2.3 From afdfe899e6420eac6c5eb3bc8c89456dff38d40e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 29 Nov 2006 11:26:47 +0900 Subject: [PATCH] libata: add missing sht->slave_destroy Many LLDs are missing sht->slave_destroy. The method is mandatory to support device warm unplugging (echo 1 > /sys/.../delete). Without it, libata might access released scsi device. Signed-off-by: Tejun Heo --- drivers/ata/ata_generic.c | 1 + drivers/ata/pata_ali.c | 1 + drivers/ata/pata_amd.c | 1 + drivers/ata/pata_artop.c | 1 + drivers/ata/pata_atiixp.c | 1 + drivers/ata/pata_cmd64x.c | 1 + drivers/ata/pata_cs5520.c | 1 + drivers/ata/pata_cs5530.c | 1 + drivers/ata/pata_cs5535.c | 1 + drivers/ata/pata_cypress.c | 1 + drivers/ata/pata_efar.c | 1 + drivers/ata/pata_hpt366.c | 1 + drivers/ata/pata_hpt37x.c | 1 + drivers/ata/pata_hpt3x2n.c | 1 + drivers/ata/pata_hpt3x3.c | 1 + drivers/ata/pata_isapnp.c | 1 + drivers/ata/pata_it821x.c | 1 + drivers/ata/pata_jmicron.c | 1 + drivers/ata/pata_legacy.c | 1 + drivers/ata/pata_mpiix.c | 1 + drivers/ata/pata_netcell.c | 1 + drivers/ata/pata_ns87410.c | 1 + drivers/ata/pata_oldpiix.c | 1 + drivers/ata/pata_opti.c | 1 + drivers/ata/pata_optidma.c | 1 + drivers/ata/pata_pcmcia.c | 1 + drivers/ata/pata_pdc2027x.c | 1 + drivers/ata/pata_pdc202xx_old.c | 1 + drivers/ata/pata_qdi.c | 1 + drivers/ata/pata_radisys.c | 1 + drivers/ata/pata_rz1000.c | 1 + drivers/ata/pata_sc1200.c | 1 + drivers/ata/pata_serverworks.c | 1 + drivers/ata/pata_sil680.c | 1 + drivers/ata/pata_sis.c | 1 + drivers/ata/pata_sl82c105.c | 1 + drivers/ata/pata_triflex.c | 1 + drivers/ata/pata_via.c | 1 + 38 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 377425e71391..4a80ff9312b8 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -116,6 +116,7 @@ static struct scsi_host_template generic_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 1d695df5860a..64eed99f6814 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -346,6 +346,7 @@ static struct scsi_host_template ali_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 5c47a9e0e0ca..8be46a63af74 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -333,6 +333,7 @@ static struct scsi_host_template amd_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 96a098020a8f..2cd30761ca1f 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -314,6 +314,7 @@ static struct scsi_host_template artop_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 1ce28d2125f4..4e1d3b59adbb 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -216,6 +216,7 @@ static struct scsi_host_template atiixp_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index b9bbd1d454bf..29a60df465da 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -275,6 +275,7 @@ static struct scsi_host_template cmd64x_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 2cd3c0ff76df..33d2b88f9c79 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -166,6 +166,7 @@ static struct scsi_host_template cs5520_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index a07cc81ef791..981f49223469 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -180,6 +180,7 @@ static struct scsi_host_template cs5530_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index f8def3f9c618..8dafa4a49fdc 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -184,6 +184,7 @@ static struct scsi_host_template cs5535_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 247b43608b14..5a0b811907ee 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -135,6 +135,7 @@ static struct scsi_host_template cy82c693_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index ef18c60fe140..755f79279de3 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -233,6 +233,7 @@ static struct scsi_host_template efar_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 6d3e4c0f15fe..c0e150a9586b 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -329,6 +329,7 @@ static struct scsi_host_template hpt36x_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index fce3fcdc7e79..1eeb16f0fb02 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -775,6 +775,7 @@ static struct scsi_host_template hpt37x_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 58cfb2bc8098..47d7664e9eee 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -341,6 +341,7 @@ static struct scsi_host_template hpt3x2n_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index 3334d72e251b..d216cc564b56 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -118,6 +118,7 @@ static struct scsi_host_template hpt3x3_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 640b8b0954f5..40ca2b82b7fc 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -34,6 +34,7 @@ static struct scsi_host_template isapnp_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 18ff3e59a89b..7f68f14be6fd 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -675,6 +675,7 @@ static struct scsi_host_template it821x_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 52a2bdf3c38d..0210b10d49cd 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -136,6 +136,7 @@ static struct scsi_host_template jmicron_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index 10231ef731d1..b39078b2a47b 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -135,6 +135,7 @@ static struct scsi_host_template legacy_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index 9dfe3e9abea3..e00d406bfdf5 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -166,6 +166,7 @@ static struct scsi_host_template mpiix_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index f5672de99c22..1963a4d35873 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -62,6 +62,7 @@ static struct scsi_host_template netcell_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, /* Use standard CHS mapping rules */ .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 2a3dbeed89b4..7ec800f00ec8 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -156,6 +156,7 @@ static struct scsi_host_template ns87410_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index fc947dfecd73..8837256632e9 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -231,6 +231,7 @@ static struct scsi_host_template oldpiix_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index a7320ba15575..c6319cf50de4 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -202,6 +202,7 @@ static struct scsi_host_template opti_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index c6906b4215de..2f4770cce04e 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -359,6 +359,7 @@ static struct scsi_host_template optidma_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index e93ea2702c73..999922de476e 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -69,6 +69,7 @@ static struct scsi_host_template pcmcia_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index d894d9918b1d..beb6d10a234b 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -141,6 +141,7 @@ static struct scsi_host_template pdc2027x_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 5ba9eb20a6c2..6baf51b2fda1 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -269,6 +269,7 @@ static struct scsi_host_template pdc_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index 2c3cc0ccc606..314938dea1fc 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -164,6 +164,7 @@ static struct scsi_host_template qdi_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 1af83d7694d5..048c2bb21ef1 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -227,6 +227,7 @@ static struct scsi_host_template radisys_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 4533b6357d99..e4e5ea423fef 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -90,6 +90,7 @@ static struct scsi_host_template rz1000_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 067d9d223e35..0c75dae74764 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -193,6 +193,7 @@ static struct scsi_host_template sc1200_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 5bbf76ec14a4..be7f60efcb61 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -325,6 +325,7 @@ static struct scsi_host_template serverworks_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 4a2b72b4be8a..11942fd03b55 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -225,6 +225,7 @@ static struct scsi_host_template sil680_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index b9ffafb4198c..91e85f90941d 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -545,6 +545,7 @@ static struct scsi_host_template sis_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 08a6dc88676f..dc1cfc6d805b 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -237,6 +237,7 @@ static struct scsi_host_template sl82c105_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 9640f80e8b0d..bfda1f7e760a 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -192,6 +192,7 @@ static struct scsi_host_template triflex_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 1e7be9eee9c3..c5f1616d224d 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -295,6 +295,7 @@ static struct scsi_host_template via_sht = { .proc_name = DRV_NAME, .dma_boundary = ATA_DMA_BOUNDARY, .slave_configure = ata_scsi_slave_config, + .slave_destroy = ata_scsi_slave_destroy, .bios_param = ata_std_bios_param, }; -- cgit v1.2.3 From 315917d23fdd20a0f4ff99b9228de5840d9d276c Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 29 Nov 2006 22:21:33 +0100 Subject: [PATCH] r8169: Fix iteration variable sign This changes the type of variable "i" in rtl8169_init_one() from "unsigned int" to "int". "i" is checked for < 0 later, which can never happen for "unsigned". This results in broken error handling. Signed-off-by: Michael Buesch Signed-off-by: Francois Romieu Signed-off-by: Linus Torvalds --- drivers/net/r8169.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 27f90b2139c0..b977ed85ff39 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -1473,8 +1473,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct rtl8169_private *tp; struct net_device *dev; void __iomem *ioaddr; - unsigned int i, pm_cap; - int rc; + unsigned int pm_cap; + int i, rc; if (netif_msg_drv(&debug)) { printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", -- cgit v1.2.3 From e82153b54d75af31d5d4a84efe441e5719f34cfc Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Mon, 16 Oct 2006 10:09:01 +0530 Subject: RDMA/cma: Optimize cma_bind_loopback() to check for empty list Optimize to test for an empty list first. This ends up simplifying the code too. Signed-off-by: Krishna Kumar Acked-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 845090b0859c..4975d8154a78 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1481,19 +1481,18 @@ static int cma_bind_loopback(struct rdma_id_private *id_priv) u8 p; mutex_lock(&lock); + if (list_empty(&dev_list)) { + ret = -ENODEV; + goto out; + } list_for_each_entry(cma_dev, &dev_list, list) for (p = 1; p <= cma_dev->device->phys_port_cnt; ++p) - if (!ib_query_port (cma_dev->device, p, &port_attr) && + if (!ib_query_port(cma_dev->device, p, &port_attr) && port_attr.state == IB_PORT_ACTIVE) goto port_found; - if (!list_empty(&dev_list)) { - p = 1; - cma_dev = list_entry(dev_list.next, struct cma_device, list); - } else { - ret = -ENODEV; - goto out; - } + p = 1; + cma_dev = list_entry(dev_list.next, struct cma_device, list); port_found: ret = ib_get_cached_gid(cma_dev->device, p, 0, &gid); -- cgit v1.2.3 From e4022274cf8df1f78f9e20ba7e199a9edf655422 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Mon, 16 Oct 2006 10:09:08 +0530 Subject: RDMA/cma: Remove redundant check in cma_add_one Remove redundant check of node_guid in cma_add_one(). Signed-off-by: Krishna Kumar Acked-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 4975d8154a78..9aba4ea94933 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -2122,8 +2122,6 @@ static void cma_add_one(struct ib_device *device) cma_dev->device = device; cma_dev->node_guid = device->node_guid; - if (!cma_dev->node_guid) - goto err; init_completion(&cma_dev->comp); atomic_set(&cma_dev->refcount, 1); @@ -2135,9 +2133,6 @@ static void cma_add_one(struct ib_device *device) list_for_each_entry(id_priv, &listen_any_list, list) cma_listen_on_dev(id_priv, cma_dev); mutex_unlock(&lock); - return; -err: - kfree(cma_dev); } static int cma_remove_id_dev(struct rdma_id_private *id_priv) -- cgit v1.2.3 From f115db4803effd8207c3169590fb3f13336a4093 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Tue, 17 Oct 2006 10:09:09 +0530 Subject: RDMA/addr: Use time_after_eq() instead of time_after() in queue_req() In queue_req(), use time_after_eq() instead of time_after() for following reasons : - Improves insert time if multiple entries with same time are present. - set_timeout need not be called if entry with same time is added to the list (and that happens to be the entry with the smallest time), saving atomic/locking operations. - Earlier entries with same time are deleted first (fifo). Signed-off-by: Krishna Kumar Acked-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index e11187ecc931..a68d7c7df4ca 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -139,7 +139,7 @@ static void queue_req(struct addr_req *req) mutex_lock(&lock); list_for_each_entry_reverse(temp_req, &req_list, list) { - if (time_after(req->timeout, temp_req->timeout)) + if (time_after_eq(req->timeout, temp_req->timeout)) break; } -- cgit v1.2.3 From a1a733f65b091fdad3d0783e648c92b491933ab6 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Tue, 17 Oct 2006 10:09:11 +0530 Subject: RDMA/cma: Rewrite cma_req_handler() to encapsulate common code Rewrite cma_req_handler error handling case to encapsulate common code. Signed-off-by: Krishna Kumar Acked-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cma.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 9aba4ea94933..b449e26b84d2 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -935,13 +935,8 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) mutex_lock(&lock); ret = cma_acquire_dev(conn_id); mutex_unlock(&lock); - if (ret) { - ret = -ENODEV; - cma_exch(conn_id, CMA_DESTROYING); - cma_release_remove(conn_id); - rdma_destroy_id(&conn_id->id); - goto out; - } + if (ret) + goto release_conn_id; conn_id->cm_id.ib = cm_id; cm_id->context = conn_id; @@ -951,13 +946,17 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event) ret = cma_notify_user(conn_id, RDMA_CM_EVENT_CONNECT_REQUEST, 0, ib_event->private_data + offset, IB_CM_REQ_PRIVATE_DATA_SIZE - offset); - if (ret) { - /* Destroy the CM ID by returning a non-zero value. */ - conn_id->cm_id.ib = NULL; - cma_exch(conn_id, CMA_DESTROYING); - cma_release_remove(conn_id); - rdma_destroy_id(&conn_id->id); - } + if (!ret) + goto out; + + /* Destroy the CM ID by returning a non-zero value. */ + conn_id->cm_id.ib = NULL; + +release_conn_id: + cma_exch(conn_id, CMA_DESTROYING); + cma_release_remove(conn_id); + rdma_destroy_id(&conn_id->id); + out: cma_release_remove(listen_id); return ret; -- cgit v1.2.3 From bed8bdfddd851657cf9e5fd16bb44abb02ae7f42 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 23 Oct 2006 22:17:21 +0200 Subject: IB: kmemdup() cleanup Replace open coded kmemdup() to save some screen space, and allow inlining/not inlining to be triggered by gcc. Signed-off-by: Eric Sesterhenn Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 3 +-- drivers/infiniband/core/iwcm.c | 3 +-- drivers/infiniband/core/ucm.c | 6 ++---- drivers/infiniband/hw/mthca/mthca_provider.c | 3 +-- 4 files changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 25b1018a476c..82bc83baceaf 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -240,11 +240,10 @@ static void * cm_copy_private_data(const void *private_data, if (!private_data || !private_data_len) return NULL; - data = kmalloc(private_data_len, GFP_KERNEL); + data = kmemdup(private_data, private_data_len, GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); - memcpy(data, private_data, private_data_len); return data; } diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index c3fb304a4e86..2bbcfa5c6e27 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -140,10 +140,9 @@ static int copy_private_data(struct iwcm_id_private *cm_id_priv, { void *p; - p = kmalloc(event->private_data_len, GFP_ATOMIC); + p = kmemdup(event->private_data, event->private_data_len, GFP_ATOMIC); if (!p) return -ENOMEM; - memcpy(p, event->private_data, event->private_data_len); event->private_data = p; return 0; } diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index ad4f4d5c2924..b4894ba223b7 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -328,20 +328,18 @@ static int ib_ucm_event_process(struct ib_cm_event *evt, } if (uvt->data_len) { - uvt->data = kmalloc(uvt->data_len, GFP_KERNEL); + uvt->data = kmemdup(evt->private_data, uvt->data_len, GFP_KERNEL); if (!uvt->data) goto err1; - memcpy(uvt->data, evt->private_data, uvt->data_len); uvt->resp.present |= IB_UCM_PRES_DATA; } if (uvt->info_len) { - uvt->info = kmalloc(uvt->info_len, GFP_KERNEL); + uvt->info = kmemdup(info, uvt->info_len, GFP_KERNEL); if (!uvt->info) goto err2; - memcpy(uvt->info, info, uvt->info_len); uvt->resp.present |= IB_UCM_PRES_INFO; } return 0; diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index fc67f780581b..21422a3336ad 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -1100,11 +1100,10 @@ static struct ib_fmr *mthca_alloc_fmr(struct ib_pd *pd, int mr_access_flags, struct mthca_fmr *fmr; int err; - fmr = kmalloc(sizeof *fmr, GFP_KERNEL); + fmr = kmemdup(fmr_attr, sizeof *fmr, GFP_KERNEL); if (!fmr) return ERR_PTR(-ENOMEM); - memcpy(&fmr->attr, fmr_attr, sizeof *fmr_attr); err = mthca_fmr_alloc(to_mdev(pd->device), to_mpd(pd)->pd_num, convert_access(mr_access_flags), fmr); -- cgit v1.2.3 From e31353eaeca736981ec13b46089d30147342b28b Mon Sep 17 00:00:00 2001 From: Dotan Barak Date: Tue, 24 Oct 2006 13:35:27 -0700 Subject: RDMA/cm: Remove setting local write as part of QP access flags The qp_access_flags are for remote access permissions only, so IB_ACCESS_LOCAL_WRITE is an invalid value. Remove it from the values set by cm_init_qp_init_attr() and cma_init_ib_qp(). Signed-off-by: Dotan Barak Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 3 +-- drivers/infiniband/core/cma.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 82bc83baceaf..78d9c0c33148 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3172,8 +3172,7 @@ static int cm_init_qp_init_attr(struct cm_id_private *cm_id_priv, case IB_CM_ESTABLISHED: *qp_attr_mask = IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX | IB_QP_PORT; - qp_attr->qp_access_flags = IB_ACCESS_LOCAL_WRITE | - IB_ACCESS_REMOTE_WRITE; + qp_attr->qp_access_flags = IB_ACCESS_REMOTE_WRITE; if (cm_id_priv->responder_resources) qp_attr->qp_access_flags |= IB_ACCESS_REMOTE_READ | IB_ACCESS_REMOTE_ATOMIC; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index b449e26b84d2..cf48f2697434 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -344,7 +344,7 @@ static int cma_init_ib_qp(struct rdma_id_private *id_priv, struct ib_qp *qp) return ret; qp_attr.qp_state = IB_QPS_INIT; - qp_attr.qp_access_flags = IB_ACCESS_LOCAL_WRITE; + qp_attr.qp_access_flags = 0; qp_attr.port_num = id_priv->id.port_num; return ib_modify_qp(qp, &qp_attr, IB_QP_STATE | IB_QP_ACCESS_FLAGS | IB_QP_PKEY_INDEX | IB_QP_PORT); -- cgit v1.2.3 From 3c8edf0eca2e47340c960b2f27c659c097118ffe Mon Sep 17 00:00:00 2001 From: Arne Redlich Date: Wed, 15 Nov 2006 12:43:00 +0100 Subject: IB/srp: Increase supported CDB size Set the Scsi_Host's max_cmd_len from 12 (default) to 16 for SRP. Otherwise scsi_dispatch_cmd() won't pass down certain commands such as READ CAPACITY 16, required for supporting disks > 2TB. Signed-off-by: Arne Redlich Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 4b09147f438f..613be2ef9c52 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1716,7 +1716,8 @@ static ssize_t srp_create_target(struct class_device *class_dev, if (!target_host) return -ENOMEM; - target_host->max_lun = SRP_MAX_LUN; + target_host->max_lun = SRP_MAX_LUN; + target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; target = host_to_target(target_host); -- cgit v1.2.3 From f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Nov 2006 15:33:06 -0800 Subject: IB/mthca: Fix section mismatches Commit b3b30f5e ("IB/mthca: Recover from catastrophic errors") introduced some section mismatch breakage, because the error recovery code tears down and reinitializes the device, which calls into lots of code originally marked __devinit and __devexit from regular .text. Fix this by getting rid of these now-incorrect section markers. Reported by Randy Dunlap . Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_av.c | 3 +-- drivers/infiniband/hw/mthca/mthca_cq.c | 3 +-- drivers/infiniband/hw/mthca/mthca_eq.c | 21 ++++++++++----------- drivers/infiniband/hw/mthca/mthca_mad.c | 2 +- drivers/infiniband/hw/mthca/mthca_main.c | 29 ++++++++++++++--------------- drivers/infiniband/hw/mthca/mthca_mcg.c | 3 +-- drivers/infiniband/hw/mthca/mthca_mr.c | 5 ++--- drivers/infiniband/hw/mthca/mthca_pd.c | 3 +-- drivers/infiniband/hw/mthca/mthca_qp.c | 3 +-- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 10 files changed, 33 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 69599455aca2..57cdc1bc5f50 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -33,7 +33,6 @@ * $Id: mthca_av.c 1349 2004-12-16 21:09:43Z roland $ */ -#include #include #include @@ -323,7 +322,7 @@ int mthca_ah_query(struct ib_ah *ibah, struct ib_ah_attr *attr) return 0; } -int __devinit mthca_init_av_table(struct mthca_dev *dev) +int mthca_init_av_table(struct mthca_dev *dev) { int err; diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c index 149b36901239..283d50b76c3d 100644 --- a/drivers/infiniband/hw/mthca/mthca_cq.c +++ b/drivers/infiniband/hw/mthca/mthca_cq.c @@ -36,7 +36,6 @@ * $Id: mthca_cq.c 1369 2004-12-20 16:17:07Z roland $ */ -#include #include #include @@ -970,7 +969,7 @@ void mthca_free_cq(struct mthca_dev *dev, mthca_free_mailbox(dev, mailbox); } -int __devinit mthca_init_cq_table(struct mthca_dev *dev) +int mthca_init_cq_table(struct mthca_dev *dev) { int err; diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index e284e0613a94..8ec9fa1ff9ea 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -33,7 +33,6 @@ * $Id: mthca_eq.c 1382 2004-12-24 02:21:02Z roland $ */ -#include #include #include #include @@ -479,10 +478,10 @@ static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr) return IRQ_HANDLED; } -static int __devinit mthca_create_eq(struct mthca_dev *dev, - int nent, - u8 intr, - struct mthca_eq *eq) +static int mthca_create_eq(struct mthca_dev *dev, + int nent, + u8 intr, + struct mthca_eq *eq) { int npages; u64 *dma_list = NULL; @@ -664,9 +663,9 @@ static void mthca_free_irqs(struct mthca_dev *dev) dev->eq_table.eq + i); } -static int __devinit mthca_map_reg(struct mthca_dev *dev, - unsigned long offset, unsigned long size, - void __iomem **map) +static int mthca_map_reg(struct mthca_dev *dev, + unsigned long offset, unsigned long size, + void __iomem **map) { unsigned long base = pci_resource_start(dev->pdev, 0); @@ -691,7 +690,7 @@ static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset, iounmap(map); } -static int __devinit mthca_map_eq_regs(struct mthca_dev *dev) +static int mthca_map_eq_regs(struct mthca_dev *dev) { if (mthca_is_memfree(dev)) { /* @@ -781,7 +780,7 @@ static void mthca_unmap_eq_regs(struct mthca_dev *dev) } } -int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) +int mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt) { int ret; u8 status; @@ -825,7 +824,7 @@ void mthca_unmap_eq_icm(struct mthca_dev *dev) __free_page(dev->eq_table.icm_page); } -int __devinit mthca_init_eq_table(struct mthca_dev *dev) +int mthca_init_eq_table(struct mthca_dev *dev) { int err; u8 status; diff --git a/drivers/infiniband/hw/mthca/mthca_mad.c b/drivers/infiniband/hw/mthca/mthca_mad.c index 45e106f14807..acfa41d968ee 100644 --- a/drivers/infiniband/hw/mthca/mthca_mad.c +++ b/drivers/infiniband/hw/mthca/mthca_mad.c @@ -317,7 +317,7 @@ err: return ret; } -void __devexit mthca_free_agents(struct mthca_dev *dev) +void mthca_free_agents(struct mthca_dev *dev) { struct ib_mad_agent *agent; int p, q; diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 47ea02148368..0491ec7a7c0a 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -98,7 +98,7 @@ static struct mthca_profile default_profile = { .uarc_size = 1 << 18, /* Arbel only */ }; -static int __devinit mthca_tune_pci(struct mthca_dev *mdev) +static int mthca_tune_pci(struct mthca_dev *mdev) { int cap; u16 val; @@ -143,7 +143,7 @@ static int __devinit mthca_tune_pci(struct mthca_dev *mdev) return 0; } -static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim) +static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim) { int err; u8 status; @@ -255,7 +255,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim return 0; } -static int __devinit mthca_init_tavor(struct mthca_dev *mdev) +static int mthca_init_tavor(struct mthca_dev *mdev) { u8 status; int err; @@ -333,7 +333,7 @@ err_disable: return err; } -static int __devinit mthca_load_fw(struct mthca_dev *mdev) +static int mthca_load_fw(struct mthca_dev *mdev) { u8 status; int err; @@ -379,10 +379,10 @@ err_free: return err; } -static int __devinit mthca_init_icm(struct mthca_dev *mdev, - struct mthca_dev_lim *dev_lim, - struct mthca_init_hca_param *init_hca, - u64 icm_size) +static int mthca_init_icm(struct mthca_dev *mdev, + struct mthca_dev_lim *dev_lim, + struct mthca_init_hca_param *init_hca, + u64 icm_size) { u64 aux_pages; u8 status; @@ -575,7 +575,7 @@ static void mthca_free_icms(struct mthca_dev *mdev) mthca_free_icm(mdev, mdev->fw.arbel.aux_icm); } -static int __devinit mthca_init_arbel(struct mthca_dev *mdev) +static int mthca_init_arbel(struct mthca_dev *mdev) { struct mthca_dev_lim dev_lim; struct mthca_profile profile; @@ -683,7 +683,7 @@ static void mthca_close_hca(struct mthca_dev *mdev) mthca_SYS_DIS(mdev, &status); } -static int __devinit mthca_init_hca(struct mthca_dev *mdev) +static int mthca_init_hca(struct mthca_dev *mdev) { u8 status; int err; @@ -720,7 +720,7 @@ err_close: return err; } -static int __devinit mthca_setup_hca(struct mthca_dev *dev) +static int mthca_setup_hca(struct mthca_dev *dev) { int err; u8 status; @@ -875,8 +875,7 @@ err_uar_table_free: return err; } -static int __devinit mthca_request_regions(struct pci_dev *pdev, - int ddr_hidden) +static int mthca_request_regions(struct pci_dev *pdev, int ddr_hidden) { int err; @@ -928,7 +927,7 @@ static void mthca_release_regions(struct pci_dev *pdev, MTHCA_HCR_SIZE); } -static int __devinit mthca_enable_msi_x(struct mthca_dev *mdev) +static int mthca_enable_msi_x(struct mthca_dev *mdev) { struct msix_entry entries[3]; int err; @@ -1213,7 +1212,7 @@ int __mthca_restart_one(struct pci_dev *pdev) } static int __devinit mthca_init_one(struct pci_dev *pdev, - const struct pci_device_id *id) + const struct pci_device_id *id) { static int mthca_version_printed = 0; int ret; diff --git a/drivers/infiniband/hw/mthca/mthca_mcg.c b/drivers/infiniband/hw/mthca/mthca_mcg.c index 47ca8a9b7247..a8ad072be074 100644 --- a/drivers/infiniband/hw/mthca/mthca_mcg.c +++ b/drivers/infiniband/hw/mthca/mthca_mcg.c @@ -32,7 +32,6 @@ * $Id: mthca_mcg.c 1349 2004-12-16 21:09:43Z roland $ */ -#include #include #include @@ -371,7 +370,7 @@ int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) return err; } -int __devinit mthca_init_mcg_table(struct mthca_dev *dev) +int mthca_init_mcg_table(struct mthca_dev *dev) { int err; int table_size = dev->limits.num_mgms + dev->limits.num_amgms; diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c index a486dec1707e..f71ffa88db3a 100644 --- a/drivers/infiniband/hw/mthca/mthca_mr.c +++ b/drivers/infiniband/hw/mthca/mthca_mr.c @@ -34,7 +34,6 @@ */ #include -#include #include #include "mthca_dev.h" @@ -135,7 +134,7 @@ static void mthca_buddy_free(struct mthca_buddy *buddy, u32 seg, int order) spin_unlock(&buddy->lock); } -static int __devinit mthca_buddy_init(struct mthca_buddy *buddy, int max_order) +static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order) { int i, s; @@ -759,7 +758,7 @@ void mthca_arbel_fmr_unmap(struct mthca_dev *dev, struct mthca_fmr *fmr) *(u8 *) fmr->mem.arbel.mpt = MTHCA_MPT_STATUS_SW; } -int __devinit mthca_init_mr_table(struct mthca_dev *dev) +int mthca_init_mr_table(struct mthca_dev *dev) { unsigned long addr; int err, i; diff --git a/drivers/infiniband/hw/mthca/mthca_pd.c b/drivers/infiniband/hw/mthca/mthca_pd.c index 59df51614c85..c1e950764bd8 100644 --- a/drivers/infiniband/hw/mthca/mthca_pd.c +++ b/drivers/infiniband/hw/mthca/mthca_pd.c @@ -34,7 +34,6 @@ * $Id: mthca_pd.c 1349 2004-12-16 21:09:43Z roland $ */ -#include #include #include "mthca_dev.h" @@ -69,7 +68,7 @@ void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd) mthca_free(&dev->pd_table.alloc, pd->pd_num); } -int __devinit mthca_init_pd_table(struct mthca_dev *dev) +int mthca_init_pd_table(struct mthca_dev *dev) { return mthca_alloc_init(&dev->pd_table.alloc, dev->limits.num_pds, diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 6a7822e0fc19..33e3ba7937f1 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c @@ -35,7 +35,6 @@ * $Id: mthca_qp.c 1355 2004-12-17 15:23:43Z roland $ */ -#include #include #include @@ -2241,7 +2240,7 @@ void mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send, *new_wqe = 0; } -int __devinit mthca_init_qp_table(struct mthca_dev *dev) +int mthca_init_qp_table(struct mthca_dev *dev) { int err; u8 status; diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index f5d7677d1079..58fcf5a691e4 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -715,7 +715,7 @@ int mthca_max_srq_sge(struct mthca_dev *dev) sizeof (struct mthca_data_seg)); } -int __devinit mthca_init_srq_table(struct mthca_dev *dev) +int mthca_init_srq_table(struct mthca_dev *dev) { int err; -- cgit v1.2.3 From 29666128a22ddc78b3e393674ef69462835db43f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Nov 2006 15:33:07 -0800 Subject: RDMA/amso1100: Fix section mismatches The amso1100 driver was missing a couple of __devinit/__devexit annotations for init/cleanup functions that are called from __devinit/__devexit functions. Reported by Randy Dunlap . Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_rnic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_rnic.c b/drivers/infiniband/hw/amso1100/c2_rnic.c index 623dc95f91df..1687c511cb2f 100644 --- a/drivers/infiniband/hw/amso1100/c2_rnic.c +++ b/drivers/infiniband/hw/amso1100/c2_rnic.c @@ -441,7 +441,7 @@ static int c2_rnic_close(struct c2_dev *c2dev) * involves initalizing the various limits and resouce pools that * comprise the RNIC instance. */ -int c2_rnic_init(struct c2_dev *c2dev) +int __devinit c2_rnic_init(struct c2_dev *c2dev) { int err; u32 qsize, msgsize; @@ -611,7 +611,7 @@ int c2_rnic_init(struct c2_dev *c2dev) /* * Called by c2_remove to cleanup the RNIC resources. */ -void c2_rnic_term(struct c2_dev *c2dev) +void __devexit c2_rnic_term(struct c2_dev *c2dev) { /* Close the open adapter instance */ -- cgit v1.2.3 From 53533e16b1d94ff71cb013497938976906d9d504 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Nov 2006 15:33:07 -0800 Subject: IB/ipath: Fix typo in pma_counter_select subscript The array has only 5 entries, so [5] should have been [4]. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index a5456108dbad..acdee33ee1f8 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -1487,7 +1487,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd) idev->pma_counter_select[1] = IB_PMA_PORT_RCV_DATA; idev->pma_counter_select[2] = IB_PMA_PORT_XMIT_PKTS; idev->pma_counter_select[3] = IB_PMA_PORT_RCV_PKTS; - idev->pma_counter_select[5] = IB_PMA_PORT_XMIT_WAIT; + idev->pma_counter_select[4] = IB_PMA_PORT_XMIT_WAIT; idev->link_width_enabled = 3; /* 1x or 4x */ /* Snapshot current HW counters to "clear" them. */ -- cgit v1.2.3 From e54f81889cd5228e7087637c377d76301c7c5663 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Nov 2006 15:33:07 -0800 Subject: IB: Convert kmem_cache_t -> struct kmem_cache Signed-off-by: Roland Dreier --- drivers/infiniband/core/mad.c | 2 +- drivers/infiniband/hw/amso1100/c2.h | 2 +- drivers/infiniband/ulp/iser/iscsi_iser.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index a72bcea46ff6..3f9c16232c4d 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -46,7 +46,7 @@ MODULE_DESCRIPTION("kernel IB MAD API"); MODULE_AUTHOR("Hal Rosenstock"); MODULE_AUTHOR("Sean Hefty"); -static kmem_cache_t *ib_mad_cache; +static struct kmem_cache *ib_mad_cache; static struct list_head ib_mad_port_list; static u32 ib_mad_client_id = 0; diff --git a/drivers/infiniband/hw/amso1100/c2.h b/drivers/infiniband/hw/amso1100/c2.h index 1b17dcdd0505..04a9db5de881 100644 --- a/drivers/infiniband/hw/amso1100/c2.h +++ b/drivers/infiniband/hw/amso1100/c2.h @@ -302,7 +302,7 @@ struct c2_dev { unsigned long pa; /* PA device memory */ void **qptr_array; - kmem_cache_t *host_msg_cache; + struct kmem_cache *host_msg_cache; struct list_head cca_link; /* adapter list */ struct list_head eh_wakeup_list; /* event wakeup list */ diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index 9c53916f28c2..234e5b061a75 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -283,7 +283,7 @@ struct iser_global { struct mutex connlist_mutex; struct list_head connlist; /* all iSER IB connections */ - kmem_cache_t *desc_cache; + struct kmem_cache *desc_cache; }; extern struct iser_global ig; -- cgit v1.2.3 From 33ba0fa9f315ce32fbb86fa671c131f5355b52a1 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 9 Nov 2006 09:30:34 +0530 Subject: RDMA/iwcm: Fix memory corruption bug in cm_work_handler() Possible memory corruption scenario: after putting the work entry back on the work_free_list, we call process_event() which dereferences work->event, which could have been modified to another value meanwhile. Signed-off-by: Krishna Kumar Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 2bbcfa5c6e27..22d498c9a68b 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -829,7 +829,8 @@ static int process_event(struct iwcm_id_private *cm_id_priv, */ static void cm_work_handler(void *arg) { - struct iwcm_work *work = arg, lwork; + struct iwcm_work *work = arg; + struct iw_cm_event levent; struct iwcm_id_private *cm_id_priv = work->cm_id; unsigned long flags; int empty; @@ -842,11 +843,11 @@ static void cm_work_handler(void *arg) struct iwcm_work, list); list_del_init(&work->list); empty = list_empty(&cm_id_priv->work_list); - lwork = *work; + levent = work->event; put_work(work); spin_unlock_irqrestore(&cm_id_priv->lock, flags); - ret = process_event(cm_id_priv, &work->event); + ret = process_event(cm_id_priv, &levent); if (ret) { set_bit(IWCM_F_CALLBACK_DESTROY, &cm_id_priv->flags); destroy_cm_id(&cm_id_priv->id); -- cgit v1.2.3 From 83b96586239bf6c719ff640341e1cf83e4a7c046 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 9 Nov 2006 09:30:41 +0530 Subject: RDMA/iwcm: Fix memory leak If we get IW_CM_EVENT_CONNECT_REQUEST message and encounter an error (not in the LISTEN state, cannot create an id, cannot alloc work_entry, etc), then the memory allocated by cm_event_handler() in the event->private_data gets leaked. Since cm_work_handler has already put the event on the work_free_list, this allocated memory is leaked. High backlog value can allow DoS attacks. Signed-off-by: Krishna Kumar Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 22d498c9a68b..0cfd7848dd37 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -619,7 +619,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv, spin_lock_irqsave(&listen_id_priv->lock, flags); if (listen_id_priv->state != IW_CM_STATE_LISTEN) { spin_unlock_irqrestore(&listen_id_priv->lock, flags); - return; + goto out; } spin_unlock_irqrestore(&listen_id_priv->lock, flags); @@ -628,7 +628,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv, listen_id_priv->id.context); /* If the cm_id could not be created, ignore the request */ if (IS_ERR(cm_id)) - return; + goto out; cm_id->provider_data = iw_event->provider_data; cm_id->local_addr = iw_event->local_addr; @@ -641,7 +641,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv, if (ret) { iw_cm_reject(cm_id, NULL, 0); iw_destroy_cm_id(cm_id); - return; + goto out; } /* Call the client CM handler */ @@ -653,6 +653,7 @@ static void cm_conn_req_handler(struct iwcm_id_private *listen_id_priv, kfree(cm_id); } +out: if (iw_event->private_data_len) kfree(iw_event->private_data); } -- cgit v1.2.3 From 13fccdb380f88770f05b922c273d907aecda7c12 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 9 Nov 2006 09:30:43 +0530 Subject: RDMA/iwcm: Remove unnecessary initializations Signed-off-by: Krishna Kumar Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 0cfd7848dd37..b02e54136acd 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -407,7 +407,7 @@ int iw_cm_listen(struct iw_cm_id *cm_id, int backlog) { struct iwcm_id_private *cm_id_priv; unsigned long flags; - int ret = 0; + int ret; cm_id_priv = container_of(cm_id, struct iwcm_id_private, id); @@ -534,7 +534,7 @@ EXPORT_SYMBOL(iw_cm_accept); int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param) { struct iwcm_id_private *cm_id_priv; - int ret = 0; + int ret; unsigned long flags; struct ib_qp *qp; @@ -674,7 +674,7 @@ static int cm_conn_est_handler(struct iwcm_id_private *cm_id_priv, struct iw_cm_event *iw_event) { unsigned long flags; - int ret = 0; + int ret; spin_lock_irqsave(&cm_id_priv->lock, flags); @@ -704,7 +704,7 @@ static int cm_conn_rep_handler(struct iwcm_id_private *cm_id_priv, struct iw_cm_event *iw_event) { unsigned long flags; - int ret = 0; + int ret; spin_lock_irqsave(&cm_id_priv->lock, flags); /* -- cgit v1.2.3 From 715a588f420936ecdb813c4fcd40dff7a16b1638 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 9 Nov 2006 09:30:45 +0530 Subject: RDMA/iwcm: Remove unnecessary function argument Remove unnecessary cm_id_priv argument to copy_private_data(), and change text to reflect the code. Fix couple of typos in comments. Signed-off-by: Krishna Kumar Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index b02e54136acd..54faa033d89e 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -80,7 +80,7 @@ struct iwcm_work { * 1) in the event upcall, cm_event_handler(), for a listening cm_id. If * the backlog is exceeded, then no more connection request events will * be processed. cm_event_handler() returns -ENOMEM in this case. Its up - * to the provider to reject the connectino request. + * to the provider to reject the connection request. * 2) in the connection request workqueue handler, cm_conn_req_handler(). * If work elements cannot be allocated for the new connect request cm_id, * then IWCM will call the provider reject method. This is ok since @@ -131,12 +131,11 @@ static int alloc_work_entries(struct iwcm_id_private *cm_id_priv, int count) } /* - * Save private data from incoming connection requests in the - * cm_id_priv so the low level driver doesn't have to. Adjust + * Save private data from incoming connection requests to + * iw_cm_event, so the low level driver doesn't have to. Adjust * the event ptr to point to the local copy. */ -static int copy_private_data(struct iwcm_id_private *cm_id_priv, - struct iw_cm_event *event) +static int copy_private_data(struct iw_cm_event *event) { void *p; @@ -242,7 +241,7 @@ static int iwcm_modify_qp_sqd(struct ib_qp *qp) /* * CM_ID <-- CLOSING * - * Block if a passive or active connection is currenlty being processed. Then + * Block if a passive or active connection is currently being processed. Then * process the event as follows: * - If we are ESTABLISHED, move to CLOSING and modify the QP state * based on the abrupt flag @@ -907,7 +906,7 @@ static int cm_event_handler(struct iw_cm_id *cm_id, if ((work->event.event == IW_CM_EVENT_CONNECT_REQUEST || work->event.event == IW_CM_EVENT_CONNECT_REPLY) && work->event.private_data_len) { - ret = copy_private_data(cm_id_priv, &work->event); + ret = copy_private_data(&work->event); if (ret) { put_work(work); goto out; -- cgit v1.2.3 From 9ab1ffa8775d9c677b1301cccce8a7d91e5163d0 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Thu, 9 Nov 2006 09:30:48 +0530 Subject: RDMA/iwcm: Fix comment for iwcm_deref_id() to match code In iwcm_deref_id(), the comment says : "If the last reference is being removed and iw_destroy_cm_id is waiting, wake up the waiting thread". The second part of the comment, "and iw_destroy_cm_id is waiting," is wrong, since this function either wakes the waiter already waiting in iwcm_deref_id, or enables it (so that when wait_for_completion() is performed later, it will immediately return). Signed-off-by: Krishna Kumar Acked-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/core/iwcm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 54faa033d89e..cf797d7aea09 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -147,8 +147,9 @@ static int copy_private_data(struct iw_cm_event *event) } /* - * Release a reference on cm_id. If the last reference is being removed - * and iw_destroy_cm_id is waiting, wake up the waiting thread. + * Release a reference on cm_id. If the last reference is being + * released, enable the waiting thread (in iw_destroy_cm_id) to + * get woken up, and return 1 if a thread is already waiting. */ static int iwcm_deref_id(struct iwcm_id_private *cm_id_priv) { -- cgit v1.2.3 From 2771e9ed4702e46c3f4c305eb2e047c251c2ad2b Mon Sep 17 00:00:00 2001 From: Hoang-Nam Nguyen Date: Mon, 20 Nov 2006 23:54:12 +0100 Subject: IB/ehca: Use WQE offset instead of WQE addr for pending work reqs This is a patch for ehca to fix a bug in prepare_sqe_to_rts(), which used WQE address to iterate pending work requests. This might cause an access violation since the queue pages can not be assumed to follow each other consecutively. Thus, this patch introduces a few queue functions to determine WQE offset based on its address and uses WQE offset to iterate the pending work requests. Signed-off-by: Hoang-Nam Nguyen Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ehca/ehca_main.c | 4 ++-- drivers/infiniband/hw/ehca/ehca_qp.c | 22 +++++++++------------- drivers/infiniband/hw/ehca/ipz_pt_fn.c | 13 +++++++++++++ drivers/infiniband/hw/ehca/ipz_pt_fn.h | 15 +++++++++++++++ 4 files changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c index 01f5aa9cb56d..3d1c1c535038 100644 --- a/drivers/infiniband/hw/ehca/ehca_main.c +++ b/drivers/infiniband/hw/ehca/ehca_main.c @@ -52,7 +52,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Christoph Raisch "); MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver"); -MODULE_VERSION("SVNEHCA_0018"); +MODULE_VERSION("SVNEHCA_0019"); int ehca_open_aqp1 = 0; int ehca_debug_level = 0; @@ -790,7 +790,7 @@ int __init ehca_module_init(void) int ret; printk(KERN_INFO "eHCA Infiniband Device Driver " - "(Rel.: SVNEHCA_0018)\n"); + "(Rel.: SVNEHCA_0019)\n"); idr_init(&ehca_qp_idr); idr_init(&ehca_cq_idr); spin_lock_init(&ehca_qp_idr_lock); diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c index cf3e50ee2d06..8682aa50c707 100644 --- a/drivers/infiniband/hw/ehca/ehca_qp.c +++ b/drivers/infiniband/hw/ehca/ehca_qp.c @@ -732,8 +732,7 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, u64 h_ret; struct ipz_queue *squeue; void *bad_send_wqe_p, *bad_send_wqe_v; - void *squeue_start_p, *squeue_end_p; - void *squeue_start_v, *squeue_end_v; + u64 q_ofs; struct ehca_wqe *wqe; int qp_num = my_qp->ib_qp.qp_num; @@ -755,26 +754,23 @@ static int prepare_sqe_rts(struct ehca_qp *my_qp, struct ehca_shca *shca, if (ehca_debug_level) ehca_dmp(bad_send_wqe_v, 32, "qp_num=%x bad_wqe", qp_num); squeue = &my_qp->ipz_squeue; - squeue_start_p = (void*)virt_to_abs(ipz_qeit_calc(squeue, 0L)); - squeue_end_p = squeue_start_p+squeue->queue_length; - squeue_start_v = abs_to_virt((u64)squeue_start_p); - squeue_end_v = abs_to_virt((u64)squeue_end_p); - ehca_dbg(&shca->ib_device, "qp_num=%x squeue_start_v=%p squeue_end_v=%p", - qp_num, squeue_start_v, squeue_end_v); + if (ipz_queue_abs_to_offset(squeue, (u64)bad_send_wqe_p, &q_ofs)) { + ehca_err(&shca->ib_device, "failed to get wqe offset qp_num=%x" + " bad_send_wqe_p=%p", qp_num, bad_send_wqe_p); + return -EFAULT; + } /* loop sets wqe's purge bit */ - wqe = (struct ehca_wqe*)bad_send_wqe_v; + wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs); *bad_wqe_cnt = 0; while (wqe->optype != 0xff && wqe->wqef != 0xff) { if (ehca_debug_level) ehca_dmp(wqe, 32, "qp_num=%x wqe", qp_num); wqe->nr_of_data_seg = 0; /* suppress data access */ wqe->wqef = WQEF_PURGE; /* WQE to be purged */ - wqe = (struct ehca_wqe*)((u8*)wqe+squeue->qe_size); + q_ofs = ipz_queue_advance_offset(squeue, q_ofs); + wqe = (struct ehca_wqe*)ipz_qeit_calc(squeue, q_ofs); *bad_wqe_cnt = (*bad_wqe_cnt)+1; - if ((void*)wqe >= squeue_end_v) { - wqe = squeue_start_v; - } } /* * bad wqe will be reprocessed and ignored when pol_cq() is called, diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.c b/drivers/infiniband/hw/ehca/ipz_pt_fn.c index e028ff1588cc..bf7a40088f61 100644 --- a/drivers/infiniband/hw/ehca/ipz_pt_fn.c +++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.c @@ -70,6 +70,19 @@ void *ipz_qeit_eq_get_inc(struct ipz_queue *queue) return ret; } +int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset) +{ + int i; + for (i = 0; i < queue->queue_length / queue->pagesize; i++) { + u64 page = (u64)virt_to_abs(queue->queue_pages[i]); + if (addr >= page && addr < page + queue->pagesize) { + *q_offset = addr - page + i * queue->pagesize; + return 0; + } + } + return -EINVAL; +} + int ipz_queue_ctor(struct ipz_queue *queue, const u32 nr_of_pages, const u32 pagesize, const u32 qe_size, const u32 nr_of_sg) diff --git a/drivers/infiniband/hw/ehca/ipz_pt_fn.h b/drivers/infiniband/hw/ehca/ipz_pt_fn.h index 2f13509d5257..dc3bda2634b7 100644 --- a/drivers/infiniband/hw/ehca/ipz_pt_fn.h +++ b/drivers/infiniband/hw/ehca/ipz_pt_fn.h @@ -150,6 +150,21 @@ static inline void *ipz_qeit_reset(struct ipz_queue *queue) return ipz_qeit_get(queue); } +/* + * return the q_offset corresponding to an absolute address + */ +int ipz_queue_abs_to_offset(struct ipz_queue *queue, u64 addr, u64 *q_offset); + +/* + * return the next queue offset. don't modify the queue. + */ +static inline u64 ipz_queue_advance_offset(struct ipz_queue *queue, u64 offset) +{ + offset += queue->qe_size; + if (offset >= queue->queue_length) offset = 0; + return offset; +} + /* struct generic page table */ struct ipz_pt { u64 entries[EHCA_PT_ENTRIES]; -- cgit v1.2.3 From 7013696a5f5ccd0d847d5e8b841d0b0b312277c8 Mon Sep 17 00:00:00 2001 From: Jack Morgenstein Date: Sun, 26 Nov 2006 09:10:19 +0200 Subject: IB/mthca: Fix initial SRQ logsize for mem-free HCAs When initializing an mthca SRQ, the log_srq_size field should be the log of the number of SRQ WQEs, not the log of the number of bytes in the SRQ. This affects only mthca drivers for memfree HCAs which set the initial srq wqe counter (in the SW2HW transition) to a non-zero value. Signed-off-by: Jack Morgenstein Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_srq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 58fcf5a691e4..34d2c4768962 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -120,7 +120,7 @@ static void mthca_arbel_init_srq_context(struct mthca_dev *dev, memset(context, 0, sizeof *context); - logsize = long_log2(srq->max) + srq->wqe_shift; + logsize = long_log2(srq->max); context->state_logsize_srqn = cpu_to_be32(logsize << 24 | srq->srqn); context->lkey = cpu_to_be32(srq->mr.ibmr.lkey); context->db_index = cpu_to_be32(srq->db_index); -- cgit v1.2.3 From c9edea298e52faeb0d4ae875cb712a5d69ba1966 Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Fri, 24 Nov 2006 16:03:48 +0530 Subject: RDMA/amso1100: Prevent deadlock in destroy QP It is possible to swap the CQs used for send_cq and recv_cq when creating two different QPs. If these two QPs are then destroyed at the same time, an AB-BA deadlock can occur because the CQ locks are taken our of order. Fix this by always taking CQ locks in a fixed order. Signed-off-by: Krishna Kumar Signed-off-by: Roland Dreier --- drivers/infiniband/hw/amso1100/c2_qp.c | 36 ++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/amso1100/c2_qp.c b/drivers/infiniband/hw/amso1100/c2_qp.c index 5bcf697aa335..179d005ed4a5 100644 --- a/drivers/infiniband/hw/amso1100/c2_qp.c +++ b/drivers/infiniband/hw/amso1100/c2_qp.c @@ -564,6 +564,32 @@ int c2_alloc_qp(struct c2_dev *c2dev, return err; } +static inline void c2_lock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq) +{ + if (send_cq == recv_cq) + spin_lock_irq(&send_cq->lock); + else if (send_cq > recv_cq) { + spin_lock_irq(&send_cq->lock); + spin_lock_nested(&recv_cq->lock, SINGLE_DEPTH_NESTING); + } else { + spin_lock_irq(&recv_cq->lock); + spin_lock_nested(&send_cq->lock, SINGLE_DEPTH_NESTING); + } +} + +static inline void c2_unlock_cqs(struct c2_cq *send_cq, struct c2_cq *recv_cq) +{ + if (send_cq == recv_cq) + spin_unlock_irq(&send_cq->lock); + else if (send_cq > recv_cq) { + spin_unlock(&recv_cq->lock); + spin_unlock_irq(&send_cq->lock); + } else { + spin_unlock(&send_cq->lock); + spin_unlock_irq(&recv_cq->lock); + } +} + void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp) { struct c2_cq *send_cq; @@ -576,15 +602,9 @@ void c2_free_qp(struct c2_dev *c2dev, struct c2_qp *qp) * Lock CQs here, so that CQ polling code can do QP lookup * without taking a lock. */ - spin_lock_irq(&send_cq->lock); - if (send_cq != recv_cq) - spin_lock(&recv_cq->lock); - + c2_lock_cqs(send_cq, recv_cq); c2_free_qpn(c2dev, qp->qpn); - - if (send_cq != recv_cq) - spin_unlock(&recv_cq->lock); - spin_unlock_irq(&send_cq->lock); + c2_unlock_cqs(send_cq, recv_cq); /* * Destory qp in the rnic... -- cgit v1.2.3 From c78bb8442b14ee6704bdb323111ffa874d4bfdaa Mon Sep 17 00:00:00 2001 From: Krishna Kumar Date: Fri, 24 Nov 2006 16:02:34 +0530 Subject: RDMA/addr: Fix some cancellation problems in process_req() Fix following problems in process_req() relating to cancellation: - Function is wrongly doing another addr_remote() when cancelled, which is not required. - Make failure reporting immediate by using time_after_eq(). - On cancellation, -ETIMEDOUT was returned to the callback routine instead of the more appropriate -ECANCELLED (users getting notified may want to print/return this status, eg ucma_event_handler). Signed-off-by: Krishna Kumar Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index a68d7c7df4ca..15ba51806ffd 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -225,17 +225,16 @@ static void process_req(void *data) mutex_lock(&lock); list_for_each_entry_safe(req, temp_req, &req_list, list) { - if (req->status) { + if (req->status == -ENODATA) { src_in = (struct sockaddr_in *) &req->src_addr; dst_in = (struct sockaddr_in *) &req->dst_addr; req->status = addr_resolve_remote(src_in, dst_in, req->addr); + if (req->status && time_after_eq(jiffies, req->timeout)) + req->status = -ETIMEDOUT; + else if (req->status == -ENODATA) + continue; } - if (req->status && time_after(jiffies, req->timeout)) - req->status = -ETIMEDOUT; - else if (req->status == -ENODATA) - continue; - list_del(&req->list); list_add_tail(&req->list, &done_list); } -- cgit v1.2.3 From 04699a1f8634a4e89c71b22050b599c72126fa96 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Wed, 29 Nov 2006 15:33:09 -0800 Subject: RDMA/addr: list_move() cleanups Replace a couple list_del()/list_add() combos with list_move(). Signed-off-by: Roland Dreier --- drivers/infiniband/core/addr.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 15ba51806ffd..7767a11b6890 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -235,8 +235,7 @@ static void process_req(void *data) else if (req->status == -ENODATA) continue; } - list_del(&req->list); - list_add_tail(&req->list, &done_list); + list_move_tail(&req->list, &done_list); } if (!list_empty(&req_list)) { @@ -346,8 +345,7 @@ void rdma_addr_cancel(struct rdma_dev_addr *addr) if (req->addr == addr) { req->status = -ECANCELED; req->timeout = jiffies; - list_del(&req->list); - list_add(&req->list, &req_list); + list_move(&req->list, &req_list); set_timeout(req->timeout); break; } -- cgit v1.2.3 From d2fcea7d68473b8bb3e0addb4926c87e2217ca83 Mon Sep 17 00:00:00 2001 From: Vu Pham Date: Tue, 21 Nov 2006 14:14:10 -0800 Subject: IB/srp: Fix memory leak on reconnect SRP reallocates the IU buffers for tx_ring and rx_ring without freeing the old buffers when it reconnects to a target. Fix this by keeping the old IU buffers around. Signed-off-by: Vu Pham Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/srp/ib_srp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 613be2ef9c52..64ab5fc7cca3 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1176,9 +1176,11 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event) break; } - target->status = srp_alloc_iu_bufs(target); - if (target->status) - break; + if (!target->rx_ring[0]) { + target->status = srp_alloc_iu_bufs(target); + if (target->status) + break; + } qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL); if (!qp_attr) { -- cgit v1.2.3 From 2745b5b713bf3457d8977c62dc2b3aa61f4a14b0 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 16 Nov 2006 14:16:47 +0200 Subject: IPoIB: Fix skb leak when freeing neighbour ipoib_neigh_free() is sometimes called while neighbour is still alive, so it might still have queued skbs. Fix skb leak in this case. Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib.h | 2 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 19 +++++++++++++------ drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 0b8a79d53a00..f2b61851a49c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -233,7 +233,7 @@ static inline struct ipoib_neigh **to_ipoib_neigh(struct neighbour *neigh) } struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neigh); -void ipoib_neigh_free(struct ipoib_neigh *neigh); +void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh); extern struct workqueue_struct *ipoib_workqueue; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 85522daeb946..5ba3154320b4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -264,7 +264,7 @@ static void path_free(struct net_device *dev, struct ipoib_path *path) if (neigh->ah) ipoib_put_ah(neigh->ah); - ipoib_neigh_free(neigh); + ipoib_neigh_free(dev, neigh); } spin_unlock_irqrestore(&priv->lock, flags); @@ -525,10 +525,11 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev) ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb->dst->neighbour->ha)); } else { neigh->ah = NULL; - __skb_queue_tail(&neigh->queue, skb); if (!path->query && path_rec_start(dev, path)) goto err_list; + + __skb_queue_tail(&neigh->queue, skb); } spin_unlock(&priv->lock); @@ -538,7 +539,7 @@ err_list: list_del(&neigh->list); err_path: - ipoib_neigh_free(neigh); + ipoib_neigh_free(dev, neigh); ++priv->stats.tx_dropped; dev_kfree_skb_any(skb); @@ -655,7 +656,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) */ ipoib_put_ah(neigh->ah); list_del(&neigh->list); - ipoib_neigh_free(neigh); + ipoib_neigh_free(dev, neigh); spin_unlock(&priv->lock); ipoib_path_lookup(skb, dev); goto out; @@ -786,7 +787,7 @@ static void ipoib_neigh_destructor(struct neighbour *n) if (neigh->ah) ah = neigh->ah; list_del(&neigh->list); - ipoib_neigh_free(neigh); + ipoib_neigh_free(n->dev, neigh); } spin_unlock_irqrestore(&priv->lock, flags); @@ -809,9 +810,15 @@ struct ipoib_neigh *ipoib_neigh_alloc(struct neighbour *neighbour) return neigh; } -void ipoib_neigh_free(struct ipoib_neigh *neigh) +void ipoib_neigh_free(struct net_device *dev, struct ipoib_neigh *neigh) { + struct ipoib_dev_priv *priv = netdev_priv(dev); + struct sk_buff *skb; *to_ipoib_neigh(neigh->neighbour) = NULL; + while ((skb = __skb_dequeue(&neigh->queue))) { + ++priv->stats.tx_dropped; + dev_kfree_skb_any(skb); + } kfree(neigh); } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 3faa1820f0e9..d282d65e3ee0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -114,7 +114,7 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) */ if (neigh->ah) ipoib_put_ah(neigh->ah); - ipoib_neigh_free(neigh); + ipoib_neigh_free(dev, neigh); } spin_unlock_irqrestore(&priv->lock, flags); -- cgit v1.2.3 From e1444b5a163e81138754cab27c4fa1637b5a2239 Mon Sep 17 00:00:00 2001 From: Sean Hefty Date: Tue, 28 Nov 2006 14:57:13 -0800 Subject: IB/cm: Fix automatic path migration support The ib_cm_establish() function is replaced with a more generic ib_cm_notify(). This routine is used to notify the CM that failover has occurred, so that future CM messages (LAP, DREQ) reach the remote CM. (Currently, we continue to use the original path) This bumps the userspace CM ABI. New alternate path information is captured when a LAP message is sent or received. This allows QP attributes to be initialized for the user when a new path is loaded after failover occurs. Signed-off-by: Sean Hefty Signed-off-by: Roland Dreier --- drivers/infiniband/core/cm.c | 115 ++++++++++++++++++++++++++++++++---------- drivers/infiniband/core/ucm.c | 12 ++--- include/rdma/ib_cm.h | 16 ++++-- include/rdma/ib_user_cm.h | 7 +-- 4 files changed, 110 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 78d9c0c33148..e5dc4530808a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -147,12 +147,12 @@ struct cm_id_private { __be32 rq_psn; int timeout_ms; enum ib_mtu path_mtu; + __be16 pkey; u8 private_data_len; u8 max_cm_retries; u8 peer_to_peer; u8 responder_resources; u8 initiator_depth; - u8 local_ack_timeout; u8 retry_count; u8 rnr_retry_count; u8 service_timeout; @@ -690,7 +690,7 @@ static void cm_enter_timewait(struct cm_id_private *cm_id_priv) * timewait before notifying the user that we've exited timewait. */ cm_id_priv->id.state = IB_CM_TIMEWAIT; - wait_time = cm_convert_to_ms(cm_id_priv->local_ack_timeout); + wait_time = cm_convert_to_ms(cm_id_priv->av.packet_life_time + 1); queue_delayed_work(cm.wq, &cm_id_priv->timewait_info->work.work, msecs_to_jiffies(wait_time)); cm_id_priv->timewait_info = NULL; @@ -1009,6 +1009,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, cm_id_priv->responder_resources = param->responder_resources; cm_id_priv->retry_count = param->retry_count; cm_id_priv->path_mtu = param->primary_path->mtu; + cm_id_priv->pkey = param->primary_path->pkey; cm_id_priv->qp_type = param->qp_type; ret = cm_alloc_msg(cm_id_priv, &cm_id_priv->msg); @@ -1023,8 +1024,6 @@ int ib_send_cm_req(struct ib_cm_id *cm_id, cm_id_priv->local_qpn = cm_req_get_local_qpn(req_msg); cm_id_priv->rq_psn = cm_req_get_starting_psn(req_msg); - cm_id_priv->local_ack_timeout = - cm_req_get_primary_local_ack_timeout(req_msg); spin_lock_irqsave(&cm_id_priv->lock, flags); ret = ib_post_send_mad(cm_id_priv->msg, NULL); @@ -1409,9 +1408,8 @@ static int cm_req_handler(struct cm_work *work) cm_id_priv->initiator_depth = cm_req_get_resp_res(req_msg); cm_id_priv->responder_resources = cm_req_get_init_depth(req_msg); cm_id_priv->path_mtu = cm_req_get_path_mtu(req_msg); + cm_id_priv->pkey = req_msg->pkey; cm_id_priv->sq_psn = cm_req_get_starting_psn(req_msg); - cm_id_priv->local_ack_timeout = - cm_req_get_primary_local_ack_timeout(req_msg); cm_id_priv->retry_count = cm_req_get_retry_count(req_msg); cm_id_priv->rnr_retry_count = cm_req_get_rnr_retry_count(req_msg); cm_id_priv->qp_type = cm_req_get_qp_type(req_msg); @@ -1715,7 +1713,7 @@ static int cm_establish_handler(struct cm_work *work) unsigned long flags; int ret; - /* See comment in ib_cm_establish about lookup. */ + /* See comment in cm_establish about lookup. */ cm_id_priv = cm_acquire_id(work->local_id, work->remote_id); if (!cm_id_priv) return -EINVAL; @@ -2401,11 +2399,16 @@ int ib_send_cm_lap(struct ib_cm_id *cm_id, cm_id_priv = container_of(cm_id, struct cm_id_private, id); spin_lock_irqsave(&cm_id_priv->lock, flags); if (cm_id->state != IB_CM_ESTABLISHED || - cm_id->lap_state != IB_CM_LAP_IDLE) { + (cm_id->lap_state != IB_CM_LAP_UNINIT && + cm_id->lap_state != IB_CM_LAP_IDLE)) { ret = -EINVAL; goto out; } + ret = cm_init_av_by_path(alternate_path, &cm_id_priv->alt_av); + if (ret) + goto out; + ret = cm_alloc_msg(cm_id_priv, &msg); if (ret) goto out; @@ -2430,7 +2433,8 @@ out: spin_unlock_irqrestore(&cm_id_priv->lock, flags); } EXPORT_SYMBOL(ib_send_cm_lap); -static void cm_format_path_from_lap(struct ib_sa_path_rec *path, +static void cm_format_path_from_lap(struct cm_id_private *cm_id_priv, + struct ib_sa_path_rec *path, struct cm_lap_msg *lap_msg) { memset(path, 0, sizeof *path); @@ -2442,10 +2446,10 @@ static void cm_format_path_from_lap(struct ib_sa_path_rec *path, path->hop_limit = lap_msg->alt_hop_limit; path->traffic_class = cm_lap_get_traffic_class(lap_msg); path->reversible = 1; - /* pkey is same as in REQ */ + path->pkey = cm_id_priv->pkey; path->sl = cm_lap_get_sl(lap_msg); path->mtu_selector = IB_SA_EQ; - /* mtu is same as in REQ */ + path->mtu = cm_id_priv->path_mtu; path->rate_selector = IB_SA_EQ; path->rate = cm_lap_get_packet_rate(lap_msg); path->packet_life_time_selector = IB_SA_EQ; @@ -2471,7 +2475,7 @@ static int cm_lap_handler(struct cm_work *work) param = &work->cm_event.param.lap_rcvd; param->alternate_path = &work->path[0]; - cm_format_path_from_lap(param->alternate_path, lap_msg); + cm_format_path_from_lap(cm_id_priv, param->alternate_path, lap_msg); work->cm_event.private_data = &lap_msg->private_data; spin_lock_irqsave(&cm_id_priv->lock, flags); @@ -2479,6 +2483,7 @@ static int cm_lap_handler(struct cm_work *work) goto unlock; switch (cm_id_priv->id.lap_state) { + case IB_CM_LAP_UNINIT: case IB_CM_LAP_IDLE: break; case IB_CM_MRA_LAP_SENT: @@ -2501,6 +2506,10 @@ static int cm_lap_handler(struct cm_work *work) cm_id_priv->id.lap_state = IB_CM_LAP_RCVD; cm_id_priv->tid = lap_msg->hdr.tid; + cm_init_av_for_response(work->port, work->mad_recv_wc->wc, + work->mad_recv_wc->recv_buf.grh, + &cm_id_priv->av); + cm_init_av_by_path(param->alternate_path, &cm_id_priv->alt_av); ret = atomic_inc_and_test(&cm_id_priv->work_count); if (!ret) list_add_tail(&work->list, &cm_id_priv->work_list); @@ -3039,7 +3048,7 @@ static void cm_work_handler(void *data) cm_free_work(work); } -int ib_cm_establish(struct ib_cm_id *cm_id) +static int cm_establish(struct ib_cm_id *cm_id) { struct cm_id_private *cm_id_priv; struct cm_work *work; @@ -3087,7 +3096,44 @@ int ib_cm_establish(struct ib_cm_id *cm_id) out: return ret; } -EXPORT_SYMBOL(ib_cm_establish); + +static int cm_migrate(struct ib_cm_id *cm_id) +{ + struct cm_id_private *cm_id_priv; + unsigned long flags; + int ret = 0; + + cm_id_priv = container_of(cm_id, struct cm_id_private, id); + spin_lock_irqsave(&cm_id_priv->lock, flags); + if (cm_id->state == IB_CM_ESTABLISHED && + (cm_id->lap_state == IB_CM_LAP_UNINIT || + cm_id->lap_state == IB_CM_LAP_IDLE)) { + cm_id->lap_state = IB_CM_LAP_IDLE; + cm_id_priv->av = cm_id_priv->alt_av; + } else + ret = -EINVAL; + spin_unlock_irqrestore(&cm_id_priv->lock, flags); + + return ret; +} + +int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event) +{ + int ret; + + switch (event) { + case IB_EVENT_COMM_EST: + ret = cm_establish(cm_id); + break; + case IB_EVENT_PATH_MIG: + ret = cm_migrate(cm_id); + break; + default: + ret = -EINVAL; + } + return ret; +} +EXPORT_SYMBOL(ib_cm_notify); static void cm_recv_handler(struct ib_mad_agent *mad_agent, struct ib_mad_recv_wc *mad_recv_wc) @@ -3220,6 +3266,9 @@ static int cm_init_qp_rtr_attr(struct cm_id_private *cm_id_priv, if (cm_id_priv->alt_av.ah_attr.dlid) { *qp_attr_mask |= IB_QP_ALT_PATH; qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; + qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; + qp_attr->alt_timeout = + cm_id_priv->alt_av.packet_life_time + 1; qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; } ret = 0; @@ -3246,19 +3295,31 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, case IB_CM_REP_SENT: case IB_CM_MRA_REP_RCVD: case IB_CM_ESTABLISHED: - *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN; - qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn); - if (cm_id_priv->qp_type == IB_QPT_RC) { - *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | - IB_QP_RNR_RETRY | - IB_QP_MAX_QP_RD_ATOMIC; - qp_attr->timeout = cm_id_priv->local_ack_timeout; - qp_attr->retry_cnt = cm_id_priv->retry_count; - qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; - qp_attr->max_rd_atomic = cm_id_priv->initiator_depth; - } - if (cm_id_priv->alt_av.ah_attr.dlid) { - *qp_attr_mask |= IB_QP_PATH_MIG_STATE; + if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT) { + *qp_attr_mask = IB_QP_STATE | IB_QP_SQ_PSN; + qp_attr->sq_psn = be32_to_cpu(cm_id_priv->sq_psn); + if (cm_id_priv->qp_type == IB_QPT_RC) { + *qp_attr_mask |= IB_QP_TIMEOUT | IB_QP_RETRY_CNT | + IB_QP_RNR_RETRY | + IB_QP_MAX_QP_RD_ATOMIC; + qp_attr->timeout = + cm_id_priv->av.packet_life_time + 1; + qp_attr->retry_cnt = cm_id_priv->retry_count; + qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; + qp_attr->max_rd_atomic = + cm_id_priv->initiator_depth; + } + if (cm_id_priv->alt_av.ah_attr.dlid) { + *qp_attr_mask |= IB_QP_PATH_MIG_STATE; + qp_attr->path_mig_state = IB_MIG_REARM; + } + } else { + *qp_attr_mask = IB_QP_ALT_PATH | IB_QP_PATH_MIG_STATE; + qp_attr->alt_port_num = cm_id_priv->alt_av.port->port_num; + qp_attr->alt_pkey_index = cm_id_priv->alt_av.pkey_index; + qp_attr->alt_timeout = + cm_id_priv->alt_av.packet_life_time + 1; + qp_attr->alt_ah_attr = cm_id_priv->alt_av.ah_attr; qp_attr->path_mig_state = IB_MIG_REARM; } ret = 0; diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index b4894ba223b7..1f4f2d2cfa2e 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -683,11 +683,11 @@ out: return result; } -static ssize_t ib_ucm_establish(struct ib_ucm_file *file, - const char __user *inbuf, - int in_len, int out_len) +static ssize_t ib_ucm_notify(struct ib_ucm_file *file, + const char __user *inbuf, + int in_len, int out_len) { - struct ib_ucm_establish cmd; + struct ib_ucm_notify cmd; struct ib_ucm_context *ctx; int result; @@ -698,7 +698,7 @@ static ssize_t ib_ucm_establish(struct ib_ucm_file *file, if (IS_ERR(ctx)) return PTR_ERR(ctx); - result = ib_cm_establish(ctx->cm_id); + result = ib_cm_notify(ctx->cm_id, (enum ib_event_type) cmd.event); ib_ucm_ctx_put(ctx); return result; } @@ -1105,7 +1105,7 @@ static ssize_t (*ucm_cmd_table[])(struct ib_ucm_file *file, [IB_USER_CM_CMD_DESTROY_ID] = ib_ucm_destroy_id, [IB_USER_CM_CMD_ATTR_ID] = ib_ucm_attr_id, [IB_USER_CM_CMD_LISTEN] = ib_ucm_listen, - [IB_USER_CM_CMD_ESTABLISH] = ib_ucm_establish, + [IB_USER_CM_CMD_NOTIFY] = ib_ucm_notify, [IB_USER_CM_CMD_SEND_REQ] = ib_ucm_send_req, [IB_USER_CM_CMD_SEND_REP] = ib_ucm_send_rep, [IB_USER_CM_CMD_SEND_RTU] = ib_ucm_send_rtu, diff --git a/include/rdma/ib_cm.h b/include/rdma/ib_cm.h index c9b4738be9d6..5c070176d9ab 100644 --- a/include/rdma/ib_cm.h +++ b/include/rdma/ib_cm.h @@ -60,6 +60,7 @@ enum ib_cm_state { }; enum ib_cm_lap_state { + IB_CM_LAP_UNINIT, IB_CM_LAP_IDLE, IB_CM_LAP_SENT, IB_CM_LAP_RCVD, @@ -443,13 +444,20 @@ int ib_send_cm_drep(struct ib_cm_id *cm_id, u8 private_data_len); /** - * ib_cm_establish - Forces a connection state to established. + * ib_cm_notify - Notifies the CM of an event reported to the consumer. * @cm_id: Connection identifier to transition to established. + * @event: Type of event. * - * This routine should be invoked by users who receive messages on a - * connected QP before an RTU has been received. + * This routine should be invoked by users to notify the CM of relevant + * communication events. Events that should be reported to the CM and + * when to report them are: + * + * IB_EVENT_COMM_EST - Used when a message is received on a connected + * QP before an RTU has been received. + * IB_EVENT_PATH_MIG - Notifies the CM that the connection has failed over + * to the alternate path. */ -int ib_cm_establish(struct ib_cm_id *cm_id); +int ib_cm_notify(struct ib_cm_id *cm_id, enum ib_event_type event); /** * ib_send_cm_rej - Sends a connection rejection message to the diff --git a/include/rdma/ib_user_cm.h b/include/rdma/ib_user_cm.h index 066c20b7cdfb..37650afb982c 100644 --- a/include/rdma/ib_user_cm.h +++ b/include/rdma/ib_user_cm.h @@ -38,7 +38,7 @@ #include -#define IB_USER_CM_ABI_VERSION 4 +#define IB_USER_CM_ABI_VERSION 5 enum { IB_USER_CM_CMD_CREATE_ID, @@ -46,7 +46,7 @@ enum { IB_USER_CM_CMD_ATTR_ID, IB_USER_CM_CMD_LISTEN, - IB_USER_CM_CMD_ESTABLISH, + IB_USER_CM_CMD_NOTIFY, IB_USER_CM_CMD_SEND_REQ, IB_USER_CM_CMD_SEND_REP, @@ -117,8 +117,9 @@ struct ib_ucm_listen { __u32 reserved; }; -struct ib_ucm_establish { +struct ib_ucm_notify { __u32 id; + __u32 event; }; struct ib_ucm_private_data { -- cgit v1.2.3 From f469b2626f48829c06e40ac799c1edf62b12048e Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 29 Nov 2006 15:33:10 -0800 Subject: IB/ucm: Fix deadlock in cleanup ib_ucm_cleanup_events() holds file_mutex while calling ib_destroy_cm_id(). This can deadlock since ib_destroy_cm_id() flushes event handlers, and ib_ucm_event_handler() needs file_mutex, too. Therefore, drop the file_mutex during the call to ib_destroy_cm_id(). Signed-off-by: Michael S. Tsirkin Signed-off-by: Roland Dreier --- drivers/infiniband/core/ucm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 1f4f2d2cfa2e..f15220a0ee75 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c @@ -161,12 +161,14 @@ static void ib_ucm_cleanup_events(struct ib_ucm_context *ctx) struct ib_ucm_event, ctx_list); list_del(&uevent->file_list); list_del(&uevent->ctx_list); + mutex_unlock(&ctx->file->file_mutex); /* clear incoming connections. */ if (ib_ucm_new_cm_id(uevent->resp.event)) ib_destroy_cm_id(uevent->cm_id); kfree(uevent); + mutex_lock(&ctx->file->file_mutex); } mutex_unlock(&ctx->file->file_mutex); } -- cgit v1.2.3 From 3cb2fccc5f48a4d6269dfd00b4db570fca2a04d5 Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 05:22:59 +0100 Subject: Fix misc Kconfig typos Fix various Kconfig typos. Signed-off-by: Matt LaPlante Acked-by: Randy Dunlap Signed-off-by: Adrian Bunk --- arch/arm/mach-ixp4xx/Kconfig | 2 +- arch/arm/mach-lh7a40x/Kconfig | 2 +- arch/arm/mach-s3c2410/Kconfig | 2 +- arch/arm/mm/Kconfig | 2 +- arch/cris/arch-v10/Kconfig | 2 +- arch/cris/arch-v10/drivers/Kconfig | 2 +- arch/cris/arch-v32/drivers/Kconfig | 8 ++++---- arch/m68knommu/Kconfig | 4 ++-- arch/mips/Kconfig | 4 ++-- arch/powerpc/Kconfig | 2 +- arch/powerpc/platforms/83xx/Kconfig | 4 ++-- arch/ppc/Kconfig | 2 +- arch/sh/Kconfig | 2 +- arch/sparc/Kconfig | 4 ++-- drivers/char/Kconfig | 2 +- drivers/media/video/Kconfig | 2 +- drivers/mtd/maps/Kconfig | 2 +- drivers/net/Kconfig | 4 ++-- drivers/net/phy/Kconfig | 4 ++-- drivers/pci/Kconfig | 2 +- drivers/spi/Kconfig | 2 +- drivers/usb/host/Kconfig | 2 +- fs/Kconfig | 2 +- sound/Kconfig | 4 ++-- 24 files changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 57f23b465392..e316bd93313f 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -133,7 +133,7 @@ config IXP4XX_INDIRECT_PCI into the kernel and we can use the standard read[bwl]/write[bwl] macros. This is the preferred method due to speed but it limits the system to just 64MB of PCI memory. This can be - problamatic if using video cards and other memory-heavy devices. + problematic if using video cards and other memory-heavy devices. 2) If > 64MB of memory space is required, the IXP4xx can be configured to use indirect registers to access PCI This allows diff --git a/arch/arm/mach-lh7a40x/Kconfig b/arch/arm/mach-lh7a40x/Kconfig index 147b01928a9b..6f4c6a1798c1 100644 --- a/arch/arm/mach-lh7a40x/Kconfig +++ b/arch/arm/mach-lh7a40x/Kconfig @@ -8,7 +8,7 @@ config MACH_KEV7A400 help Say Y here if you are using the Sharp KEV7A400 development board. This hardware is discontinued, so I'd be very - suprised if you wanted this option. + surprised if you wanted this option. config MACH_LPD7A400 bool "LPD7A400 Card Engine" diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 63965c78de8c..9aa26b99045d 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig @@ -91,7 +91,7 @@ config SMDK2440_CPU2442 config MACH_S3C2413 bool help - Internal node for S3C2413 verison of SMDK2413, so that + Internal node for S3C2413 version of SMDK2413, so that machine_is_s3c2413() will work when MACH_SMDK2413 is selected diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index c0bfb8212b77..b09a19f87d68 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -197,7 +197,7 @@ config CPU_ARM940T select CPU_CP15_MPU help ARM940T is a member of the ARM9TDMI family of general- - purpose microprocessors with MPU and seperate 4KB + purpose microprocessors with MPU and separate 4KB instruction and 4KB data cases, each with a 4-word line length. diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig index 44eb1b9accb3..c7ea9efd0104 100644 --- a/arch/cris/arch-v10/Kconfig +++ b/arch/cris/arch-v10/Kconfig @@ -323,7 +323,7 @@ config ETRAX_DEF_R_WAITSTATES depends on ETRAX_ARCH_V10 default "95a6" help - Waitstates for SRAM, Flash and peripherials (not DRAM). 95f8 is a + Waitstates for SRAM, Flash and peripherals (not DRAM). 95f8 is a good choice for most Axis products... config ETRAX_DEF_R_BUS_CONFIG diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig index 734d5f3a5304..e7e724bc0ba6 100644 --- a/arch/cris/arch-v10/drivers/Kconfig +++ b/arch/cris/arch-v10/drivers/Kconfig @@ -839,7 +839,7 @@ config ETRAX_DS1302_TRICKLE_CHARGE default "0" help This controls the initial value of the trickle charge register. - 0 = disabled (use this if you are unsure or have a non rechargable battery) + 0 = disabled (use this if you are unsure or have a non rechargeable battery) Otherwise the following values can be OR:ed together to control the charge current: 1 = 2kohm, 2 = 4kohm, 3 = 4kohm diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig index a33097f95362..f64624fc4504 100644 --- a/arch/cris/arch-v32/drivers/Kconfig +++ b/arch/cris/arch-v32/drivers/Kconfig @@ -88,7 +88,7 @@ config ETRAX_SERIAL_PORT0_DMA7_IN help Enables the DMA7 input channel for ser0 (ttyS0). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. @@ -157,7 +157,7 @@ config ETRAX_SERIAL_PORT1_DMA5_IN help Enables the DMA5 input channel for ser1 (ttyS1). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want this on, unless you use the DMA channel for something else. @@ -228,7 +228,7 @@ config ETRAX_SERIAL_PORT2_DMA3_IN help Enables the DMA3 input channel for ser2 (ttyS2). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. @@ -297,7 +297,7 @@ config ETRAX_SERIAL_PORT3_DMA9_IN help Enables the DMA9 input channel for ser3 (ttyS3). If you do not enable DMA, an interrupt for each character will be - used when receiveing data. + used when receiving data. Normally you want to use DMA, unless you use the DMA channel for something else. diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 6d920d4bdc3d..c1bc22c6d0d8 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -565,7 +565,7 @@ config ROMVEC depends on ROM help This is almost always the same as the base of the ROM. Since on all - 68000 type varients the vectors are at the base of the boot device + 68000 type variants the vectors are at the base of the boot device on system startup. config ROMVECSIZE @@ -574,7 +574,7 @@ config ROMVECSIZE depends on ROM help Define the size of the vector region in ROM. For most 68000 - varients this would be 0x400 bytes in size. Set to 0 if you do + variants this would be 0x400 bytes in size. Set to 0 if you do not want a vector region at the start of the ROM. config ROMSTART diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1443024b1c7c..22bb540b5c05 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -865,7 +865,7 @@ config MIPS_DISABLE_OBSOLETE_IDE bool # -# Endianess selection. Suffiently obscure so many users don't know what to +# Endianess selection. Sufficiently obscure so many users don't know what to # answer,so we try hard to limit the available choices. Also the use of a # choice statement should be more obvious to the user. # @@ -874,7 +874,7 @@ choice help Some MIPS machines can be configured for either little or big endian byte order. These modes require different kernels and a different - Linux distribution. In general there is one prefered byteorder for a + Linux distribution. In general there is one preferred byteorder for a particular system but some systems are just as commonly used in the one or the other endianess. diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 0673dbedb241..116d7d3683ed 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -425,7 +425,7 @@ config PPC_MAPLE default n help This option enables support for the Maple 970FX Evaluation Board. - For more informations, refer to + For more information, refer to config PPC_PASEMI depends on PPC_MULTIPLATFORM && PPC64 diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 7edb6b461382..edcd5b875b66 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -21,7 +21,7 @@ config MPC834x_SYS Be aware that PCI buses can only function when SYS board is plugged into the PIB (Platform IO Board) board from Freescale which provide 3 PCI slots. The PIBs PCI initialization is the bootloader's - responsiblilty. + responsibility. config MPC834x_ITX bool "Freescale MPC834x ITX" @@ -30,7 +30,7 @@ config MPC834x_ITX This option enables support for the MPC 834x ITX evaluation board. Be aware that PCI initialization is the bootloader's - responsiblilty. + responsibility. config MPC8360E_PB bool "Freescale MPC8360E PB" diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index 077711e63104..ef018e25fb07 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -724,7 +724,7 @@ config MPC834x_SYS Be aware that PCI buses can only function when SYS board is plugged into the PIB (Platform IO Board) board from Freescale which provide 3 PCI slots. The PIBs PCI initialization is the bootloader's - responsiblilty. + responsibility. config EV64360 bool "Marvell-EV64360BP" diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 6a461d4caeff..bffc7e176970 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig @@ -217,7 +217,7 @@ config SH_SHMIN bool "SHMIN" select CPU_SUBTYPE_SH7706 help - Select SHMIN if configureing for the SHMIN board + Select SHMIN if configuring for the SHMIN board. config SH_UNKNOWN bool "BareCPU" diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 2f96610a83e9..92a7c8a636d3 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -212,8 +212,8 @@ config SPARC_LED tristate "Sun4m LED driver" help This driver toggles the front-panel LED on sun4m systems - in a user-specifyable manner. It's state can be probed - by reading /proc/led and it's blinking mode can be changed + in a user-specifiable manner. Its state can be probed + by reading /proc/led and its blinking mode can be changed via writes to /proc/led source "fs/Kconfig.binfmt" diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 2af12fc45115..ad8b537ad47b 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -994,7 +994,7 @@ config HPET help If you say Y here, you will have a miscdevice named "/dev/hpet/". Each open selects one of the timers supported by the HPET. The timers are - non-periodioc and/or periodic. + non-periodic and/or periodic. config HPET_RTC_IRQ bool "HPET Control RTC IRQ" if !HPET_EMULATE_RTC diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bf267552941f..b8fde5cf4735 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -24,7 +24,7 @@ config VIDEO_HELPER_CHIPS_AUTO decode audio/video standards. This option will autoselect all pertinent modules to each selected video module. - Unselect this only if you know exaclty what you are doing, since + Unselect this only if you know exactly what you are doing, since it may break support on some boards. In doubt, say Y. diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 24747bdc3e19..d132ed571f13 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -607,7 +607,7 @@ config MTD_BAST_MAXSIZE default "4" config MTD_SHARP_SL - bool "ROM maped on Sharp SL Series" + bool "ROM mapped on Sharp SL Series" depends on MTD && ARCH_PXA help This enables access to the flash chip on the Sharp SL Series of PDAs. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6e863aa9894c..b6c70c58ae99 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -32,7 +32,7 @@ config IFB tristate "Intermediate Functional Block support" depends on NET_CLS_ACT ---help--- - This is an intermidiate driver that allows sharing of + This is an intermediate driver that allows sharing of resources. To compile this driver as a module, choose M here: the module will be called ifb. If you want to use more than one ifb @@ -2136,7 +2136,7 @@ config SK98LIN This driver supports the original Yukon chipset. A cleaner driver is also available (skge) which seems to work better than this one. - This driver does not support the newer Yukon2 chipset. A seperate + This driver does not support the newer Yukon2 chipset. A separate driver, sky2, is provided to support Yukon2-based adapters. The following adapters are supported by this driver: diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index b79ec0d7480f..ecb61f876f27 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -61,8 +61,8 @@ config FIXED_PHY depends on PHYLIB ---help--- Adds the driver to PHY layer to cover the boards that do not have any PHY bound, - but with the ability to manipulate with speed/link in software. The relavant MII - speed/duplex parameters could be effectively handled in user-specified fuction. + but with the ability to manipulate the speed/link in software. The relevant MII + speed/duplex parameters could be effectively handled in a user-specified function. Currently tested with mpc866ads. config FIXED_MII_10_FDX diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5f1b9f58070e..d0ba112355cc 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -27,7 +27,7 @@ config PCI_MULTITHREAD_PROBE smaller speedup on single processor machines. But it can also cause lots of bad things to happen. A number - of PCI drivers can not properly handle running in this way, + of PCI drivers cannot properly handle running in this way, some will just not work properly at all, while others might decide to blow up power supplies with a huge load all at once, so use this option at your own risk. diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 23334c8bc4c7..d895a1adb428 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -16,7 +16,7 @@ config SPI controller and a chipselect. Most SPI slaves don't support dynamic device discovery; some are even write-only or read-only. - SPI is widely used by microcontollers to talk with sensors, + SPI is widely used by microcontrollers to talk with sensors, eeprom and flash memory, codecs and various other controller chips, analog to digital (and d-to-a) converters, and more. MMC and SD cards can be accessed using SPI protocol; and for diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index cf10cbc98f80..cc60759083bf 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -153,7 +153,7 @@ config USB_U132_HCD adapter will *NOT* work with PC cards that do not contain an OHCI controller. - For those PC cards that contain multiple OHCI controllers only ther + For those PC cards that contain multiple OHCI controllers only the first one is used. The driver consists of two modules, the "ftdi-elan" module is a diff --git a/fs/Kconfig b/fs/Kconfig index 7b1511d50b05..8bec76bbc0c3 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1145,7 +1145,7 @@ config BEFS_FS help The BeOS File System (BeFS) is the native file system of Be, Inc's BeOS. Notable features include support for arbitrary attributes - on files and directories, and database-like indeces on selected + on files and directories, and database-like indices on selected attributes. (Also note that this driver doesn't make those features available at this time). It is a 64 bit filesystem, so it supports extremely large volumes and files. diff --git a/sound/Kconfig b/sound/Kconfig index e0d791a98452..95949b6806ac 100644 --- a/sound/Kconfig +++ b/sound/Kconfig @@ -64,11 +64,11 @@ source "sound/arm/Kconfig" source "sound/mips/Kconfig" -# the following will depenend on the order of config. +# the following will depend on the order of config. # here assuming USB is defined before ALSA source "sound/usb/Kconfig" -# the following will depenend on the order of config. +# the following will depend on the order of config. # here assuming PCMCIA is defined before ALSA source "sound/pcmcia/Kconfig" -- cgit v1.2.3 From 0779bf2d2ecc4d9b1e9437ae659f50e6776a7666 Mon Sep 17 00:00:00 2001 From: Matt LaPlante Date: Thu, 30 Nov 2006 05:24:39 +0100 Subject: Fix misc .c/.h comment typos Fix various .c/.h typos in comments (no code changes). Signed-off-by: Matt LaPlante Signed-off-by: Adrian Bunk --- arch/cris/arch-v10/drivers/eeprom.c | 6 +++--- arch/cris/arch-v10/drivers/i2c.c | 2 +- arch/cris/arch-v10/kernel/kgdb.c | 2 +- arch/ia64/hp/common/sba_iommu.c | 8 ++++---- arch/sh64/lib/dbg.c | 2 +- drivers/atm/iphase.c | 2 +- drivers/char/rio/riocmd.c | 2 +- drivers/char/rio/rioinit.c | 2 +- drivers/char/rio/rioparam.c | 6 +++--- drivers/ide/ide-floppy.c | 2 +- drivers/isdn/hardware/eicon/os_4bri.c | 2 +- drivers/isdn/hisax/hfc4s8s_l1.h | 2 +- drivers/media/dvb/ttpci/budget-patch.c | 8 ++++---- drivers/net/e100.c | 2 +- drivers/net/e1000/e1000_hw.c | 2 +- drivers/net/sk98lin/h/skdrv2nd.h | 2 +- drivers/net/sk98lin/skdim.c | 4 ++-- drivers/net/wireless/ipw2200.c | 4 ++-- drivers/parisc/ccio-dma.c | 2 +- drivers/parisc/iosapic.c | 6 +++--- drivers/pci/hotplug/ibmphp_hpc.c | 2 +- drivers/s390/net/claw.h | 2 +- drivers/scsi/aic94xx/aic94xx_reg_def.h | 2 +- drivers/scsi/aic94xx/aic94xx_sds.c | 4 ++-- drivers/scsi/ncr53c8xx.c | 14 +++++++------- drivers/scsi/ncr53c8xx.h | 6 +++--- drivers/usb/host/u132-hcd.c | 6 +++--- drivers/usb/misc/usb_u132.h | 2 +- drivers/usb/serial/digi_acceleport.c | 2 +- fs/reiserfs/journal.c | 6 +++--- include/asm-m68knommu/mcfmbus.h | 2 +- include/asm-parisc/dma.h | 6 +++--- include/asm-parisc/pci.h | 2 +- include/asm-parisc/ropes.h | 2 +- include/linux/ixjuser.h | 2 +- include/linux/reiserfs_fs_sb.h | 2 +- net/wanrouter/af_wanpipe.c | 4 ++-- net/wanrouter/wanmain.c | 2 +- sound/oss/cs46xx.c | 6 +++--- 39 files changed, 71 insertions(+), 71 deletions(-) (limited to 'drivers') diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c index 6e1f191a71e3..284ebfda03f0 100644 --- a/arch/cris/arch-v10/drivers/eeprom.c +++ b/arch/cris/arch-v10/drivers/eeprom.c @@ -1,7 +1,7 @@ /*!***************************************************************************** *! -*! Implements an interface for i2c compatible eeproms to run under linux. -*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustents by +*! Implements an interface for i2c compatible eeproms to run under Linux. +*! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustments by *! Johan.Adolfsson@axis.com *! *! Probing results: @@ -51,7 +51,7 @@ *! Revision 1.8 2001/06/15 13:24:29 jonashg *! * Added verification of pointers from userspace in read and write. *! * Made busy counter volatile. -*! * Added define for inital write delay. +*! * Added define for initial write delay. *! * Removed warnings by using loff_t instead of unsigned long. *! *! Revision 1.7 2001/06/14 15:26:54 jonashg diff --git a/arch/cris/arch-v10/drivers/i2c.c b/arch/cris/arch-v10/drivers/i2c.c index 6114596c3b33..092c724a645f 100644 --- a/arch/cris/arch-v10/drivers/i2c.c +++ b/arch/cris/arch-v10/drivers/i2c.c @@ -47,7 +47,7 @@ *! Update Port B register and shadow even when running with hardware support *! to avoid glitches when reading bits *! Never set direction to out in i2c_inbyte -*! Removed incorrect clock togling at end of i2c_inbyte +*! Removed incorrect clock toggling at end of i2c_inbyte *! *! Revision 1.8 2002/08/13 06:31:53 starvik *! Made SDA and SCL line configurable diff --git a/arch/cris/arch-v10/kernel/kgdb.c b/arch/cris/arch-v10/kernel/kgdb.c index 34528da98817..07628a13c6c4 100644 --- a/arch/cris/arch-v10/kernel/kgdb.c +++ b/arch/cris/arch-v10/kernel/kgdb.c @@ -33,7 +33,7 @@ *! *! Revision 1.2 2002/11/19 14:35:24 starvik *! Changes from linux 2.4 -*! Changed struct initializer syntax to the currently prefered notation +*! Changed struct initializer syntax to the currently preferred notation *! *! Revision 1.1 2001/12/17 13:59:27 bjornw *! Initial revision diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index db8e1fcfa047..14691cda05c3 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -75,7 +75,7 @@ ** If a device prefetches beyond the end of a valid pdir entry, it will cause ** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should ** disconnect on 4k boundaries and prevent such issues. If the device is -** particularly agressive, this option will keep the entire pdir valid such +** particularly aggressive, this option will keep the entire pdir valid such ** that prefetching will hit a valid address. This could severely impact ** error containment, and is therefore off by default. The page that is ** used for spill-over is poisoned, so that should help debugging somewhat. @@ -258,10 +258,10 @@ static u64 prefetch_spill_page; /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up -** (or rather not merge) DMA's into managable chunks. +** (or rather not merge) DMAs into manageable chunks. ** On parisc, this is more of the software/tuning constraint -** rather than the HW. I/O MMU allocation alogorithms can be -** faster with smaller size is (to some degree). +** rather than the HW. I/O MMU allocation algorithms can be +** faster with smaller sizes (to some degree). */ #define DMA_CHUNK_SIZE (BITS_PER_LONG*iovp_size) diff --git a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c index 1326f45f31eb..4310fc87444e 100644 --- a/arch/sh64/lib/dbg.c +++ b/arch/sh64/lib/dbg.c @@ -383,7 +383,7 @@ void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs) /* ======================================================================= */ /* -** Depending on scan the MMU, Data or Instrction side +** Depending on scan the MMU, Data or Instruction side ** looking for a valid mapping matching Eaddr & asid. ** Return -1 if not found or the TLB id entry otherwise. ** Note: it works only for 4k pages! diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index 9ed1c60048f0..bb7ef570514c 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -305,7 +305,7 @@ static void clear_lockup (struct atm_vcc *vcc, IADEV *dev) { ** | R | NZ | 5-bit exponent | 9-bit mantissa | ** +----+----+------------------+-------------------------------+ ** -** R = reserverd (written as 0) +** R = reserved (written as 0) ** NZ = 0 if 0 cells/sec; 1 otherwise ** ** if NZ = 1, rate = 1.mmmmmmmmm x 2^(eeeee) cells/sec diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c index 4df6ab2206a1..167ebc84e8d7 100644 --- a/drivers/char/rio/riocmd.c +++ b/drivers/char/rio/riocmd.c @@ -922,7 +922,7 @@ int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP) ** ** Packet is an actual packet structure to be filled in with the packet ** information associated with the command. You need to fill in everything, -** as the command processore doesn't process the command packet in any way. +** as the command processor doesn't process the command packet in any way. ** ** The PreFuncP is called before the packet is enqueued on the host rup. ** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c index 99f3df02b61c..0794844369d6 100644 --- a/drivers/char/rio/rioinit.c +++ b/drivers/char/rio/rioinit.c @@ -222,7 +222,7 @@ int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, i ** which value will be written into memory. ** Call with op set to zero means that the RAM will not be read and checked ** before it is written. -** Call with op not zero, and the RAM will be read and compated with val[op-1] +** Call with op not zero and the RAM will be read and compared with val[op-1] ** to check that the data from the previous phase was retained. */ diff --git a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c index 1066d9760704..bb498d24adcc 100644 --- a/drivers/char/rio/rioparam.c +++ b/drivers/char/rio/rioparam.c @@ -87,8 +87,8 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; ** command bit set onto the port. The command bit is in the len field, ** and gets ORed in with the actual byte count. ** -** When you send a packet with the command bit set, then the first -** data byte ( data[0] ) is interpretted as the command to execute. +** When you send a packet with the command bit set the first +** data byte (data[0]) is interpreted as the command to execute. ** It also governs what data structure overlay should accompany the packet. ** Commands are defined in cirrus/cirrus.h ** @@ -103,7 +103,7 @@ static char *_rioparam_c_sccs_ = "@(#)rioparam.c 1.3"; ** ** Most commands do not use the remaining bytes in the data array. The ** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and -** OPEN are currently analagous). With these three commands the following +** OPEN are currently analogous). With these three commands the following ** 11 data bytes are all used to pass config information such as baud rate etc. ** The fields are also defined in cirrus.h. Some contain straightforward ** information such as the transmit XON character. Two contain the transmit and diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 8ccee9c769f8..e3a267622bb6 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1635,7 +1635,7 @@ static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg) /* ** Get ATAPI_FORMAT_UNIT progress indication. ** -** Userland gives a pointer to an int. The int is set to a progresss +** Userland gives a pointer to an int. The int is set to a progress ** indicator 0-65536, with 65536=100%. ** ** If the drive does not support format progress indication, we just check diff --git a/drivers/isdn/hardware/eicon/os_4bri.c b/drivers/isdn/hardware/eicon/os_4bri.c index 11e6f937c1e4..7b4ec3f60dbf 100644 --- a/drivers/isdn/hardware/eicon/os_4bri.c +++ b/drivers/isdn/hardware/eicon/os_4bri.c @@ -464,7 +464,7 @@ int diva_4bri_init_card(diva_os_xdi_adapter_t * a) /* ** Cleanup function will be called for master adapter only -** this is garanteed by design: cleanup callback is set +** this is guaranteed by design: cleanup callback is set ** by master adapter only */ static int diva_4bri_cleanup_adapter(diva_os_xdi_adapter_t * a) diff --git a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h index e8f9c077fa85..9d5d2a56b4e9 100644 --- a/drivers/isdn/hisax/hfc4s8s_l1.h +++ b/drivers/isdn/hisax/hfc4s8s_l1.h @@ -16,7 +16,7 @@ /* * include Genero generated HFC-4S/8S header file hfc48scu.h -* for comlete register description. This will define _HFC48SCU_H_ +* for complete register description. This will define _HFC48SCU_H_ * to prevent redefinitions */ diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c index fc1267b8c892..9a155396d6ac 100644 --- a/drivers/media/dvb/ttpci/budget-patch.c +++ b/drivers/media/dvb/ttpci/budget-patch.c @@ -500,14 +500,14 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte /* New design (By Emard) ** this rps1 code will copy internal HS event to GPIO3 pin. -** GPIO3 is in budget-patch hardware connectd to port B VSYNC +** GPIO3 is in budget-patch hardware connected to port B VSYNC ** HS is an internal event of 7146, accessible with RPS ** and temporarily raised high every n lines ** (n in defined in the RPS_THRESH1 counter threshold) ** I think HS is raised high on the beginning of the n-th line ** and remains high until this n-th line that triggered -** it is completely received. When the receiption of n-th line +** it is completely received. When the reception of n-th line ** ends, HS is lowered. ** To transmit data over DMA, 7146 needs changing state at @@ -541,7 +541,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ** hardware debug note: a working budget card (including budget patch) ** with vpeirq() interrupt setup in mode "0x90" (every 64K) will ** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes -** and that means 3*25=75 Hz of interrupt freqency, as seen by +** and that means 3*25=75 Hz of interrupt frequency, as seen by ** watch cat /proc/interrupts ** ** If this frequency is 3x lower (and data received in the DMA @@ -550,7 +550,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte ** this means VSYNC line is not connected in the hardware. ** (check soldering pcb and pins) ** The same behaviour of missing VSYNC can be duplicated on budget -** cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. +** cards, by setting DD1_INIT trigger mode 7 in 3rd nibble. */ // Setup RPS1 "program" (p35) diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 19ab3441269c..3a8df479cbda 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1215,7 +1215,7 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb * the literal in the instruction before the code is loaded, the * driver can change the algorithm. * -* INTDELAY - This loads the dead-man timer with its inital value. +* INTDELAY - This loads the dead-man timer with its initial value. * When this timer expires the interrupt is asserted, and the * timer is reset each time a new packet is received. (see * BUNDLEMAX below to set the limit on number of chained packets) diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 65077f39da69..796c4f7d4260 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -3868,7 +3868,7 @@ e1000_phy_hw_reset(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code * -* Sets bit 15 of the MII Control regiser +* Sets bit 15 of the MII Control register ******************************************************************************/ int32_t e1000_phy_reset(struct e1000_hw *hw) diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h index 778d9e618ebd..3fa67171e832 100644 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ b/drivers/net/sk98lin/h/skdrv2nd.h @@ -160,7 +160,7 @@ struct s_IOCTL { /* ** Interim definition of SK_DRV_TIMER placed in this file until -** common modules have boon finallized +** common modules have been finalized */ #define SK_DRV_TIMER 11 #define SK_DRV_MODERATION_TIMER 1 diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c index 07c1b4c8699d..37ce03fb8de3 100644 --- a/drivers/net/sk98lin/skdim.c +++ b/drivers/net/sk98lin/skdim.c @@ -252,7 +252,7 @@ SkDimEnableModerationIfNeeded(SK_AC *pAC) { /******************************************************************************* ** Function : SkDimDisplayModerationSettings -** Description : Displays the current settings regaring interrupt moderation +** Description : Displays the current settings regarding interrupt moderation ** Programmer : Ralph Roesler ** Last Modified: 22-mar-03 ** Returns : void (!) @@ -510,7 +510,7 @@ EnableIntMod(SK_AC *pAC) { /******************************************************************************* ** Function : DisableIntMod() -** Description : Disbles the interrupt moderation independent of what inter- +** Description : Disables the interrupt moderation independent of what inter- ** rupts are running or not ** Programmer : Ralph Roesler ** Last Modified: 23-mar-03 diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 1f742814a01c..72120d5c2f7b 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -6920,8 +6920,8 @@ static int ipw_qos_association(struct ipw_priv *priv, } /* -* handling the beaconing responces. if we get different QoS setting -* of the network from the the associated setting adjust the QoS +* handling the beaconing responses. if we get different QoS setting +* off the network from the associated setting, adjust the QoS * setting */ static int ipw_qos_association_resp(struct ipw_priv *priv, diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 68cb3a080050..fe3f5f5365c5 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -486,7 +486,7 @@ typedef unsigned long space_t; ** This bit tells U2 to do R/M/W for partial cachelines. "Streaming" ** data can avoid this if the mapping covers full cache lines. ** o STOP_MOST is needed for atomicity across cachelines. -** Apperently only "some EISA devices" need this. +** Apparently only "some EISA devices" need this. ** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs ** to use this hint iff the EISA devices needs this feature. ** According to the U2 ERS, STOP_MOST enabled pages hurt performance. diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index c2949b4367e5..12bab64a62a1 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -50,12 +50,12 @@ ** ** PA Firmware ** ----------- -** PA-RISC platforms have two fundementally different types of firmware. +** PA-RISC platforms have two fundamentally different types of firmware. ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register ** and BARs similar to a traditional PC BIOS. ** The newer "PAT" firmware supports PDC calls which return tables. -** PAT firmware only initializes PCI Console and Boot interface. -** With these tables, the OS can progam all other PCI devices. +** PAT firmware only initializes the PCI Console and Boot interface. +** With these tables, the OS can program all other PCI devices. ** ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT). ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index c3ac98a0a6a6..f55ac3885cb3 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -531,7 +531,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index) * * Action: issue a READ command to HPC * -* Input: pslot - can not be NULL for READ_ALLSTAT +* Input: pslot - cannot be NULL for READ_ALLSTAT * pstatus - can be NULL for READ_ALLSTAT * * Return 0 or error codes diff --git a/drivers/s390/net/claw.h b/drivers/s390/net/claw.h index 969be465309c..1ee9a6f06541 100644 --- a/drivers/s390/net/claw.h +++ b/drivers/s390/net/claw.h @@ -29,7 +29,7 @@ #define CLAW_COMPLETE 0xff /* flag to indicate i/o completed */ /*-----------------------------------------------------* -* CLAW control comand code * +* CLAW control command code * *------------------------------------------------------*/ #define SYSTEM_VALIDATE_REQUEST 0x01 /* System Validate request */ diff --git a/drivers/scsi/aic94xx/aic94xx_reg_def.h b/drivers/scsi/aic94xx/aic94xx_reg_def.h index b79f45f3ad47..a11f4e6d8bd9 100644 --- a/drivers/scsi/aic94xx/aic94xx_reg_def.h +++ b/drivers/scsi/aic94xx/aic94xx_reg_def.h @@ -2000,7 +2000,7 @@ * The host accesses this scratch in a different manner from the * central sequencer. The sequencer has to use CSEQ registers CSCRPAGE * and CMnSCRPAGE to access the scratch memory. A flat mapping of the - * scratch memory is avaliable for software convenience and to prevent + * scratch memory is available for software convenience and to prevent * corruption while the sequencer is running. This memory is mapped * onto addresses 800h - BFFh, total of 400h bytes. * diff --git a/drivers/scsi/aic94xx/aic94xx_sds.c b/drivers/scsi/aic94xx/aic94xx_sds.c index de7c04d4254d..e5a0ec37e954 100644 --- a/drivers/scsi/aic94xx/aic94xx_sds.c +++ b/drivers/scsi/aic94xx/aic94xx_sds.c @@ -64,7 +64,7 @@ struct asd_ocm_dir { #define OCM_INIT_DIR_ENTRIES 5 /*************************************************************************** -* OCM dircetory default +* OCM directory default ***************************************************************************/ static struct asd_ocm_dir OCMDirInit = { @@ -73,7 +73,7 @@ static struct asd_ocm_dir OCMDirInit = }; /*************************************************************************** -* OCM dircetory Entries default +* OCM directory Entries default ***************************************************************************/ static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] = { diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 6cc2bc2f62be..adb8eb4f5fd1 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -185,7 +185,7 @@ static inline struct list_head *ncr_list_pop(struct list_head *head) ** power of 2 cache line size. ** Enhanced in linux-2.3.44 to provide a memory pool ** per pcidev to support dynamic dma mapping. (I would -** have preferred a real bus astraction, btw). +** have preferred a real bus abstraction, btw). ** **========================================================== */ @@ -1438,7 +1438,7 @@ struct head { ** The first four bytes (scr_st[4]) are used inside the script by ** "COPY" commands. ** Because source and destination must have the same alignment -** in a DWORD, the fields HAVE to be at the choosen offsets. +** in a DWORD, the fields HAVE to be at the chosen offsets. ** xerr_st 0 (0x34) scratcha ** sync_st 1 (0x05) sxfer ** wide_st 3 (0x03) scntl3 @@ -1498,7 +1498,7 @@ struct head { ** the DSA (data structure address) register points ** to this substructure of the ccb. ** This substructure contains the header with -** the script-processor-changable data and +** the script-processor-changeable data and ** data blocks for the indirect move commands. ** **---------------------------------------------------------- @@ -5107,7 +5107,7 @@ void ncr_complete (struct ncb *np, struct ccb *cp) /* ** This CCB has been skipped by the NCR. -** Queue it in the correponding unit queue. +** Queue it in the corresponding unit queue. */ static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp) { @@ -5896,8 +5896,8 @@ static void ncr_log_hard_error(struct ncb *np, u16 sist, u_char dstat) ** ** In normal cases, interrupt conditions occur one at a ** time. The ncr is able to stack in some extra registers -** other interrupts that will occurs after the first one. -** But severall interrupts may occur at the same time. +** other interrupts that will occur after the first one. +** But, several interrupts may occur at the same time. ** ** We probably should only try to deal with the normal ** case, but it seems that multiple interrupts occur in @@ -6796,7 +6796,7 @@ void ncr_int_sir (struct ncb *np) ** The host status field is set to HS_NEGOTIATE to mark this ** situation. ** -** If the target doesn't answer this message immidiately +** If the target doesn't answer this message immediately ** (as required by the standard), the SIR_NEGO_FAIL interrupt ** will be raised eventually. ** The handler removes the HS_NEGOTIATE status, and sets the diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index cb8b7701431e..b39357d9af8d 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -218,7 +218,7 @@ ** Same as option 1, but also deal with ** misconfigured interrupts. ** -** - Edge triggerred instead of level sensitive. +** - Edge triggered instead of level sensitive. ** - No interrupt line connected. ** - IRQ number misconfigured. ** @@ -549,7 +549,7 @@ struct ncr_driver_setup { /* ** Initial setup. -** Can be overriden at startup by a command line. +** Can be overridden at startup by a command line. */ #define SCSI_NCR_DRIVER_SETUP \ { \ @@ -1093,7 +1093,7 @@ struct scr_tblsel { **----------------------------------------------------------- ** On 810A, 860, 825A, 875, 895 and 896 chips the content ** of SFBR register can be used as data (SCR_SFBR_DATA). -** The 896 has additionnal IO registers starting at +** The 896 has additional IO registers starting at ** offset 0x80. Bit 7 of register offset is stored in ** bit 7 of the SCRIPTS instruction first DWORD. **----------------------------------------------------------- diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 32c635ecbf31..a00d1595656c 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -211,7 +211,7 @@ int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs, int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs, u8 width, u32 data); /* -* these can not be inlines because we need the structure offset!! +* these cannot be inlines because we need the structure offset!! * Does anyone have a better way????? */ #define u132_read_pcimem(u132, member, data) \ @@ -3045,7 +3045,7 @@ static struct hc_driver u132_hc_driver = { * This function may be called by the USB core whilst the "usb_all_devices_rwsem" * is held for writing, thus this module must not call usb_remove_hcd() * synchronously - but instead should immediately stop activity to the -* device and ansynchronously call usb_remove_hcd() +* device and asynchronously call usb_remove_hcd() */ static int __devexit u132_remove(struct platform_device *pdev) { @@ -3241,7 +3241,7 @@ static int u132_resume(struct platform_device *pdev) #define u132_resume NULL #endif /* -* this driver is loaded explicitely by ftdi_u132 +* this driver is loaded explicitly by ftdi_u132 * * the platform_driver struct is static because it is per type of module */ diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h index 551ba8906d62..5b5a3e621daa 100644 --- a/drivers/usb/misc/usb_u132.h +++ b/drivers/usb/misc/usb_u132.h @@ -52,7 +52,7 @@ * the kernel to load the "u132-hcd" module. * * The "ftdi-u132" module provides the interface to the inserted -* PC card and the "u132-hcd" module uses the API to send and recieve +* PC card and the "u132-hcd" module uses the API to send and receive * data. The API features call-backs, so that part of the "u132-hcd" * module code will run in the context of one of the kernel threads * of the "ftdi-u132" module. diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index bdb58100fc1d..5e3ac281a2f8 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -157,7 +157,7 @@ * to TASK_RUNNING will be lost and write_chan's subsequent call to * schedule() will never return (unless it catches a signal). * This race condition occurs because write_bulk_callback() (and thus -* the wakeup) are called asynchonously from an interrupt, rather than +* the wakeup) are called asynchronously from an interrupt, rather than * from the scheduler. We can avoid the race by calling the wakeup * from the scheduler queue and that's our fix: Now, at the end of * write_bulk_callback() we queue up a wakeup call on the scheduler diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 85ce23268302..ac93174c9639 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1464,7 +1464,7 @@ static int flush_journal_list(struct super_block *s, } /* if someone has this block in a newer transaction, just make - ** sure they are commited, and don't try writing it to disk + ** sure they are committed, and don't try writing it to disk */ if (pjl) { if (atomic_read(&pjl->j_commit_left)) @@ -3384,7 +3384,7 @@ static int remove_from_transaction(struct super_block *p_s_sb, /* ** for any cnode in a journal list, it can only be dirtied of all the -** transactions that include it are commited to disk. +** transactions that include it are committed to disk. ** this checks through each transaction, and returns 1 if you are allowed to dirty, ** and 0 if you aren't ** @@ -3426,7 +3426,7 @@ static int can_dirty(struct reiserfs_journal_cnode *cn) } /* syncs the commit blocks, but does not force the real buffers to disk -** will wait until the current transaction is done/commited before returning +** will wait until the current transaction is done/committed before returning */ int journal_end_sync(struct reiserfs_transaction_handle *th, struct super_block *p_s_sb, unsigned long nblocks) diff --git a/include/asm-m68knommu/mcfmbus.h b/include/asm-m68knommu/mcfmbus.h index 13df9d41bd1a..319899c47a2c 100644 --- a/include/asm-m68knommu/mcfmbus.h +++ b/include/asm-m68knommu/mcfmbus.h @@ -37,7 +37,7 @@ #define MCFMBUS_MFDR_MBC(a) ((a)&0x3F) /*M-Bus Clock*/ /* -* Define bit flags in Controll Register +* Define bit flags in Control Register */ #define MCFMBUS_MBCR_MEN (0x80) /* M-Bus Enable */ diff --git a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h index da2cf373e31c..31ad0f05af3d 100644 --- a/include/asm-parisc/dma.h +++ b/include/asm-parisc/dma.h @@ -17,10 +17,10 @@ /* ** DMA_CHUNK_SIZE is used by the SCSI mid-layer to break up -** (or rather not merge) DMA's into managable chunks. +** (or rather not merge) DMAs into manageable chunks. ** On parisc, this is more of the software/tuning constraint -** rather than the HW. I/O MMU allocation alogorithms can be -** faster with smaller size is (to some degree). +** rather than the HW. I/O MMU allocation algorithms can be +** faster with smaller sizes (to some degree). */ #define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE) diff --git a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h index 7b8ad118d2fe..7b3be9ac0dda 100644 --- a/include/asm-parisc/pci.h +++ b/include/asm-parisc/pci.h @@ -149,7 +149,7 @@ extern int parisc_bus_is_phys; /* in arch/parisc/kernel/setup.c */ /* ** Most PCI devices (eg Tulip, NCR720) also export the same registers ** to both MMIO and I/O port space. Due to poor performance of I/O Port -** access under HP PCI bus adapters, strongly reccomend use of MMIO +** access under HP PCI bus adapters, strongly recommend the use of MMIO ** address space. ** ** While I'm at it more PA programming notes: diff --git a/include/asm-parisc/ropes.h b/include/asm-parisc/ropes.h index 5542dd00472b..007a880615eb 100644 --- a/include/asm-parisc/ropes.h +++ b/include/asm-parisc/ropes.h @@ -14,7 +14,7 @@ #endif /* -** The number of pdir entries to "free" before issueing +** The number of pdir entries to "free" before issuing ** a read to PCOM register to flush out PCOM writes. ** Interacts with allocation granularity (ie 4 or 8 entries ** allocated and free'd/purged at a time might make this diff --git a/include/linux/ixjuser.h b/include/linux/ixjuser.h index fd1756d3a47e..88b45895746d 100644 --- a/include/linux/ixjuser.h +++ b/include/linux/ixjuser.h @@ -315,7 +315,7 @@ typedef struct { * structures. If the freq0 variable is non-zero, the tone table contents * for the tone_index are updated to the frequencies and gains defined. It * should be noted that DTMF tones cannot be reassigned, so if DTMF tone -* table indexs are used in a cadence the frequency and gain variables will +* table indexes are used in a cadence the frequency and gain variables will * be ignored. * * If the array elements contain frequency parameters the driver will diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h index 73e0becec086..62a7169aed8b 100644 --- a/include/linux/reiserfs_fs_sb.h +++ b/include/linux/reiserfs_fs_sb.h @@ -429,7 +429,7 @@ enum reiserfs_mount_options { /* -o hash={tea, rupasov, r5, detect} is meant for properly mounting ** reiserfs disks from 3.5.19 or earlier. 99% of the time, this option ** is not required. If the normal autodection code can't determine which -** hash to use (because both hases had the same value for a file) +** hash to use (because both hashes had the same value for a file) ** use this option to force a specific hash. It won't allow you to override ** the existing hash on the FS, so if you have a tea hash disk, and mount ** with -o hash=rupasov, the mount will fail. diff --git a/net/wanrouter/af_wanpipe.c b/net/wanrouter/af_wanpipe.c index 6f39faa15832..c2059733e15a 100644 --- a/net/wanrouter/af_wanpipe.c +++ b/net/wanrouter/af_wanpipe.c @@ -13,7 +13,7 @@ * Due Credit: * Wanpipe socket layer is based on Packet and * the X25 socket layers. The above sockets were -* used for the specific use of Sangoma Technoloiges +* used for the specific use of Sangoma Technologies * API programs. * Packet socket Authors: Ross Biro, Fred N. van Kempen and * Alan Cox. @@ -23,7 +23,7 @@ * Apr 25, 2000 Nenad Corbic o Added the ability to send zero length packets. * Mar 13, 2000 Nenad Corbic o Added a tx buffer check via ioctl call. * Mar 06, 2000 Nenad Corbic o Fixed the corrupt sock lcn problem. -* Server and client applicaton can run +* Server and client application can run * simultaneously without conflicts. * Feb 29, 2000 Nenad Corbic o Added support for PVC protocols, such as * CHDLC, Frame Relay and HDLC API. diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 9479659277ae..316211d9f17d 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -3,7 +3,7 @@ * * This module is completely hardware-independent and provides * the following common services for the WAN Link Drivers: -* o WAN device managenment (registering, unregistering) +* o WAN device management (registering, unregistering) * o Network interface management * o Physical connection management (dial-up, incoming calls) * o Logical connection management (switched virtual circuits) diff --git a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c index 6e3c41f530e6..b1c5d8286e40 100644 --- a/sound/oss/cs46xx.c +++ b/sound/oss/cs46xx.c @@ -779,7 +779,7 @@ static unsigned int cs_set_adc_rate(struct cs_state *state, unsigned int rate) rate = 48000 / 9; /* - * We can not capture at at rate greater than the Input Rate (48000). + * We cannot capture at at rate greater than the Input Rate (48000). * Return an error if an attempt is made to stray outside that limit. */ if (rate > 48000) @@ -4754,8 +4754,8 @@ static int cs_hardware_init(struct cs_card *card) mdelay(5 * cs_laptop_wait); /* Shouldnt be needed ?? */ /* -* If we are resuming under 2.2.x then we can not schedule a timeout. -* so, just spin the CPU. +* If we are resuming under 2.2.x then we cannot schedule a timeout, +* so just spin the CPU. */ if (card->pm.flags & CS46XX_PM_IDLE) { /* -- cgit v1.2.3 From 5d9a276a3eb073251737cb92b790bfdb9f0b9139 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 30 Nov 2006 05:26:46 +0100 Subject: BUG_ON conversion for drivers/media/video/pwc/pwc-if.c This patch converts a if () BUG(); construct to BUG_ON(); which occupies less space, uses unlikely and is safer when BUG() is disabled. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/media/video/pwc/pwc-if.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 46c114830884..e8db6e58d390 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -1095,8 +1095,7 @@ static int pwc_video_open(struct inode *inode, struct file *file) PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); pdev = (struct pwc_device *)vdev->priv; - if (pdev == NULL) - BUG(); + BUG_ON(!pdev); if (pdev->vopen) { PWC_DEBUG_OPEN("I'm busy, someone is using the device.\n"); return -EBUSY; -- cgit v1.2.3 From d99c5909859625f3c9c6dfee6caa3b2a7c0ef163 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 30 Nov 2006 05:27:38 +0100 Subject: BUG_ON conversion for drivers/mmc/omap.c This patch converts a if () BUG(); construct to BUG_ON(); which occupies less space, uses unlikely and is safer when BUG() is disabled. Signed-off-by: Eric Sesterhenn Signed-off-by: Adrian Bunk --- drivers/mmc/omap.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 762fa2895891..d593ef342e75 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -640,8 +640,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) } /* Max limit for DMA frame count is 0xffff */ - if (unlikely(count > 0xffff)) - BUG(); + BUG_ON(count > 0xffff); OMAP_MMC_WRITE(host->base, BUF, buf); omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, -- cgit v1.2.3 From 03a67a46af8647b2c7825107045ecae641e103d3 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 30 Nov 2006 05:32:19 +0100 Subject: Fix typos in doc and comments Changes persistant -> persistent. www.dictionary.com does not know persistant (with an A), but should it be one of those things you can spell in more than one correct way, let me know. Signed-off-by: Jan Engelhardt Signed-off-by: Adrian Bunk --- Documentation/Changes | 2 +- Documentation/power/states.txt | 2 +- arch/um/drivers/chan_user.c | 2 +- drivers/message/fusion/mptbase.c | 2 +- drivers/mtd/maps/cfi_flagadm.c | 2 +- drivers/pci/Kconfig | 2 +- fs/Kconfig | 2 +- fs/jfs/jfs_filsys.h | 2 +- include/linux/textsearch.h | 4 ++-- lib/textsearch.c | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/Documentation/Changes b/Documentation/Changes index abee7f58c1ed..73a8617f1861 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -201,7 +201,7 @@ udev ---- udev is a userspace application for populating /dev dynamically with only entries for devices actually present. udev replaces the basic -functionality of devfs, while allowing persistant device naming for +functionality of devfs, while allowing persistent device naming for devices. FUSE diff --git a/Documentation/power/states.txt b/Documentation/power/states.txt index 3e5e5d3ff419..0931a330d362 100644 --- a/Documentation/power/states.txt +++ b/Documentation/power/states.txt @@ -62,7 +62,7 @@ setup via another operating system for it to use. Despite the inconvenience, this method requires minimal work by the kernel, since the firmware will also handle restoring memory contents on resume. -If the kernel is responsible for persistantly saving state, a mechanism +If the kernel is responsible for persistently saving state, a mechanism called 'swsusp' (Swap Suspend) is used to write memory contents to free swap space. swsusp has some restrictive requirements, but should work in most cases. Some, albeit outdated, documentation can be found diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 2f880cb167a5..0cad3546cb89 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -120,7 +120,7 @@ static int winch_thread(void *arg) /* These are synchronization calls between various UML threads on the * host - since they are not different kernel threads, we cannot use * kernel semaphores. We don't use SysV semaphores because they are - * persistant. */ + * persistent. */ count = os_read_file(pipe_fd, &c, sizeof(c)); if(count != sizeof(c)) printk("winch_thread : failed to read synchronization byte, " diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index e5c72719debc..051b7c5b8f03 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -6185,7 +6185,7 @@ mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info) "Abort", /* 12h */ "IO Not Yet Executed", /* 13h */ "IO Executed", /* 14h */ - "Persistant Reservation Out Not Affiliation Owner", /* 15h */ + "Persistent Reservation Out Not Affiliation Owner", /* 15h */ "Open Transmit DMA Abort", /* 16h */ "IO Device Missing Delay Retry", /* 17h */ NULL, /* 18h */ diff --git a/drivers/mtd/maps/cfi_flagadm.c b/drivers/mtd/maps/cfi_flagadm.c index 92b5d883d7b0..65e5ee552010 100644 --- a/drivers/mtd/maps/cfi_flagadm.c +++ b/drivers/mtd/maps/cfi_flagadm.c @@ -80,7 +80,7 @@ struct mtd_partition flagadm_parts[] = { .size = FLASH_PARTITION2_SIZE }, { - .name = "Persistant storage", + .name = "Persistent storage", .offset = FLASH_PARTITION3_ADDR, .size = FLASH_PARTITION3_SIZE } diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index d0ba112355cc..3cfb0a3575e6 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -34,7 +34,7 @@ config PCI_MULTITHREAD_PROBE It is very unwise to use this option if you are not using a boot process that can handle devices being created in any - order. A program that can create persistant block and network + order. A program that can create persistent block and network device names (like udev) is a good idea if you wish to use this option. diff --git a/fs/Kconfig b/fs/Kconfig index 8bec76bbc0c3..b3b5aa0edff9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -972,7 +972,7 @@ config SYSFS Some system agents rely on the information in sysfs to operate. /sbin/hotplug uses device and object attributes in sysfs to assist in - delegating policy decisions, like persistantly naming devices. + delegating policy decisions, like persistently naming devices. sysfs is currently used by the block subsystem to mount the root partition. If sysfs is disabled you must specify the boot device on diff --git a/fs/jfs/jfs_filsys.h b/fs/jfs/jfs_filsys.h index 9901928668cf..eb550b339bb8 100644 --- a/fs/jfs/jfs_filsys.h +++ b/fs/jfs/jfs_filsys.h @@ -81,7 +81,7 @@ #define JFS_SWAP_BYTES 0x00100000 /* running on big endian computer */ /* Directory index */ -#define JFS_DIR_INDEX 0x00200000 /* Persistant index for */ +#define JFS_DIR_INDEX 0x00200000 /* Persistent index for */ /* directory entries */ diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h index 7dac8f04d28e..004808a6df1d 100644 --- a/include/linux/textsearch.h +++ b/include/linux/textsearch.h @@ -20,7 +20,7 @@ struct ts_config; /** * struct ts_state - search state * @offset: offset for next match - * @cb: control buffer, for persistant variables of get_next_block() + * @cb: control buffer, for persistent variables of get_next_block() */ struct ts_state { @@ -71,7 +71,7 @@ struct ts_config * Called repeatedly until 0 is returned. Must assign the * head of the next block of data to &*dst and return the length * of the block or 0 if at the end. consumed == 0 indicates - * a new search. May store/read persistant values in state->cb. + * a new search. May store/read persistent values in state->cb. */ unsigned int (*get_next_block)(unsigned int consumed, const u8 **dst, diff --git a/lib/textsearch.c b/lib/textsearch.c index 2cb4a437942e..98bcadc01185 100644 --- a/lib/textsearch.c +++ b/lib/textsearch.c @@ -40,7 +40,7 @@ * configuration according to the specified parameters. * (3) User starts the search(es) by calling _find() or _next() to * fetch subsequent occurrences. A state variable is provided - * to the algorihtm to store persistant variables. + * to the algorihtm to store persistent variables. * (4) Core eventually resets the search offset and forwards the find() * request to the algorithm. * (5) Algorithm calls get_next_block() provided by the user continously -- cgit v1.2.3 From 6b44d4e69c6144d0df71ab47ec90d2009237d48f Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 30 Nov 2006 05:33:40 +0100 Subject: Fix typos in drivers/isdn/hisax/isdnl2.c Changes persistant -> persistent in actual C code. (part 1 changed docs/comments). Compile-tested. Signed-off-by: Jan Engelhardt Signed-off-by: Adrian Bunk --- drivers/isdn/hisax/isdnl2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c index 6d0431725555..cd3b5ad53491 100644 --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -1442,7 +1442,7 @@ l2_tei_remove(struct FsmInst *fi, int event, void *arg) } static void -l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1453,7 +1453,7 @@ l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1466,7 +1466,7 @@ l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1477,7 +1477,7 @@ l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) } static void -l2_persistant_da(struct FsmInst *fi, int event, void *arg) +l2_persistent_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1612,14 +1612,14 @@ static struct FsmNode L2FnList[] __initdata = {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da}, + {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, - {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, - {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, + {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, + {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, + {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, }; #define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode)) -- cgit v1.2.3 From f2b67c7945e8d709444884633670fef498218639 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 29 Nov 2006 17:10:38 +0000 Subject: [PATCH] drivers/net: SAA9730: Fix build error Confusingly NET_PCI is also set for for non-PCI EISA configurations where building this driver will result in a build error due to a reference to pci_release_regions. While at it, remove the EXPERIMENTAL - in all its uglyness and despite the sincerest attempts of the buggy hardware the driver is known to work. Also limit the driver to the Atlas board - the only known system to ever use the SAA9730 before Phillips ended the short live of the SAA9730. Signed-off-by: Ralf Baechle Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 6e863aa9894c..30ae712dff74 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1769,8 +1769,8 @@ config VIA_RHINE_NAPI information. config LAN_SAA9730 - bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" - depends on NET_PCI && EXPERIMENTAL && MIPS + bool "Philips SAA9730 Ethernet support" + depends on NET_PCI && PCI && MIPS_ATLAS help The SAA9730 is a combined multimedia and peripheral controller used in thin clients, Internet access terminals, and diskless -- cgit v1.2.3 From 418e8f3d7ef4a30d4b5c84440641c9792a7f83f1 Mon Sep 17 00:00:00 2001 From: Laurent Riffard Date: Sat, 18 Nov 2006 12:03:04 +0100 Subject: [PATCH] bonding: fix an oops when slave device does not provide get_stats Bonding driver unconditionnaly dereference get_stats function pointer for each of its slave device. This patch - adds a check for NULL dev->get_stats pointer in bond_get_stats - prints a notice when the bonding device enslave a device without get_stats function. Signed-off-by: Laurent Riffard Signed-off-by: Jeff Garzik --- drivers/net/bonding/bond_main.c | 63 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 17a461152d39..488d8ed9e740 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1336,6 +1336,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) goto err_undo_flags; } + if (slave_dev->get_stats == NULL) { + printk(KERN_NOTICE DRV_NAME + ": %s: the driver for slave device %s does not provide " + "get_stats function, network statistics will be " + "inaccurate.\n", bond_dev->name, slave_dev->name); + } + new_slave = kmalloc(sizeof(struct slave), GFP_KERNEL); if (!new_slave) { res = -ENOMEM; @@ -3605,33 +3612,35 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev) read_lock_bh(&bond->lock); bond_for_each_slave(bond, slave, i) { - sstats = slave->dev->get_stats(slave->dev); - - stats->rx_packets += sstats->rx_packets; - stats->rx_bytes += sstats->rx_bytes; - stats->rx_errors += sstats->rx_errors; - stats->rx_dropped += sstats->rx_dropped; - - stats->tx_packets += sstats->tx_packets; - stats->tx_bytes += sstats->tx_bytes; - stats->tx_errors += sstats->tx_errors; - stats->tx_dropped += sstats->tx_dropped; - - stats->multicast += sstats->multicast; - stats->collisions += sstats->collisions; - - stats->rx_length_errors += sstats->rx_length_errors; - stats->rx_over_errors += sstats->rx_over_errors; - stats->rx_crc_errors += sstats->rx_crc_errors; - stats->rx_frame_errors += sstats->rx_frame_errors; - stats->rx_fifo_errors += sstats->rx_fifo_errors; - stats->rx_missed_errors += sstats->rx_missed_errors; - - stats->tx_aborted_errors += sstats->tx_aborted_errors; - stats->tx_carrier_errors += sstats->tx_carrier_errors; - stats->tx_fifo_errors += sstats->tx_fifo_errors; - stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; - stats->tx_window_errors += sstats->tx_window_errors; + if (slave->dev->get_stats) { + sstats = slave->dev->get_stats(slave->dev); + + stats->rx_packets += sstats->rx_packets; + stats->rx_bytes += sstats->rx_bytes; + stats->rx_errors += sstats->rx_errors; + stats->rx_dropped += sstats->rx_dropped; + + stats->tx_packets += sstats->tx_packets; + stats->tx_bytes += sstats->tx_bytes; + stats->tx_errors += sstats->tx_errors; + stats->tx_dropped += sstats->tx_dropped; + + stats->multicast += sstats->multicast; + stats->collisions += sstats->collisions; + + stats->rx_length_errors += sstats->rx_length_errors; + stats->rx_over_errors += sstats->rx_over_errors; + stats->rx_crc_errors += sstats->rx_crc_errors; + stats->rx_frame_errors += sstats->rx_frame_errors; + stats->rx_fifo_errors += sstats->rx_fifo_errors; + stats->rx_missed_errors += sstats->rx_missed_errors; + + stats->tx_aborted_errors += sstats->tx_aborted_errors; + stats->tx_carrier_errors += sstats->tx_carrier_errors; + stats->tx_fifo_errors += sstats->tx_fifo_errors; + stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors; + stats->tx_window_errors += sstats->tx_window_errors; + } } read_unlock_bh(&bond->lock); -- cgit v1.2.3 From 9c434f5e2181097e1d22d9b3e381ca6d693e5188 Mon Sep 17 00:00:00 2001 From: James K Lewis Date: Fri, 17 Nov 2006 14:39:36 -0800 Subject: [PATCH] Spidernet: remove ETH_ZLEN check in earlier patch In an earlier patch, code was added to pad packets that were less that ETH_ZLEN (60) bytes using the skb_pad function. This has caused hangs when accessing certain NFS mounted file systems. This patch removes the check and solves the NFS problem. The driver, with this patch, has been tested extensively. Please apply. Signed-off-by: James K Lewis Cc: Stephen Hemminger Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 18 +++++------------- drivers/net/spider_net.h | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 418138dd6c68..9dd282346e1c 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -644,20 +644,12 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, struct spider_net_descr *descr; dma_addr_t buf; unsigned long flags; - int length; - length = skb->len; - if (length < ETH_ZLEN) { - if (skb_pad(skb, ETH_ZLEN-length)) - return 0; - length = ETH_ZLEN; - } - - buf = pci_map_single(card->pdev, skb->data, length, PCI_DMA_TODEVICE); + buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); if (pci_dma_mapping_error(buf)) { if (netif_msg_tx_err(card) && net_ratelimit()) pr_err("could not iommu-map packet (%p, %i). " - "Dropping packet\n", skb->data, length); + "Dropping packet\n", skb->data, skb->len); card->spider_stats.tx_iommu_map_error++; return -ENOMEM; } @@ -667,7 +659,7 @@ spider_net_prepare_tx_descr(struct spider_net_card *card, card->tx_chain.head = descr->next; descr->buf_addr = buf; - descr->buf_size = length; + descr->buf_size = skb->len; descr->next_descr_addr = 0; descr->skb = skb; descr->data_status = 0; @@ -802,8 +794,8 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) /* unmap the skb */ if (skb) { - int len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; - pci_unmap_single(card->pdev, buf_addr, len, PCI_DMA_TODEVICE); + pci_unmap_single(card->pdev, buf_addr, skb->len, + PCI_DMA_TODEVICE); dev_kfree_skb(skb); } } diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h index b3b46119b424..cb85cbb3d92d 100644 --- a/drivers/net/spider_net.h +++ b/drivers/net/spider_net.h @@ -24,7 +24,7 @@ #ifndef _SPIDER_NET_H #define _SPIDER_NET_H -#define VERSION "1.1 A" +#define VERSION "1.5 A" #include "sungem_phy.h" -- cgit v1.2.3 From 7bd54c863608a460e72aa0e57170cffb6bc62110 Mon Sep 17 00:00:00 2001 From: Linas Vepstas Date: Fri, 17 Nov 2006 14:39:40 -0800 Subject: [PATCH] spidernet: poor network performance Correct a problem seen on later kernels running the NetPIPE application. Specifically, NetPIPE would begin running very slowly at the 1533 packet size. It was determined that Spidernet slowed with an idle DMA engine. Signed-off-by: James K Lewis Signed-off-by: Linas Vepstas Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/spider_net.c | 2 +- drivers/net/spider_net.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 9dd282346e1c..cef7e6671c49 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c @@ -1633,7 +1633,7 @@ spider_net_enable_card(struct spider_net_card *card) SPIDER_NET_INT2_MASK_VALUE); spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR, - SPIDER_NET_GDTBSTA | SPIDER_NET_GDTDCEIDIS); + SPIDER_NET_GDTBSTA); } /** diff --git a/drivers/net/spider_net.h b/drivers/net/spider_net.h index cb85cbb3d92d..3e196df29790 100644 --- a/drivers/net/spider_net.h +++ b/drivers/net/spider_net.h @@ -24,7 +24,7 @@ #ifndef _SPIDER_NET_H #define _SPIDER_NET_H -#define VERSION "1.5 A" +#define VERSION "1.6 A" #include "sungem_phy.h" @@ -217,8 +217,7 @@ extern char spider_net_driver_name[]; #define SPIDER_NET_GDTBSTA 0x00000300 #define SPIDER_NET_GDTDCEIDIS 0x00000002 #define SPIDER_NET_DMA_TX_VALUE SPIDER_NET_TX_DMA_EN | \ - SPIDER_NET_GDTBSTA | \ - SPIDER_NET_GDTDCEIDIS + SPIDER_NET_GDTBSTA #define SPIDER_NET_DMA_TX_FEND_VALUE 0x00030003 @@ -328,7 +327,8 @@ enum spider_net_int2_status { SPIDER_NET_GRISPDNGINT }; -#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) ) +#define SPIDER_NET_TXINT ( (1 << SPIDER_NET_GDTFDCINT) | \ + (1 << SPIDER_NET_GDTDCEINT) ) /* We rely on flagged descriptor interrupts */ #define SPIDER_NET_RXINT ( (1 << SPIDER_NET_GDAFDCINT) ) -- cgit v1.2.3 From 9e1402ab89623f08c8dc06ec395e3214e1ec7848 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Thu, 16 Nov 2006 14:50:14 -0500 Subject: [PATCH] Fix an offset error when reading the CS89x0 ADD_PORT register Fix an offset error when reading the CS89x0 ADD_PORT register. Signed-off-by: George G. Davis Signed-off-by: Jeff Garzik --- drivers/net/cs89x0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 4ffc9b44a8e1..dec70c2b374a 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -588,10 +588,10 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular) goto out2; } } - printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", - ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); ioaddr &= ~3; + printk(KERN_DEBUG "PP_addr at %x[%x]: 0x%x\n", + ioaddr, ADD_PORT, readword(ioaddr, ADD_PORT)); writeword(ioaddr, ADD_PORT, PP_ChipID); tmp = readword(ioaddr, DATA_PORT); -- cgit v1.2.3 From 0e75f9063f5c55fb0b0b546a7c356f8ec186825e Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 1 Dec 2006 10:40:55 +0100 Subject: [PATCH] block: support larger block pc requests This patch modifies blk_rq_map/unmap_user() and the cdrom and scsi_ioctl.c users so that it supports requests larger than bio by chaining them together. Signed-off-by: Mike Christie Signed-off-by: Jens Axboe --- block/ll_rw_blk.c | 166 +++++++++++++++++++++++++++++++++++++------------ block/scsi_ioctl.c | 53 ++++++++-------- drivers/cdrom/cdrom.c | 6 +- fs/bio.c | 18 +----- include/linux/blkdev.h | 7 ++- 5 files changed, 160 insertions(+), 90 deletions(-) (limited to 'drivers') diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 9eaee6640535..0f82e12f7b67 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -2322,6 +2322,84 @@ void blk_insert_request(request_queue_t *q, struct request *rq, EXPORT_SYMBOL(blk_insert_request); +static int __blk_rq_unmap_user(struct bio *bio) +{ + int ret = 0; + + if (bio) { + if (bio_flagged(bio, BIO_USER_MAPPED)) + bio_unmap_user(bio); + else + ret = bio_uncopy_user(bio); + } + + return ret; +} + +static int __blk_rq_map_user(request_queue_t *q, struct request *rq, + void __user *ubuf, unsigned int len) +{ + unsigned long uaddr; + struct bio *bio, *orig_bio; + int reading, ret; + + reading = rq_data_dir(rq) == READ; + + /* + * if alignment requirement is satisfied, map in user pages for + * direct dma. else, set up kernel bounce buffers + */ + uaddr = (unsigned long) ubuf; + if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) + bio = bio_map_user(q, NULL, uaddr, len, reading); + else + bio = bio_copy_user(q, uaddr, len, reading); + + if (IS_ERR(bio)) { + return PTR_ERR(bio); + } + + orig_bio = bio; + blk_queue_bounce(q, &bio); + /* + * We link the bounce buffer in and could have to traverse it + * later so we have to get a ref to prevent it from being freed + */ + bio_get(bio); + + /* + * for most (all? don't know of any) queues we could + * skip grabbing the queue lock here. only drivers with + * funky private ->back_merge_fn() function could be + * problematic. + */ + spin_lock_irq(q->queue_lock); + if (!rq->bio) + blk_rq_bio_prep(q, rq, bio); + else if (!q->back_merge_fn(q, rq, bio)) { + ret = -EINVAL; + spin_unlock_irq(q->queue_lock); + goto unmap_bio; + } else { + rq->biotail->bi_next = bio; + rq->biotail = bio; + + rq->nr_sectors += bio_sectors(bio); + rq->hard_nr_sectors = rq->nr_sectors; + rq->data_len += bio->bi_size; + } + spin_unlock_irq(q->queue_lock); + + return bio->bi_size; + +unmap_bio: + /* if it was boucned we must call the end io function */ + bio_endio(bio, bio->bi_size, 0); + __blk_rq_unmap_user(orig_bio); + bio_put(bio); + return ret; +} + /** * blk_rq_map_user - map user data to a request, for REQ_BLOCK_PC usage * @q: request queue where request should be inserted @@ -2343,42 +2421,44 @@ EXPORT_SYMBOL(blk_insert_request); * unmapping. */ int blk_rq_map_user(request_queue_t *q, struct request *rq, void __user *ubuf, - unsigned int len) + unsigned long len) { - unsigned long uaddr; - struct bio *bio; - int reading; + unsigned long bytes_read = 0; + int ret; if (len > (q->max_hw_sectors << 9)) return -EINVAL; if (!len || !ubuf) return -EINVAL; - reading = rq_data_dir(rq) == READ; + while (bytes_read != len) { + unsigned long map_len, end, start; - /* - * if alignment requirement is satisfied, map in user pages for - * direct dma. else, set up kernel bounce buffers - */ - uaddr = (unsigned long) ubuf; - if (!(uaddr & queue_dma_alignment(q)) && !(len & queue_dma_alignment(q))) - bio = bio_map_user(q, NULL, uaddr, len, reading); - else - bio = bio_copy_user(q, uaddr, len, reading); + map_len = min_t(unsigned long, len - bytes_read, BIO_MAX_SIZE); + end = ((unsigned long)ubuf + map_len + PAGE_SIZE - 1) + >> PAGE_SHIFT; + start = (unsigned long)ubuf >> PAGE_SHIFT; - if (!IS_ERR(bio)) { - rq->bio = rq->biotail = bio; - blk_rq_bio_prep(q, rq, bio); + /* + * A bad offset could cause us to require BIO_MAX_PAGES + 1 + * pages. If this happens we just lower the requested + * mapping len by a page so that we can fit + */ + if (end - start > BIO_MAX_PAGES) + map_len -= PAGE_SIZE; - rq->buffer = rq->data = NULL; - rq->data_len = len; - return 0; + ret = __blk_rq_map_user(q, rq, ubuf, map_len); + if (ret < 0) + goto unmap_rq; + bytes_read += ret; + ubuf += ret; } - /* - * bio is the err-ptr - */ - return PTR_ERR(bio); + rq->buffer = rq->data = NULL; + return 0; +unmap_rq: + blk_rq_unmap_user(rq); + return ret; } EXPORT_SYMBOL(blk_rq_map_user); @@ -2404,7 +2484,7 @@ EXPORT_SYMBOL(blk_rq_map_user); * unmapping. */ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq, - struct sg_iovec *iov, int iov_count) + struct sg_iovec *iov, int iov_count, unsigned int len) { struct bio *bio; @@ -2418,10 +2498,15 @@ int blk_rq_map_user_iov(request_queue_t *q, struct request *rq, if (IS_ERR(bio)) return PTR_ERR(bio); - rq->bio = rq->biotail = bio; + if (bio->bi_size != len) { + bio_endio(bio, bio->bi_size, 0); + bio_unmap_user(bio); + return -EINVAL; + } + + bio_get(bio); blk_rq_bio_prep(q, rq, bio); rq->buffer = rq->data = NULL; - rq->data_len = bio->bi_size; return 0; } @@ -2429,23 +2514,26 @@ EXPORT_SYMBOL(blk_rq_map_user_iov); /** * blk_rq_unmap_user - unmap a request with user data - * @bio: bio to be unmapped - * @ulen: length of user buffer + * @rq: rq to be unmapped * * Description: - * Unmap a bio previously mapped by blk_rq_map_user(). + * Unmap a rq previously mapped by blk_rq_map_user(). + * rq->bio must be set to the original head of the request. */ -int blk_rq_unmap_user(struct bio *bio, unsigned int ulen) +int blk_rq_unmap_user(struct request *rq) { - int ret = 0; + struct bio *bio, *mapped_bio; - if (bio) { - if (bio_flagged(bio, BIO_USER_MAPPED)) - bio_unmap_user(bio); + while ((bio = rq->bio)) { + if (bio_flagged(bio, BIO_BOUNCED)) + mapped_bio = bio->bi_private; else - ret = bio_uncopy_user(bio); - } + mapped_bio = bio; + __blk_rq_unmap_user(mapped_bio); + rq->bio = bio->bi_next; + bio_put(bio); + } return 0; } @@ -2476,11 +2564,8 @@ int blk_rq_map_kern(request_queue_t *q, struct request *rq, void *kbuf, if (rq_data_dir(rq) == WRITE) bio->bi_rw |= (1 << BIO_RW); - rq->bio = rq->biotail = bio; blk_rq_bio_prep(q, rq, bio); - rq->buffer = rq->data = NULL; - rq->data_len = len; return 0; } @@ -3495,6 +3580,7 @@ void blk_rq_bio_prep(request_queue_t *q, struct request *rq, struct bio *bio) rq->hard_cur_sectors = rq->current_nr_sectors; rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio); rq->buffer = bio_data(bio); + rq->data_len = bio->bi_size; rq->bio = rq->biotail = bio; } diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index e55a75621437..5493c2fbbab1 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -226,7 +226,6 @@ static int sg_io(struct file *file, request_queue_t *q, unsigned long start_time; int writing = 0, ret = 0; struct request *rq; - struct bio *bio; char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char cmd[BLK_MAX_CDB]; @@ -258,30 +257,6 @@ static int sg_io(struct file *file, request_queue_t *q, if (!rq) return -ENOMEM; - if (hdr->iovec_count) { - const int size = sizeof(struct sg_iovec) * hdr->iovec_count; - struct sg_iovec *iov; - - iov = kmalloc(size, GFP_KERNEL); - if (!iov) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(iov, hdr->dxferp, size)) { - kfree(iov); - ret = -EFAULT; - goto out; - } - - ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count); - kfree(iov); - } else if (hdr->dxfer_len) - ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); - - if (ret) - goto out; - /* * fill in request structure */ @@ -294,7 +269,6 @@ static int sg_io(struct file *file, request_queue_t *q, rq->sense_len = 0; rq->cmd_type = REQ_TYPE_BLOCK_PC; - bio = rq->bio; /* * bounce this after holding a reference to the original bio, it's @@ -309,6 +283,31 @@ static int sg_io(struct file *file, request_queue_t *q, if (!rq->timeout) rq->timeout = BLK_DEFAULT_TIMEOUT; + if (hdr->iovec_count) { + const int size = sizeof(struct sg_iovec) * hdr->iovec_count; + struct sg_iovec *iov; + + iov = kmalloc(size, GFP_KERNEL); + if (!iov) { + ret = -ENOMEM; + goto out; + } + + if (copy_from_user(iov, hdr->dxferp, size)) { + kfree(iov); + ret = -EFAULT; + goto out; + } + + ret = blk_rq_map_user_iov(q, rq, iov, hdr->iovec_count, + hdr->dxfer_len); + kfree(iov); + } else if (hdr->dxfer_len) + ret = blk_rq_map_user(q, rq, hdr->dxferp, hdr->dxfer_len); + + if (ret) + goto out; + rq->retries = 0; start_time = jiffies; @@ -339,7 +338,7 @@ static int sg_io(struct file *file, request_queue_t *q, hdr->sb_len_wr = len; } - if (blk_rq_unmap_user(bio, hdr->dxfer_len)) + if (blk_rq_unmap_user(rq)) ret = -EFAULT; /* may not have succeeded, but output values written to control diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 7ea0f48f8fa6..2df5cf4ec743 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2133,16 +2133,14 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, rq->timeout = 60 * HZ; bio = rq->bio; - if (rq->bio) - blk_queue_bounce(q, &rq->bio); - if (blk_execute_rq(q, cdi->disk, rq, 0)) { struct request_sense *s = rq->sense; ret = -EIO; cdi->last_sense = s->sense_key; } - if (blk_rq_unmap_user(bio, len)) + rq->bio = bio; + if (blk_rq_unmap_user(rq)) ret = -EFAULT; if (ret) diff --git a/fs/bio.c b/fs/bio.c index d91cfbf7ebc4..aa4d09bd4e71 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -560,10 +560,8 @@ struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr, break; } - if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) { - ret = -EINVAL; + if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) break; - } len -= bytes; } @@ -750,7 +748,6 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev, int write_to_vm) { struct bio *bio; - int len = 0, i; bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm); @@ -765,18 +762,7 @@ struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev, */ bio_get(bio); - for (i = 0; i < iov_count; i++) - len += iov[i].iov_len; - - if (bio->bi_size == len) - return bio; - - /* - * don't support partial mappings - */ - bio_endio(bio, bio->bi_size, 0); - bio_unmap_user(bio); - return ERR_PTR(-EINVAL); + return bio; } static void __bio_unmap_user(struct bio *bio) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 7bfcde2d5578..e1c7286165ff 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -678,10 +678,11 @@ extern void __blk_stop_queue(request_queue_t *q); extern void blk_run_queue(request_queue_t *); extern void blk_start_queueing(request_queue_t *); extern void blk_queue_activity_fn(request_queue_t *, activity_fn *, void *); -extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned int); -extern int blk_rq_unmap_user(struct bio *, unsigned int); +extern int blk_rq_map_user(request_queue_t *, struct request *, void __user *, unsigned long); +extern int blk_rq_unmap_user(struct request *); extern int blk_rq_map_kern(request_queue_t *, struct request *, void *, unsigned int, gfp_t); -extern int blk_rq_map_user_iov(request_queue_t *, struct request *, struct sg_iovec *, int); +extern int blk_rq_map_user_iov(request_queue_t *, struct request *, + struct sg_iovec *, int, unsigned int); extern int blk_execute_rq(request_queue_t *, struct gendisk *, struct request *, int); extern void blk_execute_rq_nowait(request_queue_t *, struct gendisk *, -- cgit v1.2.3 From 87598a2bd4c4ed19b91ef163f76297f305007304 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 13 Nov 2006 20:23:52 +0100 Subject: mmc: remove kernel_thread() Replace kernel_thread() with kthread_run()/kthread_stop(). Signed-off-by: Christoph Hellwig Signed-off-by: Pierre Ossman --- drivers/mmc/mmc_queue.c | 41 ++++++++++++++--------------------------- drivers/mmc/mmc_queue.h | 3 +-- 2 files changed, 15 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 4ccdd82b680f..4e6a534e91d0 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c @@ -10,13 +10,13 @@ */ #include #include +#include #include #include #include "mmc_queue.h" -#define MMC_QUEUE_EXIT (1 << 0) -#define MMC_QUEUE_SUSPENDED (1 << 1) +#define MMC_QUEUE_SUSPENDED (1 << 0) /* * Prepare a MMC request. Essentially, this means passing the @@ -59,7 +59,6 @@ static int mmc_queue_thread(void *d) { struct mmc_queue *mq = d; struct request_queue *q = mq->queue; - DECLARE_WAITQUEUE(wait, current); /* * Set iothread to ensure that we aren't put to sleep by @@ -67,12 +66,7 @@ static int mmc_queue_thread(void *d) */ current->flags |= PF_MEMALLOC|PF_NOFREEZE; - daemonize("mmcqd"); - - complete(&mq->thread_complete); - down(&mq->thread_sem); - add_wait_queue(&mq->thread_wq, &wait); do { struct request *req = NULL; @@ -84,7 +78,7 @@ static int mmc_queue_thread(void *d) spin_unlock_irq(q->queue_lock); if (!req) { - if (mq->flags & MMC_QUEUE_EXIT) + if (kthread_should_stop()) break; up(&mq->thread_sem); schedule(); @@ -95,10 +89,8 @@ static int mmc_queue_thread(void *d) mq->issue_fn(mq, req); } while (1); - remove_wait_queue(&mq->thread_wq, &wait); up(&mq->thread_sem); - complete_and_exit(&mq->thread_complete, 0); return 0; } @@ -113,7 +105,7 @@ static void mmc_request(request_queue_t *q) struct mmc_queue *mq = q->queuedata; if (!mq->req) - wake_up(&mq->thread_wq); + wake_up_process(mq->thread); } /** @@ -152,36 +144,31 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; - goto cleanup; + goto cleanup_queue; } - init_completion(&mq->thread_complete); - init_waitqueue_head(&mq->thread_wq); init_MUTEX(&mq->thread_sem); - ret = kernel_thread(mmc_queue_thread, mq, CLONE_KERNEL); - if (ret >= 0) { - wait_for_completion(&mq->thread_complete); - init_completion(&mq->thread_complete); - ret = 0; - goto out; + mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd"); + if (IS_ERR(mq->thread)) { + ret = PTR_ERR(mq->thread); + goto free_sg; } - cleanup: + return 0; + + free_sg: kfree(mq->sg); mq->sg = NULL; - + cleanup_queue: blk_cleanup_queue(mq->queue); - out: return ret; } EXPORT_SYMBOL(mmc_init_queue); void mmc_cleanup_queue(struct mmc_queue *mq) { - mq->flags |= MMC_QUEUE_EXIT; - wake_up(&mq->thread_wq); - wait_for_completion(&mq->thread_complete); + kthread_stop(mq->thread); kfree(mq->sg); mq->sg = NULL; diff --git a/drivers/mmc/mmc_queue.h b/drivers/mmc/mmc_queue.h index 7182d2f69b4e..c9f139e764f6 100644 --- a/drivers/mmc/mmc_queue.h +++ b/drivers/mmc/mmc_queue.h @@ -6,8 +6,7 @@ struct task_struct; struct mmc_queue { struct mmc_card *card; - struct completion thread_complete; - wait_queue_head_t thread_wq; + struct task_struct *thread; struct semaphore thread_sem; unsigned int flags; struct request *req; -- cgit v1.2.3 From ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdae Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 12 Nov 2006 17:55:30 -0800 Subject: mmc: constify mmc_host_ops vectors Now that mmc_host_ops can be constified, update the various drivers to constify those method tables and shrink the writable data segment. Signed-off-by: David Brownell Signed-off-by: Pierre Ossman --- drivers/mmc/at91_mci.c | 2 +- drivers/mmc/au1xmmc.c | 2 +- drivers/mmc/imxmmc.c | 2 +- drivers/mmc/mmci.c | 2 +- drivers/mmc/omap.c | 2 +- drivers/mmc/pxamci.c | 2 +- drivers/mmc/sdhci.c | 2 +- drivers/mmc/wbsd.c | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/at91_mci.c b/drivers/mmc/at91_mci.c index 494b23fb0a01..6495cd8a9306 100644 --- a/drivers/mmc/at91_mci.c +++ b/drivers/mmc/at91_mci.c @@ -793,7 +793,7 @@ int at91_mci_get_ro(struct mmc_host *mmc) return read_only; } -static struct mmc_host_ops at91_mci_ops = { +static const struct mmc_host_ops at91_mci_ops = { .request = at91_mci_request, .set_ios = at91_mci_set_ios, .get_ro = at91_mci_get_ro, diff --git a/drivers/mmc/au1xmmc.c b/drivers/mmc/au1xmmc.c index 53ffcbb14a97..447fba5825fd 100644 --- a/drivers/mmc/au1xmmc.c +++ b/drivers/mmc/au1xmmc.c @@ -875,7 +875,7 @@ static void au1xmmc_init_dma(struct au1xmmc_host *host) host->rx_chan = rxchan; } -struct mmc_host_ops au1xmmc_ops = { +struct const mmc_host_ops au1xmmc_ops = { .request = au1xmmc_request, .set_ios = au1xmmc_set_ios, }; diff --git a/drivers/mmc/imxmmc.c b/drivers/mmc/imxmmc.c index 659d4a822cc5..06e7fcd19221 100644 --- a/drivers/mmc/imxmmc.c +++ b/drivers/mmc/imxmmc.c @@ -877,7 +877,7 @@ static void imxmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static struct mmc_host_ops imxmci_ops = { +static const struct mmc_host_ops imxmci_ops = { .request = imxmci_request, .set_ios = imxmci_set_ios, }; diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 828503c4ee62..e9b80e920266 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -443,7 +443,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } } -static struct mmc_host_ops mmci_ops = { +static const struct mmc_host_ops mmci_ops = { .request = mmci_request, .set_ios = mmci_set_ios, }; diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 762fa2895891..895d4879027d 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -960,7 +960,7 @@ static int mmc_omap_get_ro(struct mmc_host *mmc) return host->wp_pin && omap_get_gpio_datain(host->wp_pin); } -static struct mmc_host_ops mmc_omap_ops = { +static const struct mmc_host_ops mmc_omap_ops = { .request = mmc_omap_request, .set_ios = mmc_omap_set_ios, .get_ro = mmc_omap_get_ro, diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index a526698b8c91..471e9f4e0530 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -393,7 +393,7 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->clkrt, host->cmdat); } -static struct mmc_host_ops pxamci_ops = { +static const struct mmc_host_ops pxamci_ops = { .request = pxamci_request, .get_ro = pxamci_get_ro, .set_ios = pxamci_set_ios, diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 9a7d39b7cdbf..54990ed26770 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -784,7 +784,7 @@ static int sdhci_get_ro(struct mmc_host *mmc) return !(present & SDHCI_WRITE_PROTECT); } -static struct mmc_host_ops sdhci_ops = { +static const struct mmc_host_ops sdhci_ops = { .request = sdhci_request, .set_ios = sdhci_set_ios, .get_ro = sdhci_get_ro, diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index ced309b37a8f..7e040eb18ff2 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1021,7 +1021,7 @@ static int wbsd_get_ro(struct mmc_host *mmc) return csr & WBSD_WRPT; } -static struct mmc_host_ops wbsd_ops = { +static const struct mmc_host_ops wbsd_ops = { .request = wbsd_request, .set_ios = wbsd_set_ios, .get_ro = wbsd_get_ro, -- cgit v1.2.3 From 89783b1e44d3a6fc63be911468e09494ebbba3e3 Mon Sep 17 00:00:00 2001 From: "Juha Yrjola juha.yrjola" Date: Sat, 11 Nov 2006 23:36:01 +0100 Subject: Replace base with virt_base and phys_base This patch is part of Juha Yrjola's earlier patch to replace base with virt_base and phys_base Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Juha Yrjola solidboot.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 895d4879027d..4bf7df8c4275 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -60,8 +60,9 @@ struct mmc_omap_host { unsigned char id; /* 16xx chips have 2 MMC blocks */ struct clk * iclk; struct clk * fclk; - struct resource *res; - void __iomem *base; + struct resource *mem_res; + void __iomem *virt_base; + unsigned int phys_base; int irq; unsigned char bus_mode; unsigned char hw_bus_mode; @@ -354,9 +355,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) host->data->bytes_xfered += n; if (write) { - __raw_writesw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); } else { - __raw_readsw(host->base + OMAP_MMC_REG_DATA, host->buffer, n); + __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); } } @@ -581,7 +582,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) int dst_port = 0; int sync_dev = 0; - data_addr = io_v2p((u32) host->base) + OMAP_MMC_REG_DATA; + data_addr = host->phys_base + OMAP_MMC_REG_DATA; frame = data->blksz; count = sg_dma_len(sg); @@ -1001,7 +1002,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->dma_timer.data = (unsigned long) host; host->id = pdev->id; - host->res = r; + host->mem_res = r; host->irq = irq; if (cpu_is_omap24xx()) { @@ -1032,7 +1033,8 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->dma_ch = -1; host->irq = pdev->resource[1].start; - host->base = (void __iomem*)IO_ADDRESS(r->start); + host->phys_base = host->mem_res->start; + host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); mmc->ops = &mmc_omap_ops; mmc->f_min = 400000; -- cgit v1.2.3 From 3342ee8bfa9c4453208766eb8ad61ef65241a091 Mon Sep 17 00:00:00 2001 From: "Juha Yrjola juha.yrjola" Date: Sat, 11 Nov 2006 23:36:52 +0100 Subject: Change OMAP_MMC_{READ,WRITE} macros to use the host pointer This patch is part of Juha Yrjola's earlier patch to change OMAP_MMC_{READ,WRITE} macros to use the host pointer Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Juha Yrjola solidboot.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 90 +++++++++++++++++++++++++++--------------------------- drivers/mmc/omap.h | 4 +-- 2 files changed, 47 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 4bf7df8c4275..efd14cf60f89 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -192,16 +192,16 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd) clk_enable(host->fclk); - OMAP_MMC_WRITE(host->base, CTO, 200); - OMAP_MMC_WRITE(host->base, ARGL, cmd->arg & 0xffff); - OMAP_MMC_WRITE(host->base, ARGH, cmd->arg >> 16); - OMAP_MMC_WRITE(host->base, IE, + OMAP_MMC_WRITE(host, CTO, 200); + OMAP_MMC_WRITE(host, ARGL, cmd->arg & 0xffff); + OMAP_MMC_WRITE(host, ARGH, cmd->arg >> 16); + OMAP_MMC_WRITE(host, IE, OMAP_MMC_STAT_A_EMPTY | OMAP_MMC_STAT_A_FULL | OMAP_MMC_STAT_CMD_CRC | OMAP_MMC_STAT_CMD_TOUT | OMAP_MMC_STAT_DATA_CRC | OMAP_MMC_STAT_DATA_TOUT | OMAP_MMC_STAT_END_OF_CMD | OMAP_MMC_STAT_CARD_ERR | OMAP_MMC_STAT_END_OF_DATA); - OMAP_MMC_WRITE(host->base, CMD, cmdreg); + OMAP_MMC_WRITE(host, CMD, cmdreg); } static void @@ -297,22 +297,22 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) if (cmd->flags & MMC_RSP_136) { /* response type 2 */ cmd->resp[3] = - OMAP_MMC_READ(host->base, RSP0) | - (OMAP_MMC_READ(host->base, RSP1) << 16); + OMAP_MMC_READ(host, RSP0) | + (OMAP_MMC_READ(host, RSP1) << 16); cmd->resp[2] = - OMAP_MMC_READ(host->base, RSP2) | - (OMAP_MMC_READ(host->base, RSP3) << 16); + OMAP_MMC_READ(host, RSP2) | + (OMAP_MMC_READ(host, RSP3) << 16); cmd->resp[1] = - OMAP_MMC_READ(host->base, RSP4) | - (OMAP_MMC_READ(host->base, RSP5) << 16); + OMAP_MMC_READ(host, RSP4) | + (OMAP_MMC_READ(host, RSP5) << 16); cmd->resp[0] = - OMAP_MMC_READ(host->base, RSP6) | - (OMAP_MMC_READ(host->base, RSP7) << 16); + OMAP_MMC_READ(host, RSP6) | + (OMAP_MMC_READ(host, RSP7) << 16); } else { /* response types 1, 1b, 3, 4, 5, 6 */ cmd->resp[0] = - OMAP_MMC_READ(host->base, RSP6) | - (OMAP_MMC_READ(host->base, RSP7) << 16); + OMAP_MMC_READ(host, RSP6) | + (OMAP_MMC_READ(host, RSP7) << 16); } } @@ -387,11 +387,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) int transfer_error; if (host->cmd == NULL && host->data == NULL) { - status = OMAP_MMC_READ(host->base, STAT); + status = OMAP_MMC_READ(host, STAT); dev_info(mmc_dev(host->mmc),"spurious irq 0x%04x\n", status); if (status != 0) { - OMAP_MMC_WRITE(host->base, STAT, status); - OMAP_MMC_WRITE(host->base, IE, 0); + OMAP_MMC_WRITE(host, STAT, status); + OMAP_MMC_WRITE(host, IE, 0); } return IRQ_HANDLED; } @@ -400,8 +400,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) end_transfer = 0; transfer_error = 0; - while ((status = OMAP_MMC_READ(host->base, STAT)) != 0) { - OMAP_MMC_WRITE(host->base, STAT, status); + while ((status = OMAP_MMC_READ(host, STAT)) != 0) { + OMAP_MMC_WRITE(host, STAT, status); #ifdef CONFIG_MMC_DEBUG dev_dbg(mmc_dev(host->mmc), "MMC IRQ %04x (CMD %d): ", status, host->cmd != NULL ? host->cmd->opcode : -1); @@ -471,8 +471,8 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) if (status & OMAP_MMC_STAT_CARD_ERR) { if (host->cmd && host->cmd->opcode == MMC_STOP_TRANSMISSION) { - u32 response = OMAP_MMC_READ(host->base, RSP6) - | (OMAP_MMC_READ(host->base, RSP7) << 16); + u32 response = OMAP_MMC_READ(host, RSP6) + | (OMAP_MMC_READ(host, RSP7) << 16); /* STOP sometimes sets must-ignore bits */ if (!(response & (R1_CC_ERROR | R1_ILLEGAL_COMMAND @@ -644,7 +644,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) if (unlikely(count > 0xffff)) BUG(); - OMAP_MMC_WRITE(host->base, BUF, buf); + OMAP_MMC_WRITE(host, BUF, buf); omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S16, frame, count, OMAP_DMA_SYNC_FRAME, sync_dev, 0); @@ -729,11 +729,11 @@ static inline void set_cmd_timeout(struct mmc_omap_host *host, struct mmc_reques { u16 reg; - reg = OMAP_MMC_READ(host->base, SDIO); + reg = OMAP_MMC_READ(host, SDIO); reg &= ~(1 << 5); - OMAP_MMC_WRITE(host->base, SDIO, reg); + OMAP_MMC_WRITE(host, SDIO, reg); /* Set maximum timeout */ - OMAP_MMC_WRITE(host->base, CTO, 0xff); + OMAP_MMC_WRITE(host, CTO, 0xff); } static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_request *req) @@ -747,14 +747,14 @@ static inline void set_data_timeout(struct mmc_omap_host *host, struct mmc_reque timeout = req->data->timeout_clks + req->data->timeout_ns / 500; /* Check if we need to use timeout multiplier register */ - reg = OMAP_MMC_READ(host->base, SDIO); + reg = OMAP_MMC_READ(host, SDIO); if (timeout > 0xffff) { reg |= (1 << 5); timeout /= 1024; } else reg &= ~(1 << 5); - OMAP_MMC_WRITE(host->base, SDIO, reg); - OMAP_MMC_WRITE(host->base, DTO, timeout); + OMAP_MMC_WRITE(host, SDIO, reg); + OMAP_MMC_WRITE(host, DTO, timeout); } static void @@ -766,9 +766,9 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) host->data = data; if (data == NULL) { - OMAP_MMC_WRITE(host->base, BLEN, 0); - OMAP_MMC_WRITE(host->base, NBLK, 0); - OMAP_MMC_WRITE(host->base, BUF, 0); + OMAP_MMC_WRITE(host, BLEN, 0); + OMAP_MMC_WRITE(host, NBLK, 0); + OMAP_MMC_WRITE(host, BUF, 0); host->dma_in_use = 0; set_cmd_timeout(host, req); return; @@ -777,8 +777,8 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) block_size = data->blksz; - OMAP_MMC_WRITE(host->base, NBLK, data->blocks - 1); - OMAP_MMC_WRITE(host->base, BLEN, block_size - 1); + OMAP_MMC_WRITE(host, NBLK, data->blocks - 1); + OMAP_MMC_WRITE(host, BLEN, block_size - 1); set_data_timeout(host, req); /* cope with calling layer confusion; it issues "single @@ -820,7 +820,7 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) /* Revert to PIO? */ if (!use_dma) { - OMAP_MMC_WRITE(host->base, BUF, 0x1f1f); + OMAP_MMC_WRITE(host, BUF, 0x1f1f); host->total_bytes_left = data->blocks * block_size; host->sg_len = sg_len; mmc_omap_sg_to_buf(host); @@ -872,8 +872,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on) /* GPIO 4 of TPS65010 sends SD_EN signal */ tps65010_set_gpio_out_value(GPIO4, HIGH); else if (cpu_is_omap24xx()) { - u16 reg = OMAP_MMC_READ(host->base, CON); - OMAP_MMC_WRITE(host->base, CON, reg | (1 << 11)); + u16 reg = OMAP_MMC_READ(host, CON); + OMAP_MMC_WRITE(host, CON, reg | (1 << 11)); } else if (host->power_pin >= 0) omap_set_gpio_dataout(host->power_pin, 1); @@ -885,8 +885,8 @@ static void mmc_omap_power(struct mmc_omap_host *host, int on) else if (machine_is_omap_h3()) tps65010_set_gpio_out_value(GPIO4, LOW); else if (cpu_is_omap24xx()) { - u16 reg = OMAP_MMC_READ(host->base, CON); - OMAP_MMC_WRITE(host->base, CON, reg & ~(1 << 11)); + u16 reg = OMAP_MMC_READ(host, CON); + OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11)); } else if (host->power_pin >= 0) omap_set_gpio_dataout(host->power_pin, 0); @@ -942,14 +942,14 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * which results in the while loop below getting stuck. * Writing to the CON register twice seems to do the trick. */ for (i = 0; i < 2; i++) - OMAP_MMC_WRITE(host->base, CON, dsor); + OMAP_MMC_WRITE(host, CON, dsor); if (ios->power_mode == MMC_POWER_UP) { /* Send clock cycles, poll completion */ - OMAP_MMC_WRITE(host->base, IE, 0); - OMAP_MMC_WRITE(host->base, STAT, 0xffff); - OMAP_MMC_WRITE(host->base, CMD, 1<<7); - while (0 == (OMAP_MMC_READ(host->base, STAT) & 1)); - OMAP_MMC_WRITE(host->base, STAT, 1); + OMAP_MMC_WRITE(host, IE, 0); + OMAP_MMC_WRITE(host, STAT, 0xffff); + OMAP_MMC_WRITE(host, CMD, 1<<7); + while (0 == (OMAP_MMC_READ(host, STAT) & 1)); + OMAP_MMC_WRITE(host, STAT, 1); } clk_disable(host->fclk); } diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h index c954d355a5e3..11bf2ee32d6d 100644 --- a/drivers/mmc/omap.h +++ b/drivers/mmc/omap.h @@ -41,8 +41,8 @@ #define OMAP_MMC_STAT_CARD_BUSY (1 << 2) #define OMAP_MMC_STAT_END_OF_CMD (1 << 0) -#define OMAP_MMC_READ(base, reg) __raw_readw((base) + OMAP_MMC_REG_##reg) -#define OMAP_MMC_WRITE(base, reg, val) __raw_writew((val), (base) + OMAP_MMC_REG_##reg) +#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) +#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) /* * Command types -- cgit v1.2.3 From 0551f4df35694c7f89e00da461d7bee9769f016f Mon Sep 17 00:00:00 2001 From: "Juha Yrjola juha.yrjola" Date: Sat, 11 Nov 2006 23:38:36 +0100 Subject: Move register definitions away from the header file This patch is part of Juha Yrjola's earlier patch to move register definitions away from the header file and the header file is removed. Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Juha Yrjola solidboot.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++- drivers/mmc/omap.h | 55 ------------------------------------------------------ 2 files changed, 51 insertions(+), 56 deletions(-) delete mode 100644 drivers/mmc/omap.h (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index efd14cf60f89..827753c18579 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -38,7 +38,57 @@ #include #include -#include "omap.h" +#define OMAP_MMC_REG_CMD 0x00 +#define OMAP_MMC_REG_ARGL 0x04 +#define OMAP_MMC_REG_ARGH 0x08 +#define OMAP_MMC_REG_CON 0x0c +#define OMAP_MMC_REG_STAT 0x10 +#define OMAP_MMC_REG_IE 0x14 +#define OMAP_MMC_REG_CTO 0x18 +#define OMAP_MMC_REG_DTO 0x1c +#define OMAP_MMC_REG_DATA 0x20 +#define OMAP_MMC_REG_BLEN 0x24 +#define OMAP_MMC_REG_NBLK 0x28 +#define OMAP_MMC_REG_BUF 0x2c +#define OMAP_MMC_REG_SDIO 0x34 +#define OMAP_MMC_REG_REV 0x3c +#define OMAP_MMC_REG_RSP0 0x40 +#define OMAP_MMC_REG_RSP1 0x44 +#define OMAP_MMC_REG_RSP2 0x48 +#define OMAP_MMC_REG_RSP3 0x4c +#define OMAP_MMC_REG_RSP4 0x50 +#define OMAP_MMC_REG_RSP5 0x54 +#define OMAP_MMC_REG_RSP6 0x58 +#define OMAP_MMC_REG_RSP7 0x5c +#define OMAP_MMC_REG_IOSR 0x60 +#define OMAP_MMC_REG_SYSC 0x64 +#define OMAP_MMC_REG_SYSS 0x68 + +#define OMAP_MMC_STAT_CARD_ERR (1 << 14) +#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) +#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) +#define OMAP_MMC_STAT_A_EMPTY (1 << 11) +#define OMAP_MMC_STAT_A_FULL (1 << 10) +#define OMAP_MMC_STAT_CMD_CRC (1 << 8) +#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) +#define OMAP_MMC_STAT_DATA_CRC (1 << 6) +#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) +#define OMAP_MMC_STAT_END_BUSY (1 << 4) +#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) +#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) +#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) + +#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) +#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) + +/* + * Command types + */ +#define OMAP_MMC_CMDTYPE_BC 0 +#define OMAP_MMC_CMDTYPE_BCR 1 +#define OMAP_MMC_CMDTYPE_AC 2 +#define OMAP_MMC_CMDTYPE_ADTC 3 + #define DRIVER_NAME "mmci-omap" #define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h deleted file mode 100644 index 11bf2ee32d6d..000000000000 --- a/drivers/mmc/omap.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef DRIVERS_MEDIA_MMC_OMAP_H -#define DRIVERS_MEDIA_MMC_OMAP_H - -#define OMAP_MMC_REG_CMD 0x00 -#define OMAP_MMC_REG_ARGL 0x04 -#define OMAP_MMC_REG_ARGH 0x08 -#define OMAP_MMC_REG_CON 0x0c -#define OMAP_MMC_REG_STAT 0x10 -#define OMAP_MMC_REG_IE 0x14 -#define OMAP_MMC_REG_CTO 0x18 -#define OMAP_MMC_REG_DTO 0x1c -#define OMAP_MMC_REG_DATA 0x20 -#define OMAP_MMC_REG_BLEN 0x24 -#define OMAP_MMC_REG_NBLK 0x28 -#define OMAP_MMC_REG_BUF 0x2c -#define OMAP_MMC_REG_SDIO 0x34 -#define OMAP_MMC_REG_REV 0x3c -#define OMAP_MMC_REG_RSP0 0x40 -#define OMAP_MMC_REG_RSP1 0x44 -#define OMAP_MMC_REG_RSP2 0x48 -#define OMAP_MMC_REG_RSP3 0x4c -#define OMAP_MMC_REG_RSP4 0x50 -#define OMAP_MMC_REG_RSP5 0x54 -#define OMAP_MMC_REG_RSP6 0x58 -#define OMAP_MMC_REG_RSP7 0x5c -#define OMAP_MMC_REG_IOSR 0x60 -#define OMAP_MMC_REG_SYSC 0x64 -#define OMAP_MMC_REG_SYSS 0x68 - -#define OMAP_MMC_STAT_CARD_ERR (1 << 14) -#define OMAP_MMC_STAT_CARD_IRQ (1 << 13) -#define OMAP_MMC_STAT_OCR_BUSY (1 << 12) -#define OMAP_MMC_STAT_A_EMPTY (1 << 11) -#define OMAP_MMC_STAT_A_FULL (1 << 10) -#define OMAP_MMC_STAT_CMD_CRC (1 << 8) -#define OMAP_MMC_STAT_CMD_TOUT (1 << 7) -#define OMAP_MMC_STAT_DATA_CRC (1 << 6) -#define OMAP_MMC_STAT_DATA_TOUT (1 << 5) -#define OMAP_MMC_STAT_END_BUSY (1 << 4) -#define OMAP_MMC_STAT_END_OF_DATA (1 << 3) -#define OMAP_MMC_STAT_CARD_BUSY (1 << 2) -#define OMAP_MMC_STAT_END_OF_CMD (1 << 0) - -#define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) -#define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) - -/* - * Command types - */ -#define OMAP_MMC_CMDTYPE_BC 0 -#define OMAP_MMC_CMDTYPE_BCR 1 -#define OMAP_MMC_CMDTYPE_AC 2 -#define OMAP_MMC_CMDTYPE_ADTC 3 - -#endif -- cgit v1.2.3 From 81ca70343f4d85637ac19b529dbcccd1db69a41d Mon Sep 17 00:00:00 2001 From: "Juha Yrjola juha.yrjola" Date: Sat, 11 Nov 2006 23:39:20 +0100 Subject: Platform device error handling cleanup This patch is part of Juha Yrjola's earlier patch to add platform device error handling and a BUG_ON to verify if host == NULL Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Juha Yrjola solidboot.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 100 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 827753c18579..d46fd02ba0dc 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -1022,25 +1022,29 @@ static int __init mmc_omap_probe(struct platform_device *pdev) struct omap_mmc_conf *minfo = pdev->dev.platform_data; struct mmc_host *mmc; struct mmc_omap_host *host = NULL; - struct resource *r; + struct resource *res; int ret = 0; int irq; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + if (minfo == NULL) { + dev_err(&pdev->dev, "platform data missing\n"); + return -ENXIO; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!r || irq < 0) + if (res == NULL || irq < 0) return -ENXIO; - r = request_mem_region(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1, - pdev->name); - if (!r) + res = request_mem_region(res->start, res->end - res->start + 1, + pdev->name); + if (res == NULL) return -EBUSY; mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev); - if (!mmc) { + if (mmc == NULL) { ret = -ENOMEM; - goto out; + goto err_free_mem_region; } host = mmc_priv(mmc); @@ -1052,13 +1056,13 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->dma_timer.data = (unsigned long) host; host->id = pdev->id; - host->mem_res = r; + host->mem_res = res; host->irq = irq; if (cpu_is_omap24xx()) { host->iclk = clk_get(&pdev->dev, "mmc_ick"); if (IS_ERR(host->iclk)) - goto out; + goto err_free_mmc_host; clk_enable(host->iclk); } @@ -1069,7 +1073,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) if (IS_ERR(host->fclk)) { ret = PTR_ERR(host->fclk); - goto out; + goto err_free_iclk; } /* REVISIT: @@ -1082,7 +1086,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) host->use_dma = 1; host->dma_ch = -1; - host->irq = pdev->resource[1].start; + host->irq = irq; host->phys_base = host->mem_res->start; host->virt_base = (void __iomem *) IO_ADDRESS(host->phys_base); @@ -1108,20 +1112,18 @@ static int __init mmc_omap_probe(struct platform_device *pdev) if ((ret = omap_request_gpio(host->power_pin)) != 0) { dev_err(mmc_dev(host->mmc), "Unable to get GPIO pin for MMC power\n"); - goto out; + goto err_free_fclk; } omap_set_gpio_direction(host->power_pin, 0); } ret = request_irq(host->irq, mmc_omap_irq, 0, DRIVER_NAME, host); if (ret) - goto out; + goto err_free_power_gpio; host->dev = &pdev->dev; platform_set_drvdata(pdev, host); - mmc_add_host(mmc); - if (host->switch_pin >= 0) { INIT_WORK(&host->switch_work, mmc_omap_switch_handler, host); init_timer(&host->switch_timer); @@ -1159,10 +1161,11 @@ static int __init mmc_omap_probe(struct platform_device *pdev) schedule_work(&host->switch_work); } -no_switch: + mmc_add_host(mmc); + return 0; -out: +no_switch: /* FIXME: Free other resources too. */ if (host) { if (host->iclk && !IS_ERR(host->iclk)) @@ -1171,6 +1174,20 @@ out: clk_put(host->fclk); mmc_free_host(host->mmc); } +err_free_power_gpio: + if (host->power_pin >= 0) + omap_free_gpio(host->power_pin); +err_free_fclk: + clk_put(host->fclk); +err_free_iclk: + if (host->iclk != NULL) { + clk_disable(host->iclk); + clk_put(host->iclk); + } +err_free_mmc_host: + mmc_free_host(host->mmc); +err_free_mem_region: + release_mem_region(res->start, res->end - res->start + 1); return ret; } @@ -1180,30 +1197,31 @@ static int mmc_omap_remove(struct platform_device *pdev) platform_set_drvdata(pdev, NULL); - if (host) { - mmc_remove_host(host->mmc); - free_irq(host->irq, host); - - if (host->power_pin >= 0) - omap_free_gpio(host->power_pin); - if (host->switch_pin >= 0) { - device_remove_file(&pdev->dev, &dev_attr_enable_poll); - device_remove_file(&pdev->dev, &dev_attr_cover_switch); - free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); - omap_free_gpio(host->switch_pin); - host->switch_pin = -1; - del_timer_sync(&host->switch_timer); - flush_scheduled_work(); - } - if (host->iclk && !IS_ERR(host->iclk)) - clk_put(host->iclk); - if (host->fclk && !IS_ERR(host->fclk)) - clk_put(host->fclk); - mmc_free_host(host->mmc); + BUG_ON(host == NULL); + + mmc_remove_host(host->mmc); + free_irq(host->irq, host); + + if (host->power_pin >= 0) + omap_free_gpio(host->power_pin); + if (host->switch_pin >= 0) { + device_remove_file(&pdev->dev, &dev_attr_enable_poll); + device_remove_file(&pdev->dev, &dev_attr_cover_switch); + free_irq(OMAP_GPIO_IRQ(host->switch_pin), host); + omap_free_gpio(host->switch_pin); + host->switch_pin = -1; + del_timer_sync(&host->switch_timer); + flush_scheduled_work(); } + if (host->iclk && !IS_ERR(host->iclk)) + clk_put(host->iclk); + if (host->fclk && !IS_ERR(host->fclk)) + clk_put(host->fclk); release_mem_region(pdev->resource[0].start, - pdev->resource[0].end - pdev->resource[0].start + 1); + pdev->resource[0].end - pdev->resource[0].start + 1); + + mmc_free_host(host->mmc); return 0; } -- cgit v1.2.3 From f4204fdf05e70cdbff1f657e3ed78eddd3d6267f Mon Sep 17 00:00:00 2001 From: Tony Lindgren tony Date: Sat, 11 Nov 2006 23:41:54 +0100 Subject: Add MMC_CAP_{MULTIWRITE,BYTEBLOCK} flags This patch is part of Tony Lindgren's earlier patch to add MMC_CAP_{MULTIWRITE,BYTEBLOCK} flags in omap.c Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Tony Lindgren atomide.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index d46fd02ba0dc..4e46750e8d0a 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -1094,7 +1094,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) mmc->f_min = 400000; mmc->f_max = 24000000; mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; - mmc->caps = MMC_CAP_BYTEBLOCK; + mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; if (minfo->wire4) mmc->caps |= MMC_CAP_4_BIT_DATA; -- cgit v1.2.3 From c5cb431d27237937e1b04a888bf2f8863f06fa2d Mon Sep 17 00:00:00 2001 From: "Juha Yrjola juha.yrjola" Date: Sat, 11 Nov 2006 23:42:39 +0100 Subject: Make general code cleanups This patch is part of Juha Yrjola's and Komal Shah's earlier patch to make general code cleanups Signed-off-by: Carlos Eduardo Aguiar indt.org.br> Signed-off-by: Juha Yrjola solidboot.com> Signed-off-by: Komal Shah yahoo.com> Signed-off-by: Pierre Ossman --- drivers/mmc/omap.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 4e46750e8d0a..f8830c527603 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -581,12 +581,6 @@ static void mmc_omap_switch_timer(unsigned long arg) schedule_work(&host->switch_work); } -/* FIXME: Handle card insertion and removal properly. Maybe use a mask - * for MMC state? */ -static void mmc_omap_switch_callback(unsigned long data, u8 mmc_mask) -{ -} - static void mmc_omap_switch_handler(void *data) { struct mmc_omap_host *host = (struct mmc_omap_host *) data; @@ -824,7 +818,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) return; } - block_size = data->blksz; OMAP_MMC_WRITE(host, NBLK, data->blocks - 1); @@ -896,7 +889,6 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) static void innovator_fpga_socket_power(int on) { #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) - if (on) { fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), OMAP1510_FPGA_POWER); @@ -978,7 +970,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_UP: case MMC_POWER_ON: mmc_omap_power(host, 1); - dsor |= 1<<11; + dsor |= 1 << 11; break; } @@ -997,8 +989,8 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Send clock cycles, poll completion */ OMAP_MMC_WRITE(host, IE, 0); OMAP_MMC_WRITE(host, STAT, 0xffff); - OMAP_MMC_WRITE(host, CMD, 1<<7); - while (0 == (OMAP_MMC_READ(host, STAT) & 1)); + OMAP_MMC_WRITE(host, CMD, 1 << 7); + while ((OMAP_MMC_READ(host, STAT) & 1) == 0); OMAP_MMC_WRITE(host, STAT, 1); } clk_disable(host->fclk); @@ -1093,7 +1085,7 @@ static int __init mmc_omap_probe(struct platform_device *pdev) mmc->ops = &mmc_omap_ops; mmc->f_min = 400000; mmc->f_max = 24000000; - mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34; + mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; mmc->caps = MMC_CAP_MULTIWRITE | MMC_CAP_BYTEBLOCK; if (minfo->wire4) -- cgit v1.2.3 From 9c9c26188ff9fa5f44ba5a00e01b54b539f83d1d Mon Sep 17 00:00:00 2001 From: Marcin Juszkiewicz Date: Thu, 16 Nov 2006 22:39:10 +0100 Subject: trivial change for mmc/Kconfig: MMC_PXA does not mean only PXA255 PXA MMC driver supports not only PXA255 but also PXA250 and newer ones Signed-off-by: Marcin Juszkiewicz Signed-off-by: Pierre Ossman --- drivers/mmc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index ea41852ec8cd..f4f8ccaf5455 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -40,7 +40,7 @@ config MMC_ARMMMCI If unsure, say N. config MMC_PXA - tristate "Intel PXA255 Multimedia Card Interface support" + tristate "Intel PXA25x/26x/27x Multimedia Card Interface support" depends on ARCH_PXA && MMC help This selects the Intel(R) PXA(R) Multimedia card Interface. -- cgit v1.2.3 From bce40a36de574376f41f1ff3c4d212a7da2a3c90 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sat, 21 Oct 2006 12:35:02 +0200 Subject: [PATCH] mmc: Add support for mmc v4 high speed mode This adds support for the high-speed modes defined by mmc v4 (assuming the host controller is up to it). On a TI sdhci controller, it improves read speed from 1.3MBps to 2.3MBps. The TI controller can only go up to 24MHz, but everything helps. Another person has taken this basic patch and used it on a Nokia 770 to get a bigger boost because that controller can run at 48MHZ. Signed-off-by: Philip Langdale Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 121 ++++++++++++++++++++++++++++++++++++++++++- include/linux/mmc/card.h | 8 +++ include/linux/mmc/protocol.h | 47 +++++++++++++++-- 3 files changed, 171 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 766bc54406e5..2d5b93000dee 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -4,6 +4,7 @@ * Copyright (C) 2003-2004 Russell King, All Rights Reserved. * SD support Copyright (C) 2004 Ian Molton, All Rights Reserved. * SD support Copyright (C) 2005 Pierre Ossman, All Rights Reserved. + * MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -953,6 +954,114 @@ static void mmc_read_csds(struct mmc_host *host) } } +static void mmc_process_ext_csds(struct mmc_host *host) +{ + int err; + struct mmc_card *card; + + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + + struct scatterlist sg; + + /* + * As the ext_csd is so large and mostly unused, we don't store the + * raw block in mmc_card. + */ + u8 *ext_csd; + ext_csd = kmalloc(512, GFP_KERNEL); + if (!ext_csd) { + printk("%s: could not allocate a buffer to receive the ext_csd." + "mmc v4 cards will be treated as v3.\n", + mmc_hostname(host)); + return; + } + + list_for_each_entry(card, &host->cards, node) { + if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) + continue; + if (mmc_card_sd(card)) + continue; + if (card->csd.mmca_vsn < CSD_SPEC_VER_4) + continue; + + err = mmc_select_card(host, card); + if (err != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = MMC_SEND_EXT_CSD; + cmd.arg = 0; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + memset(&data, 0, sizeof(struct mmc_data)); + + mmc_set_data_timeout(&data, card, 0); + + data.blksz = 512; + data.blocks = 1; + data.flags = MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + memset(&mrq, 0, sizeof(struct mmc_request)); + + mrq.cmd = &cmd; + mrq.data = &data; + + sg_init_one(&sg, ext_csd, 512); + + mmc_wait_for_req(host, &mrq); + + if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + switch (ext_csd[EXT_CSD_CARD_TYPE]) { + case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + break; + case EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 26000000; + break; + default: + /* MMC v4 spec says this cannot happen */ + printk("%s: card is mmc v4 but doesn't support " + "any high-speed modes.\n", + mmc_hostname(card->host)); + mmc_card_set_bad(card); + continue; + } + + /* Activate highspeed support. */ + cmd.opcode = MMC_SWITCH; + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_HS_TIMING << 16) | + (1 << 8) | + EXT_CSD_CMD_SET_NORMAL; + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + + err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); + if (err != MMC_ERR_NONE) { + printk("%s: failed to switch card to mmc v4 " + "high-speed mode.\n", + mmc_hostname(card->host)); + continue; + } + + mmc_card_set_highspeed(card); + } + + kfree(ext_csd); + + mmc_deselect_cards(host); +} + static void mmc_read_scrs(struct mmc_host *host) { int err; @@ -1031,8 +1140,14 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host) unsigned int max_dtr = host->f_max; list_for_each_entry(card, &host->cards, node) - if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr) - max_dtr = card->csd.max_dtr; + if (!mmc_card_dead(card)) { + if (mmc_card_highspeed(card)) { + if (max_dtr > card->ext_csd.hs_max_dtr) + max_dtr = card->ext_csd.hs_max_dtr; + } else if (max_dtr > card->csd.max_dtr) { + max_dtr = card->csd.max_dtr; + } + } pr_debug("%s: selected %d.%03dMHz transfer rate\n", mmc_hostname(host), @@ -1152,6 +1267,8 @@ static void mmc_setup(struct mmc_host *host) if (host->mode == MMC_MODE_SD) mmc_read_scrs(host); + else + mmc_process_ext_csds(host); } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 991a37382a22..ce25256f80d5 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -39,6 +39,10 @@ struct mmc_csd { write_misalign:1; }; +struct mmc_ext_csd { + unsigned int hs_max_dtr; +}; + struct sd_scr { unsigned char sda_vsn; unsigned char bus_widths; @@ -62,11 +66,13 @@ struct mmc_card { #define MMC_STATE_BAD (1<<2) /* unrecognised device */ #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ #define MMC_STATE_READONLY (1<<4) /* card is read-only */ +#define MMC_STATE_HIGHSPEED (1<<5) /* card is in mmc4 highspeed mode */ u32 raw_cid[4]; /* raw card CID */ u32 raw_csd[4]; /* raw card CSD */ u32 raw_scr[2]; /* raw card SCR */ struct mmc_cid cid; /* card identification */ struct mmc_csd csd; /* card specific */ + struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ struct sd_scr scr; /* extra SD information */ }; @@ -75,12 +81,14 @@ struct mmc_card { #define mmc_card_bad(c) ((c)->state & MMC_STATE_BAD) #define mmc_card_sd(c) ((c)->state & MMC_STATE_SDCARD) #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY) +#define mmc_card_highspeed(c) ((c)->state & MMC_STATE_HIGHSPEED) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_dead(c) ((c)->state |= MMC_STATE_DEAD) #define mmc_card_set_bad(c) ((c)->state |= MMC_STATE_BAD) #define mmc_card_set_sd(c) ((c)->state |= MMC_STATE_SDCARD) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) +#define mmc_card_set_highspeed(c) ((c)->state |= MMC_STATE_HIGHSPEED) #define mmc_card_name(c) ((c)->cid.prod_name) #define mmc_card_id(c) ((c)->dev.bus_id) diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h index 08dec8d9e703..311b6547f561 100644 --- a/include/linux/mmc/protocol.h +++ b/include/linux/mmc/protocol.h @@ -25,14 +25,16 @@ #ifndef MMC_MMC_PROTOCOL_H #define MMC_MMC_PROTOCOL_H -/* Standard MMC commands (3.1) type argument response */ +/* Standard MMC commands (4.1) type argument response */ /* class 1 */ #define MMC_GO_IDLE_STATE 0 /* bc */ #define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */ #define MMC_ALL_SEND_CID 2 /* bcr R2 */ #define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */ #define MMC_SET_DSR 4 /* bc [31:16] RCA */ +#define MMC_SWITCH 6 /* ac [31:0] See below R1b */ #define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */ +#define MMC_SEND_EXT_CSD 8 /* adtc R1 */ #define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */ #define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */ #define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */ @@ -87,6 +89,17 @@ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */ +/* + * MMC_SWITCH argument format: + * + * [31:26] Always 0 + * [25:24] Access Mode + * [23:16] Location of target Byte in EXT_CSD + * [15:08] Value Byte + * [07:03] Always 0 + * [02:00] Command Set + */ + /* MMC status in R1 Type @@ -230,13 +243,41 @@ struct _mmc_csd { #define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */ #define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */ -#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 */ +#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */ +#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */ #define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */ #define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */ #define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */ -#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 */ +#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */ +#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */ + +/* + * EXT_CSD fields + */ + +#define EXT_CSD_HS_TIMING 185 /* R/W */ +#define EXT_CSD_CARD_TYPE 196 /* RO */ + +/* + * EXT_CSD field definitions + */ + +#define EXT_CSD_CMD_SET_NORMAL (1<<0) +#define EXT_CSD_CMD_SET_SECURE (1<<1) +#define EXT_CSD_CMD_SET_CPSECURE (1<<2) + +#define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ +#define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ + +/* + * MMC_SWITCH access modes + */ +#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */ +#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */ +#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ +#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ /* * SD bus widths -- cgit v1.2.3 From e45a1bd20fa5b920901879e85cdf5eda21f78d7c Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 29 Oct 2006 10:14:19 +0100 Subject: mmc: Add support for mmc v4 wide-bus modes This change adds support for the mmc4 4-bit wide-bus mode. The mmc4 spec defines 8-bit and 4-bit transfer modes. As we do not support any 8-bit hardware, this patch only adds support for the 4-bit mode, but it can easily be built upon when the time comes. The 4-bit mode is electrically compatible with SD's 4-bit mode but the procedure for turning it on is different. This patch implements only the essential parts of the procedure as defined by the spec. Two additional steps are recommended but not compulsory. I am documenting them here so that there's a record. 1) A bus-test mechanism is implemented using dedicated mmc commands which allow for testing the functionality of the data bus at the electrical level. This is pretty paranoid and they way the commands work is not compatible with the mmc subsystem (they don't set valid CRC values). 2) MMC v4 cards can indicate they would like to draw more than the default amount of current in wide-bus modes. We currently will never switch the card into a higher draw mode. Supposedly, allowing the card to draw more current will let it perform better, but the specs seem to indicate that the card will function correctly without the mode change. Empirical testing supports this interpretation. Signed-off-by: Philip Langdale Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 51 ++++++++++++++++++++++++++++++++------------ include/linux/mmc/protocol.h | 5 +++++ 2 files changed, 42 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 2d5b93000dee..1593a6a632cf 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -397,23 +397,23 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card) return err; /* - * Default bus width is 1 bit. - */ - host->ios.bus_width = MMC_BUS_WIDTH_1; - - /* - * We can only change the bus width of the selected - * card so therefore we have to put the handling + * We can only change the bus width of SD cards when + * they are selected so we have to put the handling * here. + * + * The card is in 1 bit mode by default so + * we only need to change if it supports the + * wider version. */ - if (host->caps & MMC_CAP_4_BIT_DATA) { + if (mmc_card_sd(card) && + (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + /* - * The card is in 1 bit mode by default so - * we only need to change if it supports the - * wider version. - */ - if (mmc_card_sd(card) && - (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { + * Default bus width is 1 bit. + */ + host->ios.bus_width = MMC_BUS_WIDTH_1; + + if (host->caps & MMC_CAP_4_BIT_DATA) { struct mmc_command cmd; cmd.opcode = SD_APP_SET_BUS_WIDTH; cmd.arg = SD_BUS_WIDTH_4; @@ -1055,6 +1055,29 @@ static void mmc_process_ext_csds(struct mmc_host *host) } mmc_card_set_highspeed(card); + + /* Check for host support for wide-bus modes. */ + if (!(host->caps & MMC_CAP_4_BIT_DATA)) { + continue; + } + + /* Activate 4-bit support. */ + cmd.opcode = MMC_SWITCH; + cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | + (EXT_CSD_BUS_WIDTH << 16) | + (EXT_CSD_BUS_WIDTH_4 << 8) | + EXT_CSD_CMD_SET_NORMAL; + cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; + + err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); + if (err != MMC_ERR_NONE) { + printk("%s: failed to switch card to " + "mmc v4 4-bit bus mode.\n", + mmc_hostname(card->host)); + continue; + } + + host->ios.bus_width = MMC_BUS_WIDTH_4; } kfree(ext_csd); diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h index 311b6547f561..45c51fd85786 100644 --- a/include/linux/mmc/protocol.h +++ b/include/linux/mmc/protocol.h @@ -256,6 +256,7 @@ struct _mmc_csd { * EXT_CSD fields */ +#define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ #define EXT_CSD_CARD_TYPE 196 /* RO */ @@ -270,6 +271,10 @@ struct _mmc_csd { #define EXT_CSD_CARD_TYPE_26 (1<<0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_52 (1<<1) /* Card can run at 52MHz */ +#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ +#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ +#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ + /* * MMC_SWITCH access modes */ -- cgit v1.2.3 From 73778120c4088a0a7b59c4c378904f7a230b4820 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Sun, 22 Oct 2006 22:13:10 +0200 Subject: mmc: Fix mmc_delay() function Several fixes for mmc_delay(): * Repair if-clause that was supposed to detect sub-hz delays. * Change yield() to cond_resched() as yield() no longer has the semantics we desire. * mmc_delay() is used to guarantee protocol delays, so we cannot return early (i.e. use _interruptable). Based on patch by Amol Lad. Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 1593a6a632cf..82b7643c1654 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -454,11 +454,11 @@ static void mmc_deselect_cards(struct mmc_host *host) static inline void mmc_delay(unsigned int ms) { - if (ms < HZ / 1000) { - yield(); + if (ms < 1000 / HZ) { + cond_resched(); mdelay(ms); } else { - msleep_interruptible (ms); + msleep(ms); } } -- cgit v1.2.3 From 7ccd266e676a3f0c6f8f897f58b684cac3dd1650 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 8 Nov 2006 23:03:10 +0100 Subject: mmc: Support for high speed SD cards Modern SD cards support a clock speed of 50 MHz. Make sure we test for this capability and do the song and dance required to activate it. Activating high speed support actually modifies the TRAN_SPEED field of the CSD. But as the spec says that the cards must report 50 MHz, we might as well skip re-reading the CSD. Signed-off-by: Pierre Ossman --- drivers/mmc/mmc.c | 122 +++++++++++++++++++++++++++++++++++++++++-- include/linux/mmc/card.h | 7 ++- include/linux/mmc/protocol.h | 22 ++++++++ 3 files changed, 146 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 82b7643c1654..9d190022a490 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1157,6 +1157,116 @@ static void mmc_read_scrs(struct mmc_host *host) mmc_deselect_cards(host); } +static void mmc_read_switch_caps(struct mmc_host *host) +{ + int err; + struct mmc_card *card; + struct mmc_request mrq; + struct mmc_command cmd; + struct mmc_data data; + unsigned char *status; + struct scatterlist sg; + + status = kmalloc(64, GFP_KERNEL); + if (!status) { + printk(KERN_WARNING "%s: Unable to allocate buffer for " + "reading switch capabilities.\n", + mmc_hostname(host)); + return; + } + + list_for_each_entry(card, &host->cards, node) { + if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) + continue; + if (!mmc_card_sd(card)) + continue; + if (card->scr.sda_vsn < SCR_SPEC_VER_1) + continue; + + err = mmc_select_card(host, card); + if (err != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_SWITCH; + cmd.arg = 0x00FFFFF1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + memset(&data, 0, sizeof(struct mmc_data)); + + mmc_set_data_timeout(&data, card, 0); + + data.blksz = 64; + data.blocks = 1; + data.flags = MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + memset(&mrq, 0, sizeof(struct mmc_request)); + + mrq.cmd = &cmd; + mrq.data = &data; + + sg_init_one(&sg, status, 64); + + mmc_wait_for_req(host, &mrq); + + if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + if (status[13] & 0x02) + card->sw_caps.hs_max_dtr = 50000000; + + memset(&cmd, 0, sizeof(struct mmc_command)); + + cmd.opcode = SD_SWITCH; + cmd.arg = 0x80FFFFF1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + memset(&data, 0, sizeof(struct mmc_data)); + + mmc_set_data_timeout(&data, card, 0); + + data.blksz = 64; + data.blocks = 1; + data.flags = MMC_DATA_READ; + data.sg = &sg; + data.sg_len = 1; + + memset(&mrq, 0, sizeof(struct mmc_request)); + + mrq.cmd = &cmd; + mrq.data = &data; + + sg_init_one(&sg, status, 64); + + mmc_wait_for_req(host, &mrq); + + if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) { + mmc_card_set_dead(card); + continue; + } + + if ((status[16] & 0xF) != 1) { + printk(KERN_WARNING "%s: Problem switching card " + "into high-speed mode!\n", + mmc_hostname(host)); + continue; + } + + mmc_card_set_highspeed(card); + } + + kfree(status); + + mmc_deselect_cards(host); +} + static unsigned int mmc_calculate_clock(struct mmc_host *host) { struct mmc_card *card; @@ -1164,9 +1274,12 @@ static unsigned int mmc_calculate_clock(struct mmc_host *host) list_for_each_entry(card, &host->cards, node) if (!mmc_card_dead(card)) { - if (mmc_card_highspeed(card)) { + if (mmc_card_highspeed(card) && mmc_card_sd(card)) { + if (max_dtr > card->sw_caps.hs_max_dtr) + max_dtr = card->sw_caps.hs_max_dtr; + } else if (mmc_card_highspeed(card) && !mmc_card_sd(card)) { if (max_dtr > card->ext_csd.hs_max_dtr) - max_dtr = card->ext_csd.hs_max_dtr; + max_dtr = card->ext_csd.hs_max_dtr; } else if (max_dtr > card->csd.max_dtr) { max_dtr = card->csd.max_dtr; } @@ -1288,9 +1401,10 @@ static void mmc_setup(struct mmc_host *host) mmc_read_csds(host); - if (host->mode == MMC_MODE_SD) + if (host->mode == MMC_MODE_SD) { mmc_read_scrs(host); - else + mmc_read_switch_caps(host); + } else mmc_process_ext_csds(host); } diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index ce25256f80d5..d0e6a5497614 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -50,6 +50,10 @@ struct sd_scr { #define SD_SCR_BUS_WIDTH_4 (1<<2) }; +struct sd_switch_caps { + unsigned int hs_max_dtr; +}; + struct mmc_host; /* @@ -66,7 +70,7 @@ struct mmc_card { #define MMC_STATE_BAD (1<<2) /* unrecognised device */ #define MMC_STATE_SDCARD (1<<3) /* is an SD card */ #define MMC_STATE_READONLY (1<<4) /* card is read-only */ -#define MMC_STATE_HIGHSPEED (1<<5) /* card is in mmc4 highspeed mode */ +#define MMC_STATE_HIGHSPEED (1<<5) /* card is in high speed mode */ u32 raw_cid[4]; /* raw card CID */ u32 raw_csd[4]; /* raw card CSD */ u32 raw_scr[2]; /* raw card SCR */ @@ -74,6 +78,7 @@ struct mmc_card { struct mmc_csd csd; /* card specific */ struct mmc_ext_csd ext_csd; /* mmc v4 extended card specific */ struct sd_scr scr; /* extra SD information */ + struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ }; #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT) diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h index 45c51fd85786..2dce60c43f4b 100644 --- a/include/linux/mmc/protocol.h +++ b/include/linux/mmc/protocol.h @@ -82,6 +82,7 @@ /* class 8 */ /* This is basically the same command as for MMC with some quirks. */ #define SD_SEND_RELATIVE_ADDR 3 /* bcr R6 */ +#define SD_SWITCH 6 /* adtc [31:0] See below R1 */ /* Application commands */ #define SD_APP_SET_BUS_WIDTH 6 /* ac [1:0] bus width R1 */ @@ -100,6 +101,19 @@ * [02:00] Command Set */ +/* + * SD_SWITCH argument format: + * + * [31] Check (0) or switch (1) + * [30:24] Reserved (0) + * [23:20] Function group 6 + * [19:16] Function group 5 + * [15:12] Function group 4 + * [11:8] Function group 3 + * [7:4] Function group 2 + * [3:0] Function group 1 + */ + /* MMC status in R1 Type @@ -284,6 +298,14 @@ struct _mmc_csd { #define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */ #define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */ +/* + * SCR field definitions + */ + +#define SCR_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.01 */ +#define SCR_SPEC_VER_1 1 /* Implements system specification 1.10 */ +#define SCR_SPEC_VER_2 2 /* Implements system specification 2.00 */ + /* * SD bus widths */ -- cgit v1.2.3 From 077df884835ebf2b5db16aacd9a24691d89902a0 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Wed, 8 Nov 2006 23:06:35 +0100 Subject: mmc: sdhci high speed support The SDHCI spec implies that is is incorrect to set a clock frequency above 25 MHz without setting the high speed bit. Signed-off-by: Pierre Ossman --- drivers/mmc/sdhci.c | 15 +++++++++++++++ drivers/mmc/sdhci.h | 2 ++ 2 files changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 54990ed26770..cd98117632d3 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -616,6 +616,7 @@ static void sdhci_finish_command(struct sdhci_host *host) static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) { int div; + u8 ctrl; u16 clk; unsigned long timeout; @@ -624,6 +625,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); + ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); + if (clock > 25000000) + ctrl |= SDHCI_CTRL_HISPD; + else + ctrl &= ~SDHCI_CTRL_HISPD; + writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); + if (clock == 0) goto out; @@ -1291,6 +1299,13 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) else if (caps & SDHCI_CAN_VDD_180) mmc->ocr_avail |= MMC_VDD_17_18|MMC_VDD_18_19; + if ((host->max_clk > 25000000) && !(caps & SDHCI_CAN_DO_HISPD)) { + printk(KERN_ERR "%s: Controller reports > 25 MHz base clock," + " but no high speed support.\n", + host->slot_descr); + mmc->f_max = 25000000; + } + if (mmc->ocr_avail == 0) { printk(KERN_ERR "%s: Hardware doesn't report any " "support voltages.\n", host->slot_descr); diff --git a/drivers/mmc/sdhci.h b/drivers/mmc/sdhci.h index 72a67937afe0..f9d1a0a6f03a 100644 --- a/drivers/mmc/sdhci.h +++ b/drivers/mmc/sdhci.h @@ -71,6 +71,7 @@ #define SDHCI_HOST_CONTROL 0x28 #define SDHCI_CTRL_LED 0x01 #define SDHCI_CTRL_4BITBUS 0x02 +#define SDHCI_CTRL_HISPD 0x04 #define SDHCI_POWER_CONTROL 0x29 #define SDHCI_POWER_ON 0x01 @@ -138,6 +139,7 @@ #define SDHCI_CLOCK_BASE_SHIFT 8 #define SDHCI_MAX_BLOCK_MASK 0x00030000 #define SDHCI_MAX_BLOCK_SHIFT 16 +#define SDHCI_CAN_DO_HISPD 0x00200000 #define SDHCI_CAN_DO_DMA 0x00400000 #define SDHCI_CAN_VDD_330 0x01000000 #define SDHCI_CAN_VDD_300 0x02000000 -- cgit v1.2.3 From 89b4e133afea9fce333054b94d89953583a55c19 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 14 Nov 2006 22:08:16 +0100 Subject: mmc: Flush block queue when removing card After mmc_block's remove function has exited, we must not touch the card structure in any way. This means we not only must remove the gendisk, we must also flush out any remaning requests already queued up. We previously removed the disk, but didn't flush it, causing oops:es when removing a card in the middle of a transfer. Signed-off-by: Pierre Ossman --- drivers/mmc/mmc_block.c | 8 +++----- drivers/mmc/mmc_queue.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f9027c8db792..5025abebfc82 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -83,7 +83,6 @@ static void mmc_blk_put(struct mmc_blk_data *md) md->usage--; if (md->usage == 0) { put_disk(md->disk); - mmc_cleanup_queue(&md->queue); kfree(md); } mutex_unlock(&open_lock); @@ -553,12 +552,11 @@ static void mmc_blk_remove(struct mmc_card *card) if (md) { int devidx; + /* Stop new requests from getting into the queue */ del_gendisk(md->disk); - /* - * I think this is needed. - */ - md->disk->queue = NULL; + /* Then flush out any already in there */ + mmc_cleanup_queue(&md->queue); devidx = md->disk->first_minor >> MMC_SHIFT; __clear_bit(devidx, dev_use); diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 4e6a534e91d0..5fa72ccb4feb 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c @@ -103,6 +103,19 @@ static int mmc_queue_thread(void *d) static void mmc_request(request_queue_t *q) { struct mmc_queue *mq = q->queuedata; + struct request *req; + int ret; + + if (!mq) { + printk(KERN_ERR "MMC: killing requests for dead queue\n"); + while ((req = elv_next_request(q)) != NULL) { + do { + ret = end_that_request_chunk(req, 0, + req->current_nr_sectors << 9); + } while (ret); + } + return; + } if (!mq->req) wake_up_process(mq->thread); @@ -168,6 +181,15 @@ EXPORT_SYMBOL(mmc_init_queue); void mmc_cleanup_queue(struct mmc_queue *mq) { + request_queue_t *q = mq->queue; + unsigned long flags; + + /* Mark that we should start throwing out stragglers */ + spin_lock_irqsave(q->queue_lock, flags); + q->queuedata = NULL; + spin_unlock_irqrestore(q->queue_lock, flags); + + /* Then terminate our worker thread */ kthread_stop(mq->thread); kfree(mq->sg); -- cgit v1.2.3 From 8b7feff881b7e9f065ddd718a6841121207c3c19 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Tue, 14 Nov 2006 22:13:13 +0100 Subject: mmc: correct request error handling We need to jump to the part of just flushing the request when we cannot claim the bus. Sending commands to a bus we do not own will give unpredictable results. Signed-off-by: Pierre Ossman --- drivers/mmc/mmc_block.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index 5025abebfc82..87713572293f 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -224,10 +224,10 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_blk_data *md = mq->data; struct mmc_card *card = md->queue.card; struct mmc_blk_request brq; - int ret; + int ret = 1; if (mmc_card_claim_host(card)) - goto cmd_err; + goto flush_queue; do { struct mmc_command cmd; @@ -344,8 +344,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) return 1; cmd_err: - ret = 1; - /* * If this is an SD card and we're writing, we can first * mark the known good sectors as ok. @@ -379,6 +377,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) mmc_card_release_host(card); +flush_queue: spin_lock_irq(&md->lock); while (ret) { ret = end_that_request_chunk(req, 0, -- cgit v1.2.3 From 437052516779fea608261a50682b124315f48f01 Mon Sep 17 00:00:00 2001 From: "inaky@linux.intel.com" Date: Wed, 11 Oct 2006 20:05:58 -0700 Subject: usb/hub: allow hubs up to 31 children Current Wireless USB host hardware (Intel i1480 for example) allows up to 22 devices to connect, thus bringing up the max number of children in the WUSB Host Controller to 22 'fake' ports. Upcoming hardware might raise that limit. Makes almost no difference to go to 31, as the bit arrays are byte-aligned (plus an extra bit in general), so 22 bits fit in 4 bytes as 31 do. As well, the only other array that depends on USB_MAXCHILDREN is 'struct usb_hub->indicator'. By declaring it 'u8' instead of 'enum hub_led_mode', we reduce the size of each entry from 4 bytes (in i386) to 1, which will add as we when are doubling USB_MAXCHILDREN (with 16 the size of that array is 64 bytes, with 31 would be 128; by using u8 that goes down to 31 bytes). Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.h | 2 +- include/linux/usb.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 0f8e82a4d480..1b05994de4dc 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -229,7 +229,7 @@ struct usb_hub { unsigned resume_root_hub:1; unsigned has_indicators:1; - enum hub_led_mode indicator[USB_MAXCHILDREN]; + u8 indicator[USB_MAXCHILDREN]; struct work_struct leds; }; diff --git a/include/linux/usb.h b/include/linux/usb.h index 5482bfb3303d..e5cb1690975a 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -313,8 +313,13 @@ struct usb_bus { /* This is arbitrary. * From USB 2.0 spec Table 11-13, offset 7, a hub can * have up to 255 ports. The most yet reported is 10. + * + * Current Wireless USB host hardware (Intel i1480 for example) allows + * up to 22 devices to connect. Upcoming hardware might raise that + * limit. Because the arrays need to add a bit for hub status data, we + * do 31, so plus one evens out to four bytes. */ -#define USB_MAXCHILDREN (16) +#define USB_MAXCHILDREN (31) struct usb_tt; -- cgit v1.2.3 From 88fafff9d73c0a506c0b08e7cd637c89d8b604e1 Mon Sep 17 00:00:00 2001 From: "inaky@linux.intel.com" Date: Wed, 11 Oct 2006 20:05:59 -0700 Subject: usb hub: fix root hub code so it takes more than 15 devices per root hub Wireless USB Host Controllers accept a large number of devices per host, which shows up as a large number of ports in its root hub. When the number of ports in a hub device goes over 16, the activation of the hub fails with the cryptic message in klogd. hub 2-0:1.0: activate --> -22 Following this further, it was seen that: hub_probe() hub_configure() generates pipe number pseudo allocates buffer 'maxp' bytes in size using usb_maxpacket() The endpoint descriptor for a root hub interrupt endpoint is declared in drivers/usb/core/hcd.c:hs_rh_config_descriptor and declares it to be size two (supporting 15 devices max). hub_activate() usb_hcd_submit_urb() rh_urb_enqueue() urb->pipe is neither int nor ctl, so it errors out rh_queue_status() Returns -EINVAL because the buffer length is smaller than the minimum needed to report all the hub port bits as in accordance with USB2.0[11.12.3]. There has to be trunc((PORTS + 1 + 7) / 8) bytes of space at least. Alan Stern confirmed that the reason for reading maxpktsize and not the right amount is because some hubs are known to return more data and thus cause overflow. So this patch simply changes the code to make the interrupt endpoint's max packet size be at least the minimum required by USB_MAXCHILDREN (instead of a fixed magic number) and add documentation for that. This way we are always ahead of the limit. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 4 +++- drivers/usb/core/hub.c | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index afa2dd203329..10064af65d17 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = { 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ + /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) + * see hub.c:hub_configure() for details. */ + (USB_MAXCHILDREN + 1 + 7) / 8, 0x00, 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ }; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ba165aff9ea4..c91745def9e7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -759,7 +759,12 @@ static int hub_configure(struct usb_hub *hub, dev_dbg(hub_dev, "%sover-current condition exists\n", (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); - /* set up the interrupt endpoint */ + /* set up the interrupt endpoint + * We use the EP's maxpacket size instead of (PORTS+1+7)/8 + * bytes as USB2.0[11.12.3] says because some hubs are known + * to send more data (and thus cause overflow). For root hubs, + * maxpktsize is defined in hcd.c's fake endpoint descriptors + * to be big enough for at least USB_MAXCHILDREN ports. */ pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); -- cgit v1.2.3 From 6d8fc4d28deaf828606c19fb743fbe94aeab4caf Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Oct 2006 12:35:24 -0400 Subject: USB HID: Handle STALL on interrupt endpoint The USB HID driver doesn't include any code to handle a STALL on the interrupt endpoint. While this may be uncommon, it does happen sometimes. This patch (as805) adds a fix. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 39 ++++++++++++++++++++++++++------------- drivers/usb/input/hid.h | 1 + 2 files changed, 27 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 6d08a3bcc952..5de931cf4cfb 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -968,20 +968,29 @@ static void hid_retry_timeout(unsigned long _hid) hid_io_error(hid); } -/* Workqueue routine to reset the device */ +/* Workqueue routine to reset the device or clear a halt */ static void hid_reset(void *_hid) { struct hid_device *hid = (struct hid_device *) _hid; - int rc_lock, rc; - - dev_dbg(&hid->intf->dev, "resetting device\n"); - rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); - if (rc_lock >= 0) { - rc = usb_reset_composite_device(hid->dev, hid->intf); - if (rc_lock) - usb_unlock_device(hid->dev); + int rc_lock, rc = 0; + + if (test_bit(HID_CLEAR_HALT, &hid->iofl)) { + dev_dbg(&hid->intf->dev, "clear halt\n"); + rc = usb_clear_halt(hid->dev, hid->urbin->pipe); + clear_bit(HID_CLEAR_HALT, &hid->iofl); + hid_start_in(hid); + } + + else if (test_bit(HID_RESET_PENDING, &hid->iofl)) { + dev_dbg(&hid->intf->dev, "resetting device\n"); + rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); + if (rc_lock >= 0) { + rc = usb_reset_composite_device(hid->dev, hid->intf); + if (rc_lock) + usb_unlock_device(hid->dev); + } + clear_bit(HID_RESET_PENDING, &hid->iofl); } - clear_bit(HID_RESET_PENDING, &hid->iofl); switch (rc) { case 0: @@ -1023,9 +1032,8 @@ static void hid_io_error(struct hid_device *hid) /* Retries failed, so do a port reset */ if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { - if (schedule_work(&hid->reset_work)) - goto done; - clear_bit(HID_RESET_PENDING, &hid->iofl); + schedule_work(&hid->reset_work); + goto done; } } @@ -1049,6 +1057,11 @@ static void hid_irq_in(struct urb *urb) hid->retry_delay = 0; hid_input_report(HID_INPUT_REPORT, urb, 1); break; + case -EPIPE: /* stall */ + clear_bit(HID_IN_RUNNING, &hid->iofl); + set_bit(HID_CLEAR_HALT, &hid->iofl); + schedule_work(&hid->reset_work); + return; case -ECONNRESET: /* unlink */ case -ENOENT: case -ESHUTDOWN: /* unplug */ diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 0e76e6dcac37..2a9bf07944c0 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h @@ -385,6 +385,7 @@ struct hid_control_fifo { #define HID_IN_RUNNING 3 #define HID_RESET_PENDING 4 #define HID_SUSPENDED 5 +#define HID_CLEAR_HALT 6 struct hid_input { struct list_head list; -- cgit v1.2.3 From 93c8bf45e083b89dffe3a708363c15c1b220c723 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Oct 2006 16:41:51 -0400 Subject: USB core: don't match interface descriptors for vendor-specific devices This patch (as804) makes USB driver matching ignore the interface class, subclass, and protocol if the device class is Vendor Specific. Drivers can override this policy by specifying a Vendor ID as part of the match; then vendor-specific matches are allowed. Linus Walleij has reported a problem this patch fixes. When a particular mass-storage device is switched from mass-storage mode to Media Transfer Protocol, the interface class remains set to mass-storage and usb-storage binds to it erroneously, even though the device class changes to Vendor-Specific. This may cause a problem for some drivers until their match records can be updated to include Vendor IDs. But if it does, then those records were broken to begin with. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 113e484c763e..401d76f13419 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface, (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) return 0; + /* The interface class, subclass, and protocol should never be + * checked for a match if the device class is Vendor Specific, + * unless the match record specifies the Vendor ID. */ + if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + (id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS | + USB_DEVICE_ID_MATCH_INT_PROTOCOL))) + return 0; + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && (id->bInterfaceClass != intf->desc.bInterfaceClass)) return 0; @@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface, * most general; they let drivers bind to any interface on a * multiple-function device. Use the USB_INTERFACE_INFO * macro, or its siblings, to match class-per-interface style - * devices (as recorded in bDeviceClass). + * devices (as recorded in bInterfaceClass). + * + * Note that an entry created by USB_INTERFACE_INFO won't match + * any interface if the device class is set to Vendor-Specific. + * This is deliberate; according to the USB spec the meanings of + * the interface class/subclass/protocol for these devices are also + * vendor-specific, and hence matching against a standard product + * class wouldn't work anyway. If you really want to use an + * interface-based match for such a device, create a match record + * that also specifies the vendor ID. (Unforunately there isn't a + * standard macro for creating records like this.) * * Within those groups, remember that not all combinations are * meaningful. For example, don't give a product version range -- cgit v1.2.3 From b1878440d46a0dc357ed5c9687c534e20955e940 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 24 Oct 2006 12:02:31 -0400 Subject: USB: ohci-hcd: fix compiler warning This patch (as806) fixes a compiler warning when ohci-hcd is built with CONFIG_PM turned off. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 6995ea36f2e8..99357b99d133 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -50,6 +50,10 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd) static void dl_done_list (struct ohci_hcd *); static void finish_unlinks (struct ohci_hcd *, u16); +#ifdef CONFIG_PM +static int ohci_restart(struct ohci_hcd *ohci); +#endif + static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) __releases(ohci->lock) __acquires(ohci->lock) @@ -132,8 +136,6 @@ static inline struct ed *find_head (struct ed *ed) return ed; } -static int ohci_restart (struct ohci_hcd *ohci); - /* caller has locked the root hub */ static int ohci_rh_resume (struct ohci_hcd *ohci) __releases(ohci->lock) -- cgit v1.2.3 From 052ac01aeb84d8427ba8ac3d70991ac01b009b59 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 27 Oct 2006 10:33:11 -0400 Subject: USB: OHCI: disable RHSC inside interrupt handler This patch (as808b) moves the Root Hub Status Change interrupt-disable code in ohci-hcd back into the interrupt handler proper, to avoid the chance of adverse interactions with mediocre hardware implementations. It also deletes the root-hub status timer from within the interrupt-enable routine. There's no need to poll for status any more once interrupts are re-enabled. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 10 ++++++++++ drivers/usb/host/ohci-hub.c | 24 ++++++++---------------- 2 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index ea4714e557e4..a95275a401b1 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) ohci->next_statechange = jiffies + STATECHANGE_DELAY; ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, ®s->intrstatus); + + /* NOTE: Vendors didn't always make the same implementation + * choices for RHSC. Many followed the spec; RHSC triggers + * on an edge, like setting and maybe clearing a port status + * change bit. With others it's level-triggered, active + * until khubd clears all the port status change bits. We'll + * always disable it here and rely on polling until khubd + * re-enables it. + */ + ohci_writel(ohci, OHCI_INTR_RHSC, ®s->intrdisable); usb_hcd_poll_rh_status(hcd); } diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 99357b99d133..1e5ed3bb1a93 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); - ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_lock_irq(&ohci->lock); + if (!ohci->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + spin_unlock_irq(&ohci->lock); } #define OHCI_SCHED_ENABLES \ @@ -348,7 +352,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int i, changed = 0, length = 1; - int any_connected = 0, rhsc_enabled = 1; + int any_connected = 0; unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); @@ -389,19 +393,6 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) } } - /* NOTE: vendors didn't always make the same implementation - * choices for RHSC. Sometimes it triggers on an edge (like - * setting and maybe clearing a port status change bit); and - * it's level-triggered on other silicon, active until khubd - * clears all active port status change bits. If it's still - * set (level-triggered) we must disable it and rely on - * polling until khubd re-enables it. - */ - if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) { - ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable); - (void) ohci_readl (ohci, &ohci->regs->intrdisable); - rhsc_enabled = 0; - } hcd->poll_rh = 1; /* carry out appropriate state changes */ @@ -412,7 +403,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) * and RHSC is enabled */ if (!ohci->autostop) { if (any_connected) { - if (rhsc_enabled) + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) hcd->poll_rh = 0; } else { ohci->autostop = 1; -- cgit v1.2.3 From 5d7efe5b3768bf53df9b87380ea68baacf11f933 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 26 Oct 2006 21:06:24 +0200 Subject: USB: kmemdup() cleanup in drivers/usb/ replace open coded kmemdup() to save some screen space, and allow inlining/not inlining to be triggered by gcc. Signed-off-by: Eric Sesterhenn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/ueagle-atm.c | 10 +++------- drivers/usb/misc/emi26.c | 3 +-- drivers/usb/misc/emi62.c | 3 +-- drivers/usb/serial/ezusb.c | 3 +-- drivers/usb/serial/ipw.c | 3 +-- 5 files changed, 7 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index f6b9f7e1f716..c137c041f7a4 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -401,9 +401,8 @@ static int uea_send_modem_cmd(struct usb_device *usb, int ret = -ENOMEM; u8 *xfer_buff; - xfer_buff = kmalloc(size, GFP_KERNEL); + xfer_buff = kmemdup(buff, size, GFP_KERNEL); if (xfer_buff) { - memcpy(xfer_buff, buff, size); ret = usb_control_msg(usb, usb_sndctrlpipe(usb, 0), LOAD_INTERNAL, @@ -595,14 +594,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size) u8 *xfer_buff; int bytes_read; - xfer_buff = kmalloc(size, GFP_KERNEL); + xfer_buff = kmemdup(data, size, GFP_KERNEL); if (!xfer_buff) { uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); return ret; } - memcpy(xfer_buff, data, size); - ret = usb_bulk_msg(sc->usb_dev, usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE), xfer_buff, size, &bytes_read, BULK_TIMEOUT); @@ -765,12 +762,11 @@ static int uea_request(struct uea_softc *sc, u8 *xfer_buff; int ret = -ENOMEM; - xfer_buff = kmalloc(size, GFP_KERNEL); + xfer_buff = kmemdup(data, size, GFP_KERNEL); if (!xfer_buff) { uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); return ret; } - memcpy(xfer_buff, data, size); ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0), UCDC_SEND_ENCAPSULATED_COMMAND, diff --git a/drivers/usb/misc/emi26.c b/drivers/usb/misc/emi26.c index 1fd9cb85f4ca..5c0a26cbd128 100644 --- a/drivers/usb/misc/emi26.c +++ b/drivers/usb/misc/emi26.c @@ -53,13 +53,12 @@ static void __exit emi26_exit (void); static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) { int result; - unsigned char *buffer = kmalloc (length, GFP_KERNEL); + unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); if (!buffer) { err("emi26: kmalloc(%d) failed.", length); return -ENOMEM; } - memcpy (buffer, data, length); /* Note: usb_control_msg returns negative value on error or length of the * data that was written! */ result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300); diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index fe351371f274..23153eac0dfa 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -61,13 +61,12 @@ static void __exit emi62_exit (void); static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) { int result; - unsigned char *buffer = kmalloc (length, GFP_KERNEL); + unsigned char *buffer = kmemdup(data, length, GFP_KERNEL); if (!buffer) { err("emi62: kmalloc(%d) failed.", length); return -ENOMEM; } - memcpy (buffer, data, length); /* Note: usb_control_msg returns negative value on error or length of the * data that was written! */ result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300); diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index 5169c2d154ab..97ee718b1da2 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da return -ENODEV; } - transfer_buffer = kmalloc (length, GFP_KERNEL); + transfer_buffer = kmemdup(data, length, GFP_KERNEL); if (!transfer_buffer) { dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length); return -ENOMEM; } - memcpy (transfer_buffer, data, length); result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000); kfree (transfer_buffer); return result; diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 2a4bb66691ad..d3b9a351cef8 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp) dbg("%s", __FUNCTION__); - buf_flow_init = kmalloc(16, GFP_KERNEL); + buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL); if (!buf_flow_init) return -ENOMEM; - memcpy(buf_flow_init, buf_flow_static, 16); if (port->tty) port->tty->low_latency = 1; -- cgit v1.2.3 From 565402baee99096da4d79209e450fe42d379a0ca Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 27 Oct 2006 10:35:01 -0400 Subject: USB: OHCI: remove stale testing code from root-hub resume This patch (as811) removes some stale testing code from the root-hub resume routine in ohci-hcd. It also adds a spin_lock_irq() call that inadvertently got left out of an error pathway. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 1e5ed3bb1a93..dcf9eb601328 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -204,18 +204,6 @@ __acquires(ohci->lock) goto skip_resume; spin_unlock_irq (&ohci->lock); - temp = ohci->num_ports; - while (temp--) { - u32 stat = ohci_readl (ohci, - &ohci->regs->roothub.portstatus [temp]); - - /* force global, not selective, resume */ - if (!(stat & RH_PS_PSS)) - continue; - ohci_writel (ohci, RH_PS_POCI, - &ohci->regs->roothub.portstatus [temp]); - } - /* Some controllers (lucent erratum) need extra-long delays */ msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); @@ -223,6 +211,7 @@ __acquires(ohci->lock) temp &= OHCI_CTRL_HCFS; if (temp != OHCI_USB_RESUME) { ohci_err (ohci, "controller won't resume\n"); + spin_lock_irq(&ohci->lock); return -EBUSY; } -- cgit v1.2.3 From 377f13bf95b64cf5fb0fad0bf2b94106ad868562 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:45 -0300 Subject: USB: aircable: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/aircable.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 812275509137..8554c1a7b9fc 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -305,9 +305,7 @@ static int aircable_probe(struct usb_serial *serial, for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found our bulk out endpoint */ + if (usb_endpoint_is_bulk_out(endpoint)) { dbg("found bulk out on endpoint %d", i); ++num_bulk_out; } -- cgit v1.2.3 From 16f96376174bfbcb1b40734f83f5701161a5e63b Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:46 -0300 Subject: USB: appledisplay: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/appledisplay.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 6b23a1def9fe..ba30ca6a14aa 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -216,10 +216,7 @@ static int appledisplay_probe(struct usb_interface *iface, iface_desc = iface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = &iface_desc->endpoint[i].desc; - if (!int_in_endpointAddr && - (endpoint->bEndpointAddress & USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT)) { + if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) { /* we found an interrupt in endpoint */ int_in_endpointAddr = endpoint->bEndpointAddress; break; -- cgit v1.2.3 From b333d5bfd7d3791f91c678f3f5033c82b1e2b46f Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:47 -0300 Subject: USB: cdc_ether: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/cdc_ether.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/cdc_ether.c b/drivers/usb/net/cdc_ether.c index f6971b88349d..44a91547146e 100644 --- a/drivers/usb/net/cdc_ether.c +++ b/drivers/usb/net/cdc_ether.c @@ -200,8 +200,7 @@ next_desc: dev->status = &info->control->cur_altsetting->endpoint [0]; desc = &dev->status->desc; - if (desc->bmAttributes != USB_ENDPOINT_XFER_INT - || !(desc->bEndpointAddress & USB_DIR_IN) + if (!usb_endpoint_is_int_in(desc) || (le16_to_cpu(desc->wMaxPacketSize) < sizeof(struct usb_cdc_notification)) || !desc->bInterval) { -- cgit v1.2.3 From 45aea704d12d05f06b3f82974aa1438460f42398 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:48 -0300 Subject: USB: cdc-acm: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 9a9012fd284b..ec3438dc8ee5 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -892,7 +892,7 @@ skip_normal_probe: /* workaround for switched endpoints */ - if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) { + if (!usb_endpoint_dir_in(epread)) { /* descriptors are swapped */ struct usb_endpoint_descriptor *t; dev_dbg(&intf->dev,"The data interface has switched endpoints"); -- cgit v1.2.3 From 87ad46c94ec74f1750764c12744410ed524f9900 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:49 -0300 Subject: USB: devices: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 3538c2fdadfe..ea398e5d50af 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor ( ) { char dir, unit, *type; - unsigned interval, in, bandwidth = 1; + unsigned interval, bandwidth = 1; if (start > end) return start; - in = (desc->bEndpointAddress & USB_DIR_IN); - dir = in ? 'I' : 'O'; + + dir = usb_endpoint_dir_in(desc) ? 'I' : 'O'; + if (speed == USB_SPEED_HIGH) { switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { case 1 << 11: bandwidth = 2; break; @@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor ( break; case USB_ENDPOINT_XFER_BULK: type = "Bulk"; - if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */ interval = desc->bInterval; else interval = 0; -- cgit v1.2.3 From 2ae7745beac6de54a47ed19fe441f1d45aa96172 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:50 -0300 Subject: USB: ftdi-elan: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ftdi-elan.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 9b591b8b9369..0e8ee2dea881 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2633,10 +2633,7 @@ static int ftdi_elan_probe(struct usb_interface *interface, for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (!ftdi->bulk_in_endpointAddr && - ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) && ((endpoint->bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) - { + usb_endpoint_is_bulk_in(endpoint)) { buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); ftdi->bulk_in_size = buffer_size; ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; @@ -2649,10 +2646,7 @@ static int ftdi_elan_probe(struct usb_interface *interface, } } if (!ftdi->bulk_out_endpointAddr && - ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_OUT) && ((endpoint->bmAttributes & - USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) - { + usb_endpoint_is_bulk_out(endpoint)) { ftdi->bulk_out_endpointAddr = endpoint->bEndpointAddress; } -- cgit v1.2.3 From 0f12aa03972e797129c79a236d2872f2ee5d25b6 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:51 -0300 Subject: USB: hid-core: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5de931cf4cfb..2c12b04da111 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1998,7 +1998,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) interval = hid_mousepoll_interval; - if (endpoint->bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(endpoint)) { if (hid->urbin) continue; if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) -- cgit v1.2.3 From a7dc218b8f61d58fcf27ee5650e340d7baff74c4 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:52 -0300 Subject: USB: idmouse: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/idmouse.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index 8e6e195a22ba..c5fee0033a84 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -350,11 +350,7 @@ static int idmouse_probe(struct usb_interface *interface, /* set up the endpoint information - use only the first bulk-in endpoint */ endpoint = &iface_desc->endpoint[0].desc; - if (!dev->bulk_in_endpointAddr - && (endpoint->bEndpointAddress & USB_DIR_IN) - && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK)) { - + if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); dev->bulk_in_size = 0x200; /* works _much_ faster */ -- cgit v1.2.3 From 4f1f1ddd73d04e8d41c010934d81122d1a632e4e Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:53 -0300 Subject: USB: kobil_sct: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index ff03331e0bcf..8dd2afa2fca8 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial) for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { endpoint = &altsetting->endpoint[i]; - if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && - ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + if (usb_endpoint_is_int_out(&endpoint->desc)) { dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress); priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress; } - if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { + if (usb_endpoint_is_int_in(&endpoint->desc)) { dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress); priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress; } -- cgit v1.2.3 From 240661c55646401df64411e04ba5833c411c42bc Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:54 -0300 Subject: USB: legousbtower: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 27089497e717..f8611997bd77 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -898,14 +898,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { - dev->interrupt_in_endpoint = endpoint; - } - - if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && - ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { - dev->interrupt_out_endpoint = endpoint; + if (usb_endpoint_xfer_int(endpoint)) { + if (usb_endpoint_dir_in(endpoint)) + dev->interrupt_in_endpoint = endpoint; + else + dev->interrupt_out_endpoint = endpoint; } } if(dev->interrupt_in_endpoint == NULL) { -- cgit v1.2.3 From 66722a194ef96a09ac12d0fe2f9e206f86c29c9f Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:55 -0300 Subject: USB: onetouch: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/onetouch.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 3baf448e300d..3a158d58441f 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss) return -ENODEV; endpoint = &interface->endpoint[2].desc; - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) - return -ENODEV; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) + if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); -- cgit v1.2.3 From 8419404949488bba4504005c0d1180fb07bef740 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:56 -0300 Subject: USB: phidgetkit: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index abb4dcd811ac..0dc0d034cc9a 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -551,7 +551,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!usb_endpoint_dir_in(endpoint)) return -ENODEV; /* * bmAttributes -- cgit v1.2.3 From a742e5a7fc5b179e2482b85e875fc99192cead74 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:57 -0300 Subject: USB: phidgetmotorcontrol: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetmotorcontrol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 5c780cab92e0..7702a4f7b082 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -323,7 +323,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & 0x80)) + if (!usb_endpoint_dir_in(endpoint)) return -ENODEV; /* -- cgit v1.2.3 From c5dd1f94246acdf6be6796db47efba8b2a93f93e Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:58 -0300 Subject: USB: speedtch: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/speedtch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index c870c804470f..a823486495c3 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -834,8 +834,8 @@ static int speedtch_bind(struct usbatm_data *usbatm, const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; if ((endpoint_desc->bEndpointAddress == target_address)) { - use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC; + use_isoc = + usb_endpoint_xfer_isoc(endpoint_desc); break; } } -- cgit v1.2.3 From a20c314412b9e9e029a73dbb4dd951e36499eb58 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:02:59 -0300 Subject: USB: usbkbd: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/usbkbd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index c73285cf8558..b6c2ba7e05a4 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -236,9 +236,7 @@ static int usb_kbd_probe(struct usb_interface *iface, return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) - return -ENODEV; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) + if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); -- cgit v1.2.3 From 30f36ef922201cd085a598a6274ee18a360635ea Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:03:00 -0300 Subject: USB: usbmouse: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/usbmouse.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index cbbbea332ed7..68a55642c082 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c @@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i return -ENODEV; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) - return -ENODEV; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) + if (!usb_endpoint_is_int_in(endpoint)) return -ENODEV; pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); -- cgit v1.2.3 From fc6e2544bdb1e7cb9f7ccbb16c268d61743b123c Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:03:01 -0300 Subject: USB: usbnet: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/usbnet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c index 760b5327b81b..7672e11c94c4 100644 --- a/drivers/usb/net/usbnet.c +++ b/drivers/usb/net/usbnet.c @@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) e = alt->endpoint + ep; switch (e->desc.bmAttributes) { case USB_ENDPOINT_XFER_INT: - if (!(e->desc.bEndpointAddress & USB_DIR_IN)) + if (!usb_endpoint_dir_in(&e->desc)) continue; intr = 1; /* FALLTHROUGH */ @@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) default: continue; } - if (e->desc.bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(&e->desc)) { if (!intr && !in) in = e; else if (intr && !status) -- cgit v1.2.3 From 4d823dd21d81c29a83a4672ac92e449fc5fa5cca Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:03:02 -0300 Subject: USB: usbtest: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 7c2cbdf81d20..194065dbb51f 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) default: continue; } - if (e->desc.bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(&e->desc)) { if (!in) in = e; } else { @@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf) } continue; try_iso: - if (e->desc.bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(&e->desc)) { if (!iso_in) iso_in = e; } else { -- cgit v1.2.3 From 0472074748444529188c77f62f0714f9ff7d7556 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:03:03 -0300 Subject: USB: storage: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/usb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index b8d6031b0975..b401084b3d22 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us) ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { + if (usb_endpoint_xfer_bulk(ep)) { /* BULK in or out? */ - if (ep->bEndpointAddress & USB_DIR_IN) + if (usb_endpoint_dir_in(ep)) ep_in = ep; else ep_out = ep; } /* Is it an interrupt endpoint? */ - else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_INT) { + else if (usb_endpoint_xfer_int(ep)) { ep_int = ep; } } -- cgit v1.2.3 From 6f7cd44162ca1bffd54f4090e67b9810bacb5d25 Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Thu, 26 Oct 2006 13:03:04 -0300 Subject: USB: yealink: Use usb_endpoint_* functions Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/yealink.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/yealink.c b/drivers/usb/input/yealink.c index 905bf6398257..2268ca311ade 100644 --- a/drivers/usb/input/yealink.c +++ b/drivers/usb/input/yealink.c @@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id) interface = intf->cur_altsetting; endpoint = &interface->endpoint[0].desc; - if (!(endpoint->bEndpointAddress & USB_DIR_IN)) - return -EIO; - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) - return -EIO; + if (!usb_endpoint_is_int_in(endpoint)) + return -ENODEV; yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); if (!yld) -- cgit v1.2.3 From 0c1ac4f25f894f9df0ffe9b912c165fb6a185a3c Mon Sep 17 00:00:00 2001 From: "Luiz Fernando N. Capitulino" Date: Mon, 30 Oct 2006 14:53:03 -0300 Subject: USB: makes usb_endpoint_* functions inline. We have no benefits of having the usb_endpoint_* functions as functions, but making them inline saves text and data segment sizes: text data bss dec hex filename 14893634 3108770 1108840 19111244 1239d4c vmlinux.func 14893185 3108566 1108840 19110591 1239abf vmlinux.inline This is the result of a 2.6.19-rc3 kernel compiled with GCC 4.1.1 without CONFIG_MODULES, CONFIG_CC_OPTIMIZE_FOR_SIZE, CONFIG_REGPARM options set. USB support is fully enabled (while most of the other drivers are not), and that kernel has most of the USB code ported to use the endpoint functions. That happens because a call to those functions are expensive (in terms of bytes), while the function's size is smaller or have the same 'size' of the call. Signed-off-by: Luiz Fernando N. Capitulino Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 144 ------------------------------------------------- include/linux/usb.h | 142 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 131 insertions(+), 155 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 467cb02832f3..a83c2d5065c1 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -537,138 +537,6 @@ int usb_get_current_frame_number(struct usb_device *dev) return usb_hcd_get_frame_number (dev); } -/** - * usb_endpoint_dir_in - check if the endpoint has IN direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type IN, otherwise it returns false. - */ -int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); -} - -/** - * usb_endpoint_dir_out - check if the endpoint has OUT direction - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type OUT, otherwise it returns false. - */ -int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); -} - -/** - * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type bulk, otherwise it returns false. - */ -int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_BULK); -} - -/** - * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type interrupt, otherwise it returns - * false. - */ -int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_INT); -} - -/** - * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type - * @epd: endpoint to be checked - * - * Returns true if the endpoint is of type isochronous, otherwise it returns - * false. - */ -int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) -{ - return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_ISOC); -} - -/** - * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and IN direction, - * otherwise it returns false. - */ -int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has bulk transfer type and OUT direction, - * otherwise it returns false. - */ -int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_int_in - check if the endpoint is interrupt IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and IN direction, - * otherwise it returns false. - */ -int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has interrupt transfer type and OUT direction, - * otherwise it returns false. - */ -int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); -} - -/** - * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and IN direction, - * otherwise it returns false. - */ -int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); -} - -/** - * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT - * @epd: endpoint to be checked - * - * Returns true if the endpoint has isochronous transfer type and OUT direction, - * otherwise it returns false. - */ -int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) -{ - return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); -} - /*-------------------------------------------------------------------*/ /* * __usb_get_extra_descriptor() finds a descriptor of specific type in the @@ -1102,18 +970,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(usb_find_device); EXPORT_SYMBOL(usb_get_current_frame_number); -EXPORT_SYMBOL_GPL(usb_endpoint_dir_in); -EXPORT_SYMBOL_GPL(usb_endpoint_dir_out); -EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk); -EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int); -EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc); -EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in); -EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out); -EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in); -EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out); -EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in); -EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out); - EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_free); diff --git a/include/linux/usb.h b/include/linux/usb.h index e5cb1690975a..e732e024a141 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -495,17 +495,137 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, /*-------------------------------------------------------------------------*/ -extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd); -extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd); +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd)); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd)); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) +{ + return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd)); +} /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From af4f76066d0fcb215ae389b8839d7ae37ce0e28b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 30 Oct 2006 17:06:45 -0500 Subject: USB: autosuspend code consolidation This patch (as813) gathers together common code for USB interface autosuspend/autoresume. It also adds some simple checking at the time an autosuspend request is made, to see whether the request will fail. This way we don't add a workqueue entry when it would end up doing nothing. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 112 +++++++++++++++++++++++++++------------------- 1 file changed, 67 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 401d76f13419..ca0e40ed2b72 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -940,6 +940,36 @@ done: return status; } +/* Internal routine to check whether we may autosuspend a device. */ +static int autosuspend_check(struct usb_device *udev) +{ + int i; + struct usb_interface *intf; + + /* For autosuspend, fail fast if anything is in use. + * Also fail if any interfaces require remote wakeup but it + * isn't available. */ + udev->do_remote_wakeup = device_may_wakeup(&udev->dev); + if (udev->pm_usage_cnt > 0) + return -EBUSY; + if (udev->actconfig) { + for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { + intf = udev->actconfig->interface[i]; + if (!is_active(intf)) + continue; + if (intf->pm_usage_cnt > 0) + return -EBUSY; + if (intf->needs_remote_wakeup && + !udev->do_remote_wakeup) { + dev_dbg(&udev->dev, "remote wakeup needed " + "for autosuspend\n"); + return -EOPNOTSUPP; + } + } + } + return 0; +} + /** * usb_suspend_both - suspend a USB device and its interfaces * @udev: the usb_device to suspend @@ -991,28 +1021,10 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg) udev->do_remote_wakeup = device_may_wakeup(&udev->dev); - /* For autosuspend, fail fast if anything is in use. - * Also fail if any interfaces require remote wakeup but it - * isn't available. */ if (udev->auto_pm) { - if (udev->pm_usage_cnt > 0) - return -EBUSY; - if (udev->actconfig) { - for (; i < udev->actconfig->desc.bNumInterfaces; i++) { - intf = udev->actconfig->interface[i]; - if (!is_active(intf)) - continue; - if (intf->pm_usage_cnt > 0) - return -EBUSY; - if (intf->needs_remote_wakeup && - !udev->do_remote_wakeup) { - dev_dbg(&udev->dev, - "remote wakeup needed for autosuspend\n"); - return -EOPNOTSUPP; - } - } - i = 0; - } + status = autosuspend_check(udev); + if (status < 0) + return status; } /* Suspend all the interfaces and then udev itself */ @@ -1151,7 +1163,7 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) { usb_pm_lock(udev); udev->pm_usage_cnt -= dec_usage_cnt; - if (udev->pm_usage_cnt <= 0) + if (autosuspend_check(udev) == 0) queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, USB_AUTOSUSPEND_DELAY); usb_pm_unlock(udev); @@ -1200,6 +1212,33 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) return status; } +/* Internal routine to adjust an interface's usage counter and change + * its device's autosuspend state. + */ +static int usb_autopm_do_interface(struct usb_interface *intf, + int inc_usage_cnt) +{ + struct usb_device *udev = interface_to_usbdev(intf); + int status = 0; + + usb_pm_lock(udev); + if (intf->condition == USB_INTERFACE_UNBOUND) + status = -ENODEV; + else { + intf->pm_usage_cnt += inc_usage_cnt; + if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { + udev->auto_pm = 1; + status = usb_resume_both(udev); + if (status != 0) + intf->pm_usage_cnt -= inc_usage_cnt; + } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) + queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, + USB_AUTOSUSPEND_DELAY); + } + usb_pm_unlock(udev); + return status; +} + /** * usb_autopm_put_interface - decrement a USB interface's PM-usage counter * @intf: the usb_interface whose counter should be decremented @@ -1233,17 +1272,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) */ void usb_autopm_put_interface(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); + int status; - usb_pm_lock(udev); - if (intf->condition != USB_INTERFACE_UNBOUND && - --intf->pm_usage_cnt <= 0) { - queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, - USB_AUTOSUSPEND_DELAY); - } - usb_pm_unlock(udev); - // dev_dbg(&intf->dev, "%s: cnt %d\n", - // __FUNCTION__, intf->pm_usage_cnt); + status = usb_autopm_do_interface(intf, -1); + // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", + // __FUNCTION__, status, intf->pm_usage_cnt); } EXPORT_SYMBOL_GPL(usb_autopm_put_interface); @@ -1280,20 +1313,9 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface); */ int usb_autopm_get_interface(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - int status; + int status; - usb_pm_lock(udev); - if (intf->condition == USB_INTERFACE_UNBOUND) - status = -ENODEV; - else { - ++intf->pm_usage_cnt; - udev->auto_pm = 1; - status = usb_resume_both(udev); - if (status != 0) - --intf->pm_usage_cnt; - } - usb_pm_unlock(udev); + status = usb_autopm_do_interface(intf, 1); // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", // __FUNCTION__, status, intf->pm_usage_cnt); return status; -- cgit v1.2.3 From 692a186c9d5f12d43cef28d40c25247dc4f302f0 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 30 Oct 2006 17:07:51 -0500 Subject: USB: expand autosuspend/autoresume API This patch (as814) adds usb_autopm_set_interface() to the autosuspend API. It also provides convenient wrapper routines, usb_autopm_enable() and usb_autopm_disable(), for drivers that want to specify directly whether autosuspend should be allowed. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 22 ++++++++++++++++++++++ include/linux/usb.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ca0e40ed2b72..204495fa6b3d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1322,6 +1322,28 @@ int usb_autopm_get_interface(struct usb_interface *intf) } EXPORT_SYMBOL_GPL(usb_autopm_get_interface); +/** + * usb_autopm_set_interface - set a USB interface's autosuspend state + * @intf: the usb_interface whose state should be set + * + * This routine sets the autosuspend state of @intf's device according + * to @intf's usage counter, which the caller must have set previously. + * If the counter is <= 0, the device is autosuspended (if it isn't + * already suspended and if nothing else prevents the autosuspend). If + * the counter is > 0, the device is autoresumed (if it isn't already + * awake). + */ +int usb_autopm_set_interface(struct usb_interface *intf) +{ + int status; + + status = usb_autopm_do_interface(intf, 0); + // dev_dbg(&intf->dev, "%s: status %d cnt %d\n", + // __FUNCTION__, status, intf->pm_usage_cnt); + return status; +} +EXPORT_SYMBOL_GPL(usb_autopm_set_interface); + #endif /* CONFIG_USB_SUSPEND */ static int usb_suspend(struct device *dev, pm_message_t message) diff --git a/include/linux/usb.h b/include/linux/usb.h index e732e024a141..864c6c21c21e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -415,14 +415,37 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id); /* USB autosuspend and autoresume */ #ifdef CONFIG_USB_SUSPEND +extern int usb_autopm_set_interface(struct usb_interface *intf); extern int usb_autopm_get_interface(struct usb_interface *intf); extern void usb_autopm_put_interface(struct usb_interface *intf); +static inline void usb_autopm_enable(struct usb_interface *intf) +{ + intf->pm_usage_cnt = 0; + usb_autopm_set_interface(intf); +} + +static inline void usb_autopm_disable(struct usb_interface *intf) +{ + intf->pm_usage_cnt = 1; + usb_autopm_set_interface(intf); +} + #else -#define usb_autopm_get_interface(intf) 0 -#define usb_autopm_put_interface(intf) do {} while (0) -#endif +static inline int usb_autopm_set_interface(struct usb_interface *intf) +{ return 0; } + +static inline int usb_autopm_get_interface(struct usb_interface *intf) +{ return 0; } + +static inline void usb_autopm_put_interface(struct usb_interface *intf) +{ } +static inline void usb_autopm_enable(struct usb_interface *intf) +{ } +static inline void usb_autopm_disable(struct usb_interface *intf) +{ } +#endif /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From b4ee4a2309c9f811457ce44962eed753e451dc11 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 9 Nov 2006 22:02:37 +0100 Subject: USB: net1080: Fix && typos Fix STATUS_PACKETS_* macros, where "&&" was mistakenly used where "&" should have. Signed-off-by: Jean Delvare Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/net1080.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/net1080.c b/drivers/usb/net/net1080.c index ce00de8f13a1..a77410562e12 100644 --- a/drivers/usb/net/net1080.c +++ b/drivers/usb/net/net1080.c @@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl) #define STATUS_CONN_OTHER (1 << 14) #define STATUS_SUSPEND_OTHER (1 << 13) #define STATUS_MAILBOX_OTHER (1 << 12) -#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) +#define STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03) #define STATUS_CONN_THIS (1 << 6) #define STATUS_SUSPEND_THIS (1 << 5) #define STATUS_MAILBOX_THIS (1 << 4) -#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) +#define STATUS_PACKETS_THIS(n) (((n) >> 0) & 0x03) #define STATUS_UNSPEC_MASK 0x0c8c #define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) -- cgit v1.2.3 From 1bb5f66bb3b6c2fd7eec1cdfee9cf3f68ef83487 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 6 Nov 2006 11:56:13 -0500 Subject: USB: Move private hub declarations out of public header file This patch (as809b) moves the declaration of the hub driver's private data structure from hub.h into the hub.c source file. Lots of other files import hub.h; they have no need to know about the details of the hub driver's private data. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 42 ++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/hub.h | 41 ----------------------------------------- 2 files changed, 42 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c91745def9e7..c961a32f3176 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -31,6 +31,48 @@ #include "hcd.h" #include "hub.h" +struct usb_hub { + struct device *intfdev; /* the "interface" device */ + struct usb_device *hdev; + struct urb *urb; /* for interrupt polling pipe */ + + /* buffer for urb ... with extra space in case of babble */ + char (*buffer)[8]; + dma_addr_t buffer_dma; /* DMA address for buffer */ + union { + struct usb_hub_status hub; + struct usb_port_status port; + } *status; /* buffer for status reports */ + + int error; /* last reported error */ + int nerrors; /* track consecutive errors */ + + struct list_head event_list; /* hubs w/data or errs ready */ + unsigned long event_bits[1]; /* status change bitmask */ + unsigned long change_bits[1]; /* ports with logical connect + status change */ + unsigned long busy_bits[1]; /* ports being reset or + resumed */ +#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ +#error event_bits[] is too short! +#endif + + struct usb_hub_descriptor *descriptor; /* class descriptor */ + struct usb_tt tt; /* Transaction Translator */ + + unsigned mA_per_port; /* current for each child */ + + unsigned limited_power:1; + unsigned quiescing:1; + unsigned activating:1; + unsigned resume_root_hub:1; + + unsigned has_indicators:1; + u8 indicator[USB_MAXCHILDREN]; + struct work_struct leds; +}; + + /* Protect struct usb_device->state and ->children members * Note: Both are also protected by ->dev.sem, except that ->state can * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h index 1b05994de4dc..cf9559c6c9b6 100644 --- a/drivers/usb/core/hub.h +++ b/drivers/usb/core/hub.h @@ -192,45 +192,4 @@ struct usb_tt_clear { extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); -struct usb_hub { - struct device *intfdev; /* the "interface" device */ - struct usb_device *hdev; - struct urb *urb; /* for interrupt polling pipe */ - - /* buffer for urb ... with extra space in case of babble */ - char (*buffer)[8]; - dma_addr_t buffer_dma; /* DMA address for buffer */ - union { - struct usb_hub_status hub; - struct usb_port_status port; - } *status; /* buffer for status reports */ - - int error; /* last reported error */ - int nerrors; /* track consecutive errors */ - - struct list_head event_list; /* hubs w/data or errs ready */ - unsigned long event_bits[1]; /* status change bitmask */ - unsigned long change_bits[1]; /* ports with logical connect - status change */ - unsigned long busy_bits[1]; /* ports being reset or - resumed */ -#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ -#error event_bits[] is too short! -#endif - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct usb_tt tt; /* Transaction Translator */ - - unsigned mA_per_port; /* current for each child */ - - unsigned limited_power:1; - unsigned quiescing:1; - unsigned activating:1; - unsigned resume_root_hub:1; - - unsigned has_indicators:1; - u8 indicator[USB_MAXCHILDREN]; - struct work_struct leds; -}; - #endif /* __LINUX_HUB_H */ -- cgit v1.2.3 From d8126a0c23b95d8f49a8f4b49191691f9a09ae4a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 12 Nov 2006 18:09:44 -0800 Subject: usb/gadget/ether.c minor manycast tweaks Minor cleanup/clarification in the ethernet gadget driver, using standard calls to test for Ethernet multicast and broadcast addresses. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ether.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 1c17d26d03b8..3bd1dfe565c1 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) if (!eth_is_promisc (dev)) { u8 *dest = skb->data; - if (dest [0] & 0x01) { + if (is_multicast_ether_addr(dest)) { u16 type; /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host * SET_ETHERNET_MULTICAST_FILTERS requests */ - if (memcmp (dest, net->broadcast, ETH_ALEN) == 0) + if (is_broadcast_ether_addr(dest)) type = USB_CDC_PACKET_TYPE_BROADCAST; else type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; -- cgit v1.2.3 From d5ec1686ba96eb75e132196c486cc0521b00f12c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 14 Nov 2006 10:06:17 -0800 Subject: USB: resume_device symbol conflict Several functions in USB core overlap with global functions. The linker appears to do the right thing, but it is bad practice and makes debugging harder. Signed-off-by: Stephen Hemminger Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 204495fa6b3d..44dd6103fb44 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -810,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister); #ifdef CONFIG_PM /* Caller has locked udev's pm_mutex */ -static int suspend_device(struct usb_device *udev, pm_message_t msg) +static int usb_suspend_device(struct usb_device *udev, pm_message_t msg) { struct usb_device_driver *udriver; int status = 0; @@ -837,7 +837,7 @@ done: } /* Caller has locked udev's pm_mutex */ -static int resume_device(struct usb_device *udev) +static int usb_resume_device(struct usb_device *udev) { struct usb_device_driver *udriver; int status = 0; @@ -863,7 +863,7 @@ done: } /* Caller has locked intf's usb_device's pm mutex */ -static int suspend_interface(struct usb_interface *intf, pm_message_t msg) +static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; int status = 0; @@ -900,7 +900,7 @@ done: } /* Caller has locked intf's usb_device's pm_mutex */ -static int resume_interface(struct usb_interface *intf) +static int usb_resume_interface(struct usb_interface *intf) { struct usb_driver *driver; int status = 0; @@ -1031,19 +1031,19 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (udev->actconfig) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - status = suspend_interface(intf, msg); + status = usb_suspend_interface(intf, msg); if (status != 0) break; } } if (status == 0) - status = suspend_device(udev, msg); + status = usb_suspend_device(udev, msg); /* If the suspend failed, resume interfaces that did get suspended */ if (status != 0) { while (--i >= 0) { intf = udev->actconfig->interface[i]; - resume_interface(intf); + usb_resume_interface(intf); } /* If the suspend succeeded, propagate it up the tree */ @@ -1109,14 +1109,14 @@ int usb_resume_both(struct usb_device *udev) status = -EHOSTUNREACH; } if (status == 0) - status = resume_device(udev); + status = usb_resume_device(udev); if (parent) usb_pm_unlock(parent); } else { /* Needed only for setting udev->dev.power.power_state.event * and for possible debugging message. */ - status = resume_device(udev); + status = usb_resume_device(udev); } /* Now the parent won't suspend until we are finished */ @@ -1124,7 +1124,7 @@ int usb_resume_both(struct usb_device *udev) if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - resume_interface(intf); + usb_resume_interface(intf); } } -- cgit v1.2.3 From 54c9b2266f83dfc3d6c538417564dc74266f4dd9 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:23:58 +0100 Subject: USB: make drivers/usb/input/wacom_sys.c:wacom_sys_irq() static This patch makes the needlessly global wacom_sys_irq() static. Signed-off-by: Adrian Bunk Signed-off-by: Ping Cheng Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/wacom.h | 1 - drivers/usb/input/wacom_sys.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/wacom.h b/drivers/usb/input/wacom.h index 1cf08f02c50e..d85abfc5ab58 100644 --- a/drivers/usb/input/wacom.h +++ b/drivers/usb/input/wacom.h @@ -110,7 +110,6 @@ struct wacom_combo { }; extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); -extern void wacom_sys_irq(struct urb *urb); extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); diff --git a/drivers/usb/input/wacom_sys.c b/drivers/usb/input/wacom_sys.c index 3498b893b53b..e7cc20ab8155 100644 --- a/drivers/usb/input/wacom_sys.c +++ b/drivers/usb/input/wacom_sys.c @@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo) return wcombo->wacom->dev; } -void wacom_sys_irq(struct urb *urb) +static void wacom_sys_irq(struct urb *urb) { struct wacom *wacom = urb->context; struct wacom_combo wcombo; -- cgit v1.2.3 From ad0327d680734b76c33f5438cd656bdfd26f5f5b Mon Sep 17 00:00:00 2001 From: "daniel@centurion.net.nz" Date: Sat, 11 Nov 2006 15:47:52 +1300 Subject: USB: airprime: New device ID Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/airprime.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/airprime.c b/drivers/usb/serial/airprime.c index 7f5d546da39a..96c73726d74a 100644 --- a/drivers/usb/serial/airprime.c +++ b/drivers/usb/serial/airprime.c @@ -19,6 +19,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ + { USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */ { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ { }, }; -- cgit v1.2.3 From 1f54a6ae79ab4369f17d6bc86eaff3125395af9c Mon Sep 17 00:00:00 2001 From: Oleg Verych Date: Fri, 17 Nov 2006 08:21:27 +0000 Subject: usb-serial: ti_usb, TI ez430 development tool ID usb-serial: ti_usb, TI ez430 development tool ID Signed-off-by: Oleg Verych Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ti_usb_3410_5052.c | 2 ++ drivers/usb/serial/ti_usb_3410_5052.h | 1 + 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 07400c0c8a8c..bbbb993447b9 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -228,6 +228,7 @@ static int product_5052_count; /* null entry */ static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, }; static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { @@ -239,6 +240,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_combined[] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index 02c1aeb9e1b8..b5541bf991ba 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h @@ -28,6 +28,7 @@ /* Vendor and product ids */ #define TI_VENDOR_ID 0x0451 #define TI_3410_PRODUCT_ID 0x3410 +#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */ #define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */ #define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */ #define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */ -- cgit v1.2.3 From 444f4f91fda54bea57a0e31098a75f54548e8b28 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Thu, 16 Nov 2006 16:38:57 +0100 Subject: USB: pwc-if loop fix We should free urbs starting at [i-1] not [i]. Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/pwc/pwc-if.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 46c114830884..83739b213e7f 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -866,11 +866,10 @@ int pwc_isoc_init(struct pwc_device *pdev) } if (ret) { /* De-allocate in reverse order */ - while (i >= 0) { + while (i--) { if (pdev->sbuf[i].urb != NULL) usb_free_urb(pdev->sbuf[i].urb); pdev->sbuf[i].urb = NULL; - i--; } return ret; } -- cgit v1.2.3 From 6265d62f31e42cc839f929439a95f602d70d6bf7 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:02 +0100 Subject: usb: pcwd_usb free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/char/watchdog/pcwd_usb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c index bda45334d802..e275dd4a705d 100644 --- a/drivers/char/watchdog/pcwd_usb.c +++ b/drivers/char/watchdog/pcwd_usb.c @@ -561,8 +561,7 @@ static struct notifier_block usb_pcwd_notifier = { */ static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) { - if (usb_pcwd->intr_urb != NULL) - usb_free_urb (usb_pcwd->intr_urb); + usb_free_urb(usb_pcwd->intr_urb); if (usb_pcwd->intr_buffer != NULL) usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, usb_pcwd->intr_buffer, usb_pcwd->intr_dma); -- cgit v1.2.3 From 8f21d119f457ece27a69ac1dadd655deee6f2a20 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:09 +0100 Subject: usb: iforce-usb free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/input/joystick/iforce/iforce-usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 105112fb7b57..80cdebcbcb99 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c @@ -178,9 +178,9 @@ static int iforce_usb_probe(struct usb_interface *intf, fail: if (iforce) { - if (iforce->irq) usb_free_urb(iforce->irq); - if (iforce->out) usb_free_urb(iforce->out); - if (iforce->ctrl) usb_free_urb(iforce->ctrl); + usb_free_urb(iforce->irq); + usb_free_urb(iforce->out); + usb_free_urb(iforce->ctrl); kfree(iforce); } -- cgit v1.2.3 From ead54fcd6a6ffc0c45e318ffe8872d228bdff0e5 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:17 +0100 Subject: usb: usb-gigaset free kill urb cleanup - usb_free_urb() cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/isdn/gigaset/usb-gigaset.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 4ffa9eb1c28e..5ebf49ac9b23 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -815,14 +815,11 @@ static int gigaset_probe(struct usb_interface *interface, return 0; error: - if (ucs->read_urb) - usb_kill_urb(ucs->read_urb); + usb_kill_urb(ucs->read_urb); kfree(ucs->bulk_out_buffer); - if (ucs->bulk_out_urb != NULL) - usb_free_urb(ucs->bulk_out_urb); + usb_free_urb(ucs->bulk_out_urb); kfree(cs->inbuf[0].rcvbuf); - if (ucs->read_urb != NULL) - usb_free_urb(ucs->read_urb); + usb_free_urb(ucs->read_urb); usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; @@ -850,11 +847,9 @@ static void gigaset_disconnect(struct usb_interface *interface) usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ kfree(ucs->bulk_out_buffer); - if (ucs->bulk_out_urb != NULL) - usb_free_urb(ucs->bulk_out_urb); + usb_free_urb(ucs->bulk_out_urb); kfree(cs->inbuf[0].rcvbuf); - if (ucs->read_urb != NULL) - usb_free_urb(ucs->read_urb); + usb_free_urb(ucs->read_urb); ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; -- cgit v1.2.3 From 4064fe43e8bf6cfe7fc6fadfbccc7fe1fbb1f0c1 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:22 +0100 Subject: usb: cinergyT2 free kill urb cleanup - usb_free_urb() cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/cinergyT2/cinergyT2.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index ff7d4f56ced3..55bc891768c2 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -275,8 +275,7 @@ static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2) int i; for (i=0; istream_urb[i]) - usb_free_urb(cinergyt2->stream_urb[i]); + usb_free_urb(cinergyt2->stream_urb[i]); usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); @@ -320,8 +319,7 @@ static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2) cinergyt2_control_stream_transfer(cinergyt2, 0); for (i=0; istream_urb[i]) - usb_kill_urb(cinergyt2->stream_urb[i]); + usb_kill_urb(cinergyt2->stream_urb[i]); } static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) -- cgit v1.2.3 From 5d02d027ac2e7778011fa833b3efa50b72a23dcd Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:27 +0100 Subject: usb: ttusb_dec free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/dvb/ttusb-dec/ttusb_dec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c index a1c9fa9919ea..8135f3e76aeb 100644 --- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c @@ -1135,8 +1135,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec) dprintk("%s\n", __FUNCTION__); for (i = 0; i < ISO_BUF_COUNT; i++) - if (dec->iso_urb[i]) - usb_free_urb(dec->iso_urb[i]); + usb_free_urb(dec->iso_urb[i]); pci_free_consistent(NULL, ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * -- cgit v1.2.3 From 5e55d2cea80254faa6ba5c13f3053070db57b63f Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:31 +0100 Subject: usb: pvrusb2-hdw free unlink urb cleanup - usb_free_urb() cleanup - usb_unlink_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/pvrusb2/pvrusb2-hdw.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index f920e0ccacd3..1f787333d18c 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c @@ -1953,8 +1953,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, return hdw; fail: if (hdw) { - if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb); - if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb); + usb_free_urb(hdw->ctl_read_urb); + usb_free_urb(hdw->ctl_write_urb); if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer); if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer); if (hdw->controls) kfree(hdw->controls); @@ -2575,12 +2575,10 @@ static void pvr2_ctl_timeout(unsigned long data) struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { hdw->ctl_timeout_flag = !0; - if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) { + if (hdw->ctl_write_pend_flag) usb_unlink_urb(hdw->ctl_write_urb); - } - if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) { + if (hdw->ctl_read_pend_flag) usb_unlink_urb(hdw->ctl_read_urb); - } } } -- cgit v1.2.3 From 4c6f7d4a889ad997483a4c0318111b4a506f0fe3 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:50 +0100 Subject: usb: pvrusb2-io free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/pvrusb2/pvrusb2-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/pvrusb2/pvrusb2-io.c b/drivers/media/video/pvrusb2/pvrusb2-io.c index 70aa63eba0cb..57fb32033543 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-io.c +++ b/drivers/media/video/pvrusb2/pvrusb2-io.c @@ -289,7 +289,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp) pvr2_buffer_set_none(bp); bp->signature = 0; bp->stream = NULL; - if (bp->purb) usb_free_urb(bp->purb); + usb_free_urb(bp->purb); pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/" " bufferDone %p",bp); } -- cgit v1.2.3 From 90b2625a5159607e37871cd75370c189fc22d208 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:55 +0100 Subject: usb: pwc-if free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/pwc/pwc-if.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 83739b213e7f..62070b9049eb 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c @@ -867,8 +867,7 @@ int pwc_isoc_init(struct pwc_device *pdev) if (ret) { /* De-allocate in reverse order */ while (i--) { - if (pdev->sbuf[i].urb != NULL) - usb_free_urb(pdev->sbuf[i].urb); + usb_free_urb(pdev->sbuf[i].urb); pdev->sbuf[i].urb = NULL; } return ret; -- cgit v1.2.3 From 14d2707b80d6a9d1e8e92718885f99b77531b339 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:34:59 +0100 Subject: usb: sn9c102_core free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/sn9c102/sn9c102_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/sn9c102/sn9c102_core.c b/drivers/media/video/sn9c102/sn9c102_core.c index 42fb60d985b9..18458d46c0ff 100644 --- a/drivers/media/video/sn9c102/sn9c102_core.c +++ b/drivers/media/video/sn9c102/sn9c102_core.c @@ -775,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) return 0; free_urbs: - for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) + for (i = 0; i < SN9C102_URBS; i++) usb_free_urb(cam->urb[i]); free_buffers: -- cgit v1.2.3 From 926b1e90093688d91cbc358e5339ad2861c86e46 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:02 +0100 Subject: usb: quickcam_messenger free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/usbvideo/quickcam_messenger.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c index 9a26b9484aae..bbf2beeeb449 100644 --- a/drivers/media/video/usbvideo/quickcam_messenger.c +++ b/drivers/media/video/usbvideo/quickcam_messenger.c @@ -190,8 +190,7 @@ static int qcm_alloc_int_urb(struct qcm *cam) static void qcm_free_int(struct qcm *cam) { - if (cam->button_urb) - usb_free_urb(cam->button_urb); + usb_free_urb(cam->button_urb); } #endif /* CONFIG_INPUT */ -- cgit v1.2.3 From 8563650da0fb2df5755ea133d5fb182ded9d2ae8 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:12 +0100 Subject: usb: zc0301_core free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/media/video/zc0301/zc0301_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/zc0301/zc0301_core.c b/drivers/media/video/zc0301/zc0301_core.c index 5b5563424422..52d0f759ee00 100644 --- a/drivers/media/video/zc0301/zc0301_core.c +++ b/drivers/media/video/zc0301/zc0301_core.c @@ -489,7 +489,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam) return 0; free_urbs: - for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) + for (i = 0; i < ZC0301_URBS; i++) usb_free_urb(cam->urb[i]); free_buffers: -- cgit v1.2.3 From 8fd31e1d85d5c13c1273013067474ebb73ad6fd1 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:38 +0100 Subject: usb: irda-usb free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/net/irda/irda-usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index 14bda765c2fa..6e95645e7245 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1793,10 +1793,8 @@ err_out_3: err_out_2: usb_free_urb(self->tx_urb); err_out_1: - for (i = 0; i < self->max_rx_urb; i++) { - if (self->rx_urb[i]) - usb_free_urb(self->rx_urb[i]); - } + for (i = 0; i < self->max_rx_urb; i++) + usb_free_urb(self->rx_urb[i]); free_netdev(net); err_out: return ret; -- cgit v1.2.3 From f988f272fe8de462045e9f298e5b7f1e39b2e53a Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:42 +0100 Subject: usb: zd1201 free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/net/wireless/zd1201.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index 36b29ff05814..6cb66a356c96 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -1828,10 +1828,8 @@ err_start: /* Leave the device in reset state */ zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); err_zd: - if (zd->tx_urb) - usb_free_urb(zd->tx_urb); - if (zd->rx_urb) - usb_free_urb(zd->rx_urb); + usb_free_urb(zd->tx_urb); + usb_free_urb(zd->rx_urb); kfree(zd); return err; } -- cgit v1.2.3 From 459f836a612d28f224dbbc306ab63187014a6503 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:46 +0100 Subject: usb: ati_remote free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/ati_remote.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 787b847d38cc..ff23318dc301 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c @@ -630,11 +630,8 @@ static int ati_remote_alloc_buffers(struct usb_device *udev, */ static void ati_remote_free_buffers(struct ati_remote *ati_remote) { - if (ati_remote->irq_urb) - usb_free_urb(ati_remote->irq_urb); - - if (ati_remote->out_urb) - usb_free_urb(ati_remote->out_urb); + usb_free_urb(ati_remote->irq_urb); + usb_free_urb(ati_remote->out_urb); usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, ati_remote->inbuf, ati_remote->inbuf_dma); -- cgit v1.2.3 From 2381526a793582ad18b30af0e3013ccad1a8bcdb Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:50 +0100 Subject: usb: ati_remote2 free urb cleanup Hello, - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/ati_remote2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/ati_remote2.c b/drivers/usb/input/ati_remote2.c index f982a2b4a7f9..83f1f79db7c7 100644 --- a/drivers/usb/input/ati_remote2.c +++ b/drivers/usb/input/ati_remote2.c @@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2) int i; for (i = 0; i < 2; i++) { - if (ar2->urb[i]) - usb_free_urb(ar2->urb[i]); + usb_free_urb(ar2->urb[i]); if (ar2->buf[i]) usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); -- cgit v1.2.3 From 6f07429fa295a04e06c93601e6c597e7a6d95495 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:54 +0100 Subject: usb: hid-core free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2c12b04da111..f7a67c4db515 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -2080,13 +2080,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) return hid; fail: - - if (hid->urbin) - usb_free_urb(hid->urbin); - if (hid->urbout) - usb_free_urb(hid->urbout); - if (hid->urbctrl) - usb_free_urb(hid->urbctrl); + usb_free_urb(hid->urbin); + usb_free_urb(hid->urbout); + usb_free_urb(hid->urbctrl); hid_free_buffers(dev, hid); hid_free_device(hid); @@ -2117,8 +2113,7 @@ static void hid_disconnect(struct usb_interface *intf) usb_free_urb(hid->urbin); usb_free_urb(hid->urbctrl); - if (hid->urbout) - usb_free_urb(hid->urbout); + usb_free_urb(hid->urbout); hid_free_buffers(hid->dev, hid); hid_free_device(hid); -- cgit v1.2.3 From 4ba0b2ed583b80cb26b9c8d8a8b418f677ec4a83 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:35:58 +0100 Subject: usb: usbkbd free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/usbkbd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index b6c2ba7e05a4..dac88640eab6 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c @@ -208,10 +208,8 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) { - if (kbd->irq) - usb_free_urb(kbd->irq); - if (kbd->led) - usb_free_urb(kbd->led); + usb_free_urb(kbd->irq); + usb_free_urb(kbd->led); if (kbd->new) usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); if (kbd->cr) -- cgit v1.2.3 From 2891a51cc27e0eed9474668b58e4f587b9f36694 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:03 +0100 Subject: usb: auerswald free kill urb cleanup - usb_free_urb() cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/auerswald.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index e4971d6aaafb..c703f73e1655 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp) { kfree(bp->bufp); kfree(bp->dr); - if (bp->urbp) { - usb_free_urb(bp->urbp); - } + usb_free_urb(bp->urbp); kfree(bp); } @@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp) dbg ("auerswald_int_release"); /* stop the int endpoint */ - if (cp->inturbp) - usb_kill_urb (cp->inturbp); + usb_kill_urb (cp->inturbp); /* deallocate memory */ auerswald_int_free (cp); -- cgit v1.2.3 From f53510e8c49d00085a820ae98ca4753d4487dbad Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:14 +0100 Subject: usb: legousbtower free kill urb cleanup Hello, - usb_free_urb() cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/legousbtower.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index f8611997bd77..5dce797bddb7 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev) tower_abort_transfers (dev); /* free data structures */ - if (dev->interrupt_in_urb != NULL) { - usb_free_urb (dev->interrupt_in_urb); - } - if (dev->interrupt_out_urb != NULL) { - usb_free_urb (dev->interrupt_out_urb); - } + usb_free_urb(dev->interrupt_in_urb); + usb_free_urb(dev->interrupt_out_urb); kfree (dev->read_buffer); kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_out_buffer); @@ -502,15 +498,11 @@ static void tower_abort_transfers (struct lego_usb_tower *dev) if (dev->interrupt_in_running) { dev->interrupt_in_running = 0; mb(); - if (dev->interrupt_in_urb != NULL && dev->udev) { + if (dev->udev) usb_kill_urb (dev->interrupt_in_urb); - } - } - if (dev->interrupt_out_busy) { - if (dev->interrupt_out_urb != NULL && dev->udev) { - usb_kill_urb (dev->interrupt_out_urb); - } } + if (dev->interrupt_out_busy && dev->udev) + usb_kill_urb(dev->interrupt_out_urb); exit: dbg(2, "%s: leave", __FUNCTION__); -- cgit v1.2.3 From df43121463d2e6dde9f7e40a7720e111e4cc600e Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:07 +0100 Subject: usb: phidgetkit free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetkit.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c index 0dc0d034cc9a..9110793f81d3 100644 --- a/drivers/usb/misc/phidgetkit.c +++ b/drivers/usb/misc/phidgetkit.c @@ -650,8 +650,7 @@ out2: device_remove_file(kit->dev, &dev_output_attrs[i]); out: if (kit) { - if (kit->irq) - usb_free_urb(kit->irq); + usb_free_urb(kit->irq); if (kit->data) usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); if (kit->dev) -- cgit v1.2.3 From 5483eb1300fc052c294a9dac57d5bf6653126efd Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:18 +0100 Subject: usb: phidgetmotorcontrol free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/phidgetmotorcontrol.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c index 7702a4f7b082..c3469b0a67c2 100644 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ b/drivers/usb/misc/phidgetmotorcontrol.c @@ -392,8 +392,7 @@ out2: device_remove_file(mc->dev, &dev_attrs[i]); out: if (mc) { - if (mc->irq) - usb_free_urb(mc->irq); + usb_free_urb(mc->irq); if (mc->data) usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); if (mc->dev) -- cgit v1.2.3 From 794c944ecd468ddf8a571bd37ab7b21035965f91 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:25 +0100 Subject: usb: ftdi_sio kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index c186b4e73c72..89ce2775be15 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1388,8 +1388,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp) flush_scheduled_work(); /* shutdown our bulk read */ - if (port->read_urb) - usb_kill_urb(port->read_urb); + usb_kill_urb(port->read_urb); } /* ftdi_close */ -- cgit v1.2.3 From c69694b779714b751a326d1b886087322001e86f Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:22 +0100 Subject: usb: catc free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/catc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c index f740325abac4..907b820a5faf 100644 --- a/drivers/usb/net/catc.c +++ b/drivers/usb/net/catc.c @@ -786,14 +786,10 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id if ((!catc->ctrl_urb) || (!catc->tx_urb) || (!catc->rx_urb) || (!catc->irq_urb)) { err("No free urbs available."); - if (catc->ctrl_urb) - usb_free_urb(catc->ctrl_urb); - if (catc->tx_urb) - usb_free_urb(catc->tx_urb); - if (catc->rx_urb) - usb_free_urb(catc->rx_urb); - if (catc->irq_urb) - usb_free_urb(catc->irq_urb); + usb_free_urb(catc->ctrl_urb); + usb_free_urb(catc->tx_urb); + usb_free_urb(catc->rx_urb); + usb_free_urb(catc->irq_urb); free_netdev(netdev); return -ENOMEM; } -- cgit v1.2.3 From 9a25f44f91b621f49b459687ae49d4fed4423d0e Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:29 +0100 Subject: usb: io_edgeport kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/io_edgeport.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 91bd3014ef1e..d06547a13f28 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp) edge_port->open = FALSE; edge_port->openPending = FALSE; - if (edge_port->write_urb) { - usb_kill_urb(edge_port->write_urb); - } + usb_kill_urb(edge_port->write_urb); if (edge_port->write_urb) { /* if this urb had a transfer buffer already (old transfer) free it */ -- cgit v1.2.3 From 1cadc1378fe9cdee9515842a4bf9f42228448ad2 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:34 +0100 Subject: usb: keyspan free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/keyspan.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 53be824eb1bf..7639652cec42 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial) } /* Now free them */ - if (s_priv->instat_urb) - usb_free_urb(s_priv->instat_urb); - if (s_priv->glocont_urb) - usb_free_urb(s_priv->glocont_urb); + usb_free_urb(s_priv->instat_urb); + usb_free_urb(s_priv->glocont_urb); for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; p_priv = usb_get_serial_port_data(port); - if (p_priv->inack_urb) - usb_free_urb(p_priv->inack_urb); - if (p_priv->outcont_urb) - usb_free_urb(p_priv->outcont_urb); + usb_free_urb(p_priv->inack_urb); + usb_free_urb(p_priv->outcont_urb); for (j = 0; j < 2; j++) { - if (p_priv->in_urbs[j]) - usb_free_urb(p_priv->in_urbs[j]); - if (p_priv->out_urbs[j]) - usb_free_urb(p_priv->out_urbs[j]); + usb_free_urb(p_priv->in_urbs[j]); + usb_free_urb(p_priv->out_urbs[j]); } } -- cgit v1.2.3 From 5505c2261eb5e7a6ff851afbe7f77d54d960e83b Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:38 +0100 Subject: usb: kobil_sct kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/kobil_sct.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 8dd2afa2fca8..237289920f03 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -353,8 +353,7 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp) usb_free_urb( port->write_urb ); port->write_urb = NULL; } - if (port->interrupt_in_urb) - usb_kill_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); } -- cgit v1.2.3 From 73135bb9154f9565e8ae294ffa73f9e871d72b47 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:42 +0100 Subject: usb: mct_u232 free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mct_u232.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index b7582cc496dc..a906e500a02b 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial) /* Puh, that's dirty */ port = serial->port[0]; rport = serial->port[1]; - if (port->read_urb) { - /* No unlinking, it wasn't submitted yet. */ - usb_free_urb(port->read_urb); - } + /* No unlinking, it wasn't submitted yet. */ + usb_free_urb(port->read_urb); port->read_urb = rport->interrupt_in_urb; rport->interrupt_in_urb = NULL; port->read_urb->context = port; -- cgit v1.2.3 From 9aac10ff1d9a228d05491f68f933cf6a41b9debc Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:46 +0100 Subject: usb: navman kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/navman.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index 0610409a6568..054abee81652 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __FUNCTION__, port->number); - if (port->interrupt_in_urb) - usb_kill_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); } static int navman_write(struct usb_serial_port *port, -- cgit v1.2.3 From 95d4316654a7e09778ebf81e03cab7040ecca1b0 Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:51 +0100 Subject: usb: usb-serial free urb cleanup - usb_free_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8006e51c34bb..c1257d5292f5 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -952,32 +952,28 @@ probe_error: port = serial->port[i]; if (!port) continue; - if (port->read_urb) - usb_free_urb (port->read_urb); + usb_free_urb(port->read_urb); kfree(port->bulk_in_buffer); } for (i = 0; i < num_bulk_out; ++i) { port = serial->port[i]; if (!port) continue; - if (port->write_urb) - usb_free_urb (port->write_urb); + usb_free_urb(port->write_urb); kfree(port->bulk_out_buffer); } for (i = 0; i < num_interrupt_in; ++i) { port = serial->port[i]; if (!port) continue; - if (port->interrupt_in_urb) - usb_free_urb (port->interrupt_in_urb); + usb_free_urb(port->interrupt_in_urb); kfree(port->interrupt_in_buffer); } for (i = 0; i < num_interrupt_out; ++i) { port = serial->port[i]; if (!port) continue; - if (port->interrupt_out_urb) - usb_free_urb (port->interrupt_out_urb); + usb_free_urb(port->interrupt_out_urb); kfree(port->interrupt_out_buffer); } -- cgit v1.2.3 From bcb54a54033ff9359cf64e4283e4f4b92bf9132f Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Wed, 8 Nov 2006 15:36:55 +0100 Subject: usb: visor kill urb cleanup - usb_kill_urb() cleanup Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/visor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index befe2e11a041..eef5eaa5fa0b 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) /* shutdown our urbs */ usb_kill_urb(port->read_urb); - if (port->interrupt_in_urb) - usb_kill_urb(port->interrupt_in_urb); + usb_kill_urb(port->interrupt_in_urb); /* Try to send shutdown message, if the device is gone, this will just fail. */ transfer_buffer = kmalloc (0x12, GFP_KERNEL); -- cgit v1.2.3 From 1b7be3c066ae9238996a7a861b39b0bfd5860735 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 6 Nov 2006 12:05:00 -0500 Subject: OHCI: change priority level of resume log message All the other root-hub suspend or resume log messages, in ohci-hcd or any of the other host controller drivers, use the debug priority level. This patch (as815) makes the one single exception behave like all the rest. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index dcf9eb601328..4c9492779ede 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -175,7 +175,7 @@ __acquires(ohci->lock) break; case OHCI_USB_RESUME: /* HCFS changes sometime after INTR_RD */ - ohci_info(ohci, "%swakeup\n", + ohci_dbg(ohci, "%swakeup root hub\n", autostopped ? "auto-" : ""); break; case OHCI_USB_OPER: -- cgit v1.2.3 From 7a5c7b42d3c7b1e0085d48414ee73003d3888d1f Mon Sep 17 00:00:00 2001 From: Naranjo Manuel Francisco Date: Wed, 15 Nov 2006 15:14:27 -0300 Subject: USB: fix aircable.c: inconsequent NULL checking > 2006/11/11, Adrian Bunk : > > The Coverity checker spotted the following in > > drivers/usb/serial/aircable.c: > > > > <-- snip --> > > > > ... > > static void aircable_read(void *params) > > { > > ... Hi everyone, Sorry for the long time response but here is the patch, I think this way should work, if anyone has any suggestion let me know. What I do now is, in case I don't have the tty available I reschedule the work, I have tried it and it works with no problem, I even tried removing the device, and didn't find anything strange. Signed-off-by: Naranjo Manuel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/aircable.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index 8554c1a7b9fc..b1b5707bc99a 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -270,8 +270,11 @@ static void aircable_read(void *params) */ tty = port->tty; - if (!tty) + if (!tty) { schedule_work(&priv->rx_work); + err("%s - No tty available", __FUNCTION__); + return ; + } count = min(64, serial_buf_data_avail(priv->rx_buf)); -- cgit v1.2.3 From db063507b40664de33a61161c90358fe6fc9565a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 13 Nov 2006 15:02:04 -0500 Subject: USB core: fix compiler warning about usb_autosuspend_work This patch (as821) fixes a compiler warning when CONFIG_PM isn't on ("usb_autosuspend_work" defined but not used). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/usb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index a83c2d5065c1..81cb52564e68 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void) destroy_workqueue(ksuspend_usb_wq); } -#else - -#define ksuspend_usb_init() 0 -#define ksuspend_usb_cleanup() do {} while (0) - -#endif - #ifdef CONFIG_USB_SUSPEND /* usb_autosuspend_work - callback routine to autosuspend a USB device */ @@ -225,7 +218,14 @@ static void usb_autosuspend_work(void *_udev) static void usb_autosuspend_work(void *_udev) {} -#endif +#endif /* CONFIG_USB_SUSPEND */ + +#else + +#define ksuspend_usb_init() 0 +#define ksuspend_usb_cleanup() do {} while (0) + +#endif /* CONFIG_PM */ /** * usb_alloc_dev - usb device constructor (usbcore-internal) -- cgit v1.2.3 From 49314378ac9b76c40f221e3e5aed866e912e7e99 Mon Sep 17 00:00:00 2001 From: Jaco Kroon Date: Wed, 15 Nov 2006 01:02:08 -0800 Subject: USB: add Digitech USB-Storage to unusual_devs.h The mass storage device from Digitech designed for Flash Cards, as found on (for example) the GNX4 device has issues with residue, similar to the bug report at http://kerneltrap.org/node/6297. This patch adds the faulty storage device to unusual_devs.h, this not only reduces the noise in dmesg but also increases the transfer speeds by a factor of 7x for me (89kB/s -> 637kB/s). T: Bus=02 Lev=02 Prnt=02 Port=01 Cnt=02 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1210 ProdID=0003 Rev= 1.00 S: Manufacturer=DigiTech HMG S: Product=DigiTech Mass Storage C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 0mA I: If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms Signed-off-by: Jaco Kroon Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index efb047f431e8..db8b26012c75 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1318,6 +1318,16 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110, US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, 0 ), +/* Reported by Jaco Kroon + * The usb-storage module found on the Digitech GNX4 (and supposedly other + * devices) misbehaves and causes a bunch of invalid I/O errors. + */ +UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, + "Digitech HMG", + "DigiTech Mass Storage", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_RESIDUE ), + /* Reported by Vilius Bilinkevicius Date: Fri, 17 Nov 2006 11:53:23 +0100 Subject: usb: microtek possible memleak fix Possible memleak fix on error path. The changes: - out_kfree2 and out_free_urb replaced - missing scsi_host_put() added Here it goes: Signed-off-by: Mariusz Kozlowski Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/microtek.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 3038ed0700d3..8ccddf74534a 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf, new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL); if (!new_desc->context.scsi_status) - goto out_kfree2; + goto out_free_urb; new_desc->usb_dev = dev; new_desc->usb_intf = intf; @@ -822,18 +822,20 @@ static int mts_usb_probe(struct usb_interface *intf, new_desc->host = scsi_host_alloc(&mts_scsi_host_template, sizeof(new_desc)); if (!new_desc->host) - goto out_free_urb; + goto out_kfree2; new_desc->host->hostdata[0] = (unsigned long)new_desc; if (scsi_add_host(new_desc->host, NULL)) { err_retval = -EIO; - goto out_free_urb; + goto out_host_put; } scsi_scan_host(new_desc->host); usb_set_intfdata(intf, new_desc); return 0; + out_host_put: + scsi_host_put(new_desc->host); out_kfree2: kfree(new_desc->context.scsi_status); out_free_urb: -- cgit v1.2.3 From 1f26e28d3e32339ca683f087cd55a70e2befc333 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 16 Nov 2006 10:16:00 -0500 Subject: USB: net2280: don't send unwanted zero-length packets The net2280 driver is too eager to send zero-length packets when IN tokens are received on ep0. No such packet should be sent (the driver should NAK) before the gadget driver has queued the proper response. Otherwise deferred responses are impossible. This patch (as823) makes net2280 avoid sending ZLPs for IN transfers on ep0 until a response has been submitted, and avoids stalling when an OUT packet is received before a request has been submitted for an OUT transfer on ep0. Signed-off-by: Alan Stern Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/net2280.c | 8 ++++++-- drivers/usb/gadget/net2280.h | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3acc896a5d4c..0b590831582c 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) } /* else the irq handler advances the queue. */ + ep->responded = 1; if (req) list_add_tail (&req->queue, &ep->queue); done: @@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep) ep->stopped = 1; set_halt (ep); mode = 2; - } else if (!req && !ep->stopped) + } else if (ep->responded && + !req && !ep->stopped) write_fifo (ep, NULL); } } else { @@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep) } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) && req && req->req.actual == req->req.length) - || !req) { + || (ep->responded && !req)) { ep->dev->protocol_stall = 1; set_halt (ep); ep->stopped = 1; @@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) /* we made the hardware handle most lowlevel requests; * everything else goes uplevel to the gadget code. */ + ep->responded = 1; switch (u.r.bRequest) { case USB_REQ_GET_STATUS: { struct net2280_ep *e; @@ -2537,6 +2540,7 @@ delegate: u.r.bRequestType, u.r.bRequest, w_value, w_index, w_length, readl (&ep->regs->ep_cfg)); + ep->responded = 0; spin_unlock (&dev->lock); tmp = dev->driver->setup (&dev->gadget, &u.r); spin_lock (&dev->lock); diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h index 957d6df34015..44ca139983d8 100644 --- a/drivers/usb/gadget/net2280.h +++ b/drivers/usb/gadget/net2280.h @@ -110,7 +110,8 @@ struct net2280_ep { out_overflow : 1, stopped : 1, is_in : 1, - is_iso : 1; + is_iso : 1, + responded : 1; }; static inline void allow_status (struct net2280_ep *ep) -- cgit v1.2.3 From f0d7f27351058284f62ab4848909373c2d1f5ce8 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:56:15 -0800 Subject: USB: EHCI hooks for high speed electrical tests EHCI hooks for high speed electrical tests of the root hub ports. The expectation is that a usermode program actually triggers the test, making the same control request it would make for an external hub. Tests for peripheral upstream ports would issue a different request. In all cases, the hardware needs re-initialization before it could be used "normally" again (e.g. unplug/replug, rmmod/modprobe). Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hub.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 1b20722c102b..7c170a29f959 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -319,6 +319,7 @@ static int ehci_hub_control ( u32 temp, status; unsigned long flags; int retval = 0; + unsigned selector; /* * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. @@ -506,6 +507,8 @@ static int ehci_hub_control ( } break; case SetPortFeature: + selector = wIndex >> 8; + wIndex &= 0xff; if (!wIndex || wIndex > ports) goto error; wIndex--; @@ -559,6 +562,22 @@ static int ehci_hub_control ( } writel (temp, &ehci->regs->port_status [wIndex]); break; + + /* For downstream facing ports (these): one hub port is put + * into test mode according to USB2 11.24.2.13, then the hub + * must be reset (which for root hub now means rmmod+modprobe, + * or else system reboot). See EHCI 2.3.9 and 4.14 for info + * about the EHCI-specific stuff. + */ + case USB_PORT_FEAT_TEST: + if (!selector || selector > 5) + goto error; + ehci_quiesce(ehci); + ehci_halt(ehci); + temp |= selector << 16; + writel (temp, &ehci->regs->port_status [wIndex]); + break; + default: goto error; } -- cgit v1.2.3 From 93f1a47c4af34c4ee014b3d2aae70089b3b69f72 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:34:58 -0800 Subject: USB: add ehci_hcd.ignore_oc parameter Certain boards seem to like to issue false overcurrent notifications, for example on ports that don't have anything connected to them. This looks like a hardware error, at the level of noise to those ports' overcurrent input signals (or non-debounced VBUS comparators). This surfaces to users as truly massive amounts of syslog spam from khubd (which is appropriate for real hardware problems, except for the volume from multiple ports). Using this new "ignore_oc" flag helps such systems work more sanely, by preventing such indications from getting to khubd (and spam syslog). The downside is of course that true overcurrent errors will be masked; they'll appear as spontaneous disconnects, without the diagnostics that will let users troubleshoot issues like short circuited cables. Note that the bulk of these reports seem to be with VIA southbridges, but I think some were with Intel ones. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 10 ++++++++-- drivers/usb/host/ehci-hub.c | 18 +++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 9030994aba98..f2ceb5fdbeb7 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -126,6 +126,11 @@ static unsigned park = 0; module_param (park, uint, S_IRUGO); MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); +/* for flakey hardware, ignore overcurrent indicators */ +static int ignore_oc = 0; +module_param (ignore_oc, bool, S_IRUGO); +MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); + #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) /*-------------------------------------------------------------------------*/ @@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd) temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); ehci_info (ehci, - "USB %x.%x started, EHCI %x.%02x, driver %s\n", + "USB %x.%x started, EHCI %x.%02x, driver %s%s\n", ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, DRIVER_VERSION); + temp >> 8, temp & 0xff, DRIVER_VERSION, + ignore_oc ? ", overcurrent ignored" : ""); writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 7c170a29f959..0a56dfa2745d 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -218,6 +218,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp, status = 0; + u32 mask; int ports, i, retval = 1; unsigned long flags; @@ -233,6 +234,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) retval++; } + /* Some boards (mostly VIA?) report bogus overcurrent indications, + * causing massive log spam unless we completely ignore them. It + * may be relevant that VIA VT8235 controlers, where PORT_POWER is + * always set, seem to clear PORT_OCC and PORT_CSC when writing to + * PORT_POWER; that's surprising, but maybe within-spec. + */ + if (!ignore_oc) + mask = PORT_CSC | PORT_PEC | PORT_OCC; + else + mask = PORT_CSC | PORT_PEC; + // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND + /* no hub change reports (bit 0) for now (power, ...) */ /* port N changes (bit N)? */ @@ -250,8 +263,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) } if (!(temp & PORT_CONNECT)) ehci->reset_done [i] = 0; - if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0 - // PORT_STAT_C_SUSPEND? + if ((temp & mask) != 0 || ((temp & PORT_RESUME) != 0 && time_after (jiffies, ehci->reset_done [i]))) { @@ -418,7 +430,7 @@ static int ehci_hub_control ( status |= 1 << USB_PORT_FEAT_C_CONNECTION; if (temp & PORT_PEC) status |= 1 << USB_PORT_FEAT_C_ENABLE; - if (temp & PORT_OCC) + if ((temp & PORT_OCC) && !ignore_oc) status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; /* whoever resumes must GetPortStatus to complete it!! */ -- cgit v1.2.3 From 2e46b74852446404d64b0b00ce872724bfa627ab Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Fri, 17 Nov 2006 17:49:22 +0100 Subject: usb: cypress_m8 init error path fix If at some point cypress_init() fails deregister only the resources that were registered until that point. Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cypress_m8.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index f2e89a083659..093f303b3189 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -1684,15 +1684,14 @@ static int __init cypress_init(void) info(DRIVER_DESC " " DRIVER_VERSION); return 0; + failed_usb_register: - usb_deregister(&cypress_driver); -failed_ca42v2_register: usb_serial_deregister(&cypress_ca42v2_device); -failed_hidcom_register: +failed_ca42v2_register: usb_serial_deregister(&cypress_hidcom_device); -failed_em_register: +failed_hidcom_register: usb_serial_deregister(&cypress_earthmate_device); - +failed_em_register: return retval; } -- cgit v1.2.3 From 27a3de4cfc3508b30803b7350ca6385b3c53f223 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:23:54 +0100 Subject: USB: make drivers/usb/host/u132-hcd.c:u132_hcd_wait static This patch makes the needlessly global "u132_hcd_wait" static. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 32c635ecbf31..5b06e2e8662b 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -71,7 +71,7 @@ static int distrust_firmware = 1; module_param(distrust_firmware, bool, 0); MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" "t setup"); -DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); +static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); /* * u132_module_lock exists to protect access to global variables * -- cgit v1.2.3 From 9ce8540c884c19c0f5f38c9e85d4bdc192baf321 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 20 Nov 2006 03:24:44 +0100 Subject: USB: ftdi-elan.c: fixes and cleanups This patch contains the following possible cleanups: - make the needlessly global ftdi_release_platform_dev() static - remove the unused usb_ftdi_elan_read_reg() - proper prototypes for the following functions: - usb_ftdi_elan_read_pcimem() - usb_ftdi_elan_write_pcimem() Note that the misplaced prototypes for the latter ones in drivers/usb/host/u132-hcd.c were buggy. Depending on the calling convention of the architecture calling one of them could have turned your stack into garbage. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/u132-hcd.c | 6 +----- drivers/usb/misc/ftdi-elan.c | 10 +--------- drivers/usb/misc/usb_u132.h | 4 ++++ 3 files changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 5b06e2e8662b..87106085a98d 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -205,11 +205,7 @@ struct u132 { struct u132_port port[MAX_U132_PORTS]; struct u132_endp *endp[MAX_U132_ENDPS]; }; -int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data); -int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs, - u8 width, u32 *data); -int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs, - u8 width, u32 data); + /* * these can not be inlines because we need the structure offset!! * Does anyone have a better way????? diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 0e8ee2dea881..cb0ba3107d7f 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -303,7 +303,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev) EXPORT_SYMBOL_GPL(ftdi_elan_gone_away); -void ftdi_release_platform_dev(struct device *dev) +static void ftdi_release_platform_dev(struct device *dev) { dev->parent = NULL; } @@ -1426,14 +1426,6 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data) } } -int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data) -{ - struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev); - return ftdi_elan_read_reg(ftdi, data); -} - - -EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg); static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, u8 width, u32 *data) { diff --git a/drivers/usb/misc/usb_u132.h b/drivers/usb/misc/usb_u132.h index 551ba8906d62..fbb52b21349e 100644 --- a/drivers/usb/misc/usb_u132.h +++ b/drivers/usb/misc/usb_u132.h @@ -95,3 +95,7 @@ int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number, int halted, int skipped, int actual, int non_null)); int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number, void *endp); +int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset, + u8 width, u32 *data); +int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset, + u8 width, u32 data); -- cgit v1.2.3 From 24ced062a2965645d651ff92bc93b2c1f926474e Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Fri, 17 Nov 2006 22:50:15 +0100 Subject: usbtouchscreen: add support for DMC TSC-10/25 devices Adds support for the DMC TSC-10 and TSC-25 usb touchscreen controllers. Signed-off-by: Holger Schurig Signed-off-by: Daniel Ritz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/Kconfig | 6 +++ drivers/usb/input/usbtouchscreen.c | 96 +++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 20db36448ab3..661af7aa6236 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig @@ -221,6 +221,7 @@ config USB_TOUCHSCREEN - ITM - some other eTurboTouch - Gunze AHL61 + - DMC TSC-10/25 Have a look at for a usage description and the required user-space stuff. @@ -258,6 +259,11 @@ config USB_TOUCHSCREEN_GUNZE bool "Gunze AHL61 device support" if EMBEDDED depends on USB_TOUCHSCREEN +config USB_TOUCHSCREEN_DMC_TSC10 + default y + bool "DMC TSC-10/25 device support" if EMBEDDED + depends on USB_TOUCHSCREEN + config USB_YEALINK tristate "Yealink usb-p1k voip phone" depends on USB && INPUT && EXPERIMENTAL diff --git a/drivers/usb/input/usbtouchscreen.c b/drivers/usb/input/usbtouchscreen.c index 933ceddf3dee..49704d4ed0e2 100644 --- a/drivers/usb/input/usbtouchscreen.c +++ b/drivers/usb/input/usbtouchscreen.c @@ -8,6 +8,7 @@ * - PanJit TouchSet * - eTurboTouch * - Gunze AHL61 + * - DMC TSC-10/25 * * Copyright (C) 2004-2006 by Daniel Ritz * Copyright (C) by Todd E. Johnson (mtouchusb.c) @@ -30,6 +31,8 @@ * - ITM parts are from itmtouch.c * - 3M parts are from mtouchusb.c * - PanJit parts are from an unmerged driver by Lanslott Gish + * - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged + * driver from Marius Vollmer * *****************************************************************************/ @@ -44,7 +47,7 @@ #include -#define DRIVER_VERSION "v0.4" +#define DRIVER_VERSION "v0.5" #define DRIVER_AUTHOR "Daniel Ritz " #define DRIVER_DESC "USB Touchscreen Driver" @@ -103,6 +106,7 @@ enum { DEVTYPE_ITM, DEVTYPE_ETURBO, DEVTYPE_GUNZE, + DEVTYPE_DMC_TSC10, }; static struct usb_device_id usbtouch_devices[] = { @@ -139,6 +143,10 @@ static struct usb_device_id usbtouch_devices[] = { {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, #endif +#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 + {USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10}, +#endif + {} }; @@ -312,6 +320,80 @@ static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int * } #endif +/***************************************************************************** + * DMC TSC-10/25 Part + * + * Documentation about the controller and it's protocol can be found at + * http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf + * http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf + */ +#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 + +/* supported data rates. currently using 130 */ +#define TSC10_RATE_POINT 0x50 +#define TSC10_RATE_30 0x40 +#define TSC10_RATE_50 0x41 +#define TSC10_RATE_80 0x42 +#define TSC10_RATE_100 0x43 +#define TSC10_RATE_130 0x44 +#define TSC10_RATE_150 0x45 + +/* commands */ +#define TSC10_CMD_RESET 0x55 +#define TSC10_CMD_RATE 0x05 +#define TSC10_CMD_DATA1 0x01 + +static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) +{ + struct usb_device *dev = usbtouch->udev; + int ret; + unsigned char buf[2]; + + /* reset */ + buf[0] = buf[1] = 0xFF; + ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + TSC10_CMD_RESET, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0, buf, 2, USB_CTRL_SET_TIMEOUT); + if (ret < 0) + return ret; + if (buf[0] != 0x06 || buf[1] != 0x00) + return -ENODEV; + + /* set coordinate output rate */ + buf[0] = buf[1] = 0xFF; + ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + TSC10_CMD_RATE, + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT); + if (ret < 0) + return ret; + if (buf[0] != 0x06 || buf[1] != 0x00) + return -ENODEV; + + /* start sending data */ + ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + TSC10_CMD_DATA1, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); + if (ret < 0) + return ret; + + return 0; +} + + +static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press) +{ + *x = ((pkt[2] & 0x03) << 8) | pkt[1]; + *y = ((pkt[4] & 0x03) << 8) | pkt[3]; + *touch = pkt[0] & 0x01; + + return 1; +} +#endif + + /***************************************************************************** * the different device descriptors */ @@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { .read_data = gunze_read_data, }, #endif + +#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10 + [DEVTYPE_DMC_TSC10] = { + .min_xc = 0x0, + .max_xc = 0x03ff, + .min_yc = 0x0, + .max_yc = 0x03ff, + .rept_size = 5, + .init = dmc_tsc10_init, + .read_data = dmc_tsc10_read_data, + }, +#endif }; -- cgit v1.2.3 From 827982c577cddbe50b2120e577a60f6376716900 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 20 Nov 2006 11:38:57 -0800 Subject: USB: pxa2xx_udc recognizes ixp425 rev b0 chip Make the pxa2xx_udc driver recognize a newer revision of the IXP425 chip. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa2xx_udc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index 671c24bc6d75..1ed506e95985 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -2472,6 +2472,7 @@ static struct pxa2xx_udc memory = { #define PXA210_B1 0x00000123 #define PXA210_B0 0x00000122 #define IXP425_A0 0x000001c1 +#define IXP425_B0 0x000001f1 #define IXP465_AD 0x00000200 /* @@ -2509,6 +2510,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev) break; #elif defined(CONFIG_ARCH_IXP4XX) case IXP425_A0: + case IXP425_B0: case IXP465_AD: dev->has_cfr = 1; out_dma = 0; -- cgit v1.2.3 From 7481bb8a7f2fd6b411764e0dc91713b1a58fce4c Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 20 Nov 2006 11:41:39 -0800 Subject: USB: lh7a40x_udc remove double declaration Remove minor double-declaration goof. Signed-off-by: Milan Svoboda Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/lh7a40x_udc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index 179259664c18..4a991564a03e 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -83,7 +83,6 @@ static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t); static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); static int lh7a40x_set_halt(struct usb_ep *ep, int); static int lh7a40x_fifo_status(struct usb_ep *ep); -static int lh7a40x_fifo_status(struct usb_ep *ep); static void lh7a40x_fifo_flush(struct usb_ep *ep); static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep); static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr); -- cgit v1.2.3 From 8bb22d2bdaac415965e7be1af8da2b8f3ee35f31 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 21 Nov 2006 22:02:54 +0100 Subject: USB: make drivers/usb/core/driver.c:usb_device_match() static usb_device_match() can now become static. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 44dd6103fb44..40c1bf09b2b7 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -525,7 +525,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface, } EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); -int usb_device_match(struct device *dev, struct device_driver *drv) +static int usb_device_match(struct device *dev, struct device_driver *drv) { /* devices and interfaces are handled separately */ if (is_usb_device(dev)) { -- cgit v1.2.3 From 54ecf1fba683f779a1b36abed9c843decafc7d5b Mon Sep 17 00:00:00 2001 From: Mariusz Kozlowski Date: Mon, 6 Nov 2006 17:37:20 +0100 Subject: USB: idmouse cleanup Just digging through code and found these needless variable initializations. So here is the patch. Signed-off-by: Mariusz Kozlowski Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/idmouse.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index c5fee0033a84..c9418535bef8 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex); static int idmouse_create_image(struct usb_idmouse *dev) { - int bytes_read = 0; - int bulk_read = 0; - int result = 0; + int bytes_read; + int bulk_read; + int result; memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1); - bytes_read += sizeof(HEADER)-1; + bytes_read = sizeof(HEADER)-1; /* reset the device and set a fast blink rate */ result = ftip_command(dev, FTIP_RELEASE, 0, 0); @@ -208,9 +208,9 @@ static inline void idmouse_delete(struct usb_idmouse *dev) static int idmouse_open(struct inode *inode, struct file *file) { - struct usb_idmouse *dev = NULL; + struct usb_idmouse *dev; struct usb_interface *interface; - int result = 0; + int result; /* prevent disconnects */ mutex_lock(&disconnect_mutex); @@ -305,7 +305,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count loff_t * ppos) { struct usb_idmouse *dev; - int result = 0; + int result; dev = (struct usb_idmouse *) file->private_data; @@ -329,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(interface); - struct usb_idmouse *dev = NULL; + struct usb_idmouse *dev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int result; -- cgit v1.2.3 From afd21ee5abd0fef567dbfa234099304886ff83ce Mon Sep 17 00:00:00 2001 From: Julien BLACHE Date: Wed, 15 Nov 2006 00:00:17 -0500 Subject: USB: hid-core: canonical defines for Apple USB device IDs Use canonical defines for the Apple USB device IDs. Also add the Geyser IV devices missing in my previous patch. Signed-off-by: Julien BLACHE Acked-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/input/hid-core.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index f7a67c4db515..a49644b7c58e 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1640,6 +1640,19 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_APPLE 0x05ac #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 +#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e +#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f +#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214 +#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215 +#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216 +#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217 +#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218 +#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219 +#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a +#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b +#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c +#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a +#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b #define USB_VENDOR_ID_CHERRY 0x046a #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 @@ -1807,17 +1820,19 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, - { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, - { USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, - { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, + { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, -- cgit v1.2.3 From 7ac9da10af7ffd94cfd07e097b93d588bbd32b75 Mon Sep 17 00:00:00 2001 From: Burman Yan Date: Wed, 22 Nov 2006 20:54:38 +0200 Subject: USB serial: replace kmalloc+memset with kzalloc Replace kmalloc+memset with kzalloc Signed-off-by: Yan Burman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ark3116.c | 3 +-- drivers/usb/serial/console.c | 6 ++---- drivers/usb/serial/garmin_gps.c | 3 +-- drivers/usb/serial/mos7840.c | 3 +-- drivers/usb/serial/ti_usb_3410_5052.c | 3 +-- 5 files changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index ca52f12f0e24..863966c1c5ac 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial) int i; for (i = 0; i < serial->num_ports; ++i) { - priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL); + priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL); if (!priv) goto cleanup; - memset(priv, 0x00, sizeof (struct ark3116_private)); spin_lock_init(&priv->lock); usb_set_serial_port_data(serial->port[i], priv); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 3a9073dbfe6a..7167728d764c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options) if (serial->type->set_termios) { /* build up a fake tty structure so that the open call has something * to look at to get the cflag value */ - tty = kmalloc (sizeof (*tty), GFP_KERNEL); + tty = kzalloc(sizeof(*tty), GFP_KERNEL); if (!tty) { err ("no more memory"); return -ENOMEM; } - termios = kmalloc (sizeof (*termios), GFP_KERNEL); + termios = kzalloc(sizeof(*termios), GFP_KERNEL); if (!termios) { err ("no more memory"); kfree (tty); return -ENOMEM; } - memset (tty, 0x00, sizeof(*tty)); - memset (termios, 0x00, sizeof(*termios)); termios->c_cflag = cflag; tty->termios = termios; port->tty = tty; diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 4543152a9966..6530d391ebed 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial) dbg("%s", __FUNCTION__); - garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); + garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL); if (garmin_data_p == NULL) { dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); return -ENOMEM; } - memset (garmin_data_p, 0, sizeof(struct garmin_data)); init_timer(&garmin_data_p->timer); spin_lock_init(&garmin_data_p->lock); INIT_LIST_HEAD(&garmin_data_p->pktlist); diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 5b71962d0351..02c89e10b2cf 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -2596,12 +2596,11 @@ static int mos7840_startup(struct usb_serial *serial) /* set up port private structures */ for (i = 0; i < serial->num_ports; ++i) { - mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL); + mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7840_port == NULL) { err("%s - Out of memory", __FUNCTION__); return -ENOMEM; } - memset(mos7840_port, 0, sizeof(struct moschip_port)); /* Initialize all port interrupt end point to port 0 int endpoint * * Our device has only one interrupt end point comman to all port */ diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index bbbb993447b9..ae98d8cbdbb8 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -461,13 +461,12 @@ static int ti_startup(struct usb_serial *serial) /* set up port structures */ for (i = 0; i < serial->num_ports; ++i) { - tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL); + tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL); if (tport == NULL) { dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); status = -ENOMEM; goto free_tports; } - memset(tport, 0, sizeof(struct ti_port)); spin_lock_init(&tport->tp_lock); tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0; -- cgit v1.2.3 From 8feabf70f51f3f6772e2beda608a0ebca1dbf46a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 24 Nov 2006 03:24:03 +0100 Subject: USB: build the appledisplay driver We do already have both the code and a config option, so why not build this driver? ;-) Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 11dc59540cda..2cba07d31971 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -4,6 +4,7 @@ # obj-$(CONFIG_USB_ADUTUX) += adutux.o +obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o obj-$(CONFIG_USB_AUERSWALD) += auerswald.o obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o -- cgit v1.2.3 From 9aa742ef7c1a7ff8e6df92a93ce3688e99fa66e3 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 23 Nov 2006 12:45:31 +0100 Subject: USB: endianness fix for asix.c the latest update for asix.c reverted some endianness fixes. This reinstates them. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/asix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/asix.c b/drivers/usb/net/asix.c index 881841e600de..95e682e2c9d6 100644 --- a/drivers/usb/net/asix.c +++ b/drivers/usb/net/asix.c @@ -249,9 +249,9 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; req->bRequest = cmd; - req->wValue = value; - req->wIndex = index; - req->wLength = size; + req->wValue = cpu_to_le16(value); + req->wIndex = cpu_to_le16(index); + req->wLength = cpu_to_le16(size); usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), -- cgit v1.2.3 From 10c8211c634f759633ffcdc3b0e2913963b32abc Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 23 Nov 2006 15:40:17 +0100 Subject: USB: pegasus error path not resetting task's state there is an error path in the pegasus driver which can leave the task in TASK_UNINTERRUPTIBLE. Depending on when it schedules next, this can be bad. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/net/pegasus.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 33abbd2176b6..69eb0db399df 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -163,6 +163,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, /* using ATOMIC, we'd never wake up if we slept */ if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { + set_current_state(TASK_RUNNING); if (ret == -ENODEV) netif_device_detach(pegasus->net); if (netif_msg_drv(pegasus)) -- cgit v1.2.3 From 7e27780ffdf5fcf8675dfb278ca316a1f2b7e179 Mon Sep 17 00:00:00 2001 From: Sarah Bailey Date: Sat, 18 Nov 2006 22:30:16 -0800 Subject: USB: added dynamic major number for USB endpoints This patch is an update for Greg K-H's proposed usbfs2: http://sourceforge.net/mailarchive/message.php?msg_id=19295229 It creates a dynamic major for USB endpoints and fixes the endpoint minor calculation. Signed-off-by: Sarah Bailey Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 98 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 3b2d137912be..c505b767cee1 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -10,15 +10,20 @@ */ #include +#include +#include #include #include "usb.h" -/* endpoint stuff */ +#define MAX_ENDPOINT_MINORS (64*128*32) +static int usb_endpoint_major; +static DEFINE_IDR(endpoint_idr); struct ep_device { struct usb_endpoint_descriptor *desc; struct usb_device *udev; struct device dev; + int minor; }; #define to_ep_device(_dev) \ container_of(_dev, struct ep_device, dev) @@ -152,6 +157,55 @@ static struct attribute_group ep_dev_attr_grp = { .attrs = ep_dev_attrs, }; +static int usb_endpoint_major_init(void) +{ + dev_t dev; + int error; + + error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS, + "usb_endpoint"); + if (error) { + err("unable to get a dynamic major for usb endpoints"); + return error; + } + usb_endpoint_major = MAJOR(dev); + + return error; +} + +static void usb_endpoint_major_cleanup(void) +{ + unregister_chrdev_region(MKDEV(usb_endpoint_major, 0), + MAX_ENDPOINT_MINORS); +} + +static int endpoint_get_minor(struct ep_device *ep_dev) +{ + static DEFINE_MUTEX(minor_lock); + int retval = -ENOMEM; + int id; + + mutex_lock(&minor_lock); + if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0) + goto exit; + + retval = idr_get_new(&endpoint_idr, ep_dev, &id); + if (retval < 0) { + if (retval == -EAGAIN) + retval = -ENOMEM; + goto exit; + } + ep_dev->minor = id & MAX_ID_MASK; +exit: + mutex_unlock(&minor_lock); + return retval; +} + +static void endpoint_free_minor(struct ep_device *ep_dev) +{ + idr_remove(&endpoint_idr, ep_dev->minor); +} + static struct endpoint_class { struct kref kref; struct class *class; @@ -176,11 +230,20 @@ static int init_endpoint_class(void) ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); if (IS_ERR(ep_class->class)) { result = IS_ERR(ep_class->class); - kfree(ep_class); - ep_class = NULL; - goto exit; + goto class_create_error; } + result = usb_endpoint_major_init(); + if (result) + goto endpoint_major_error; + + goto exit; + +endpoint_major_error: + class_destroy(ep_class->class); +class_create_error: + kfree(ep_class); + ep_class = NULL; exit: return result; } @@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref) class_destroy(ep_class->class); kfree(ep_class); ep_class = NULL; + usb_endpoint_major_cleanup(); } static void destroy_endpoint_class(void) @@ -213,7 +277,6 @@ int usb_create_ep_files(struct device *parent, { char name[8]; struct ep_device *ep_dev; - int minor; int retval; retval = init_endpoint_class(); @@ -226,12 +289,16 @@ int usb_create_ep_files(struct device *parent, goto error_alloc; } - /* fun calculation to determine the minor of this endpoint */ - minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); + retval = endpoint_get_minor(ep_dev); + if (retval) { + dev_err(parent, "can not allocate minor number for %s", + ep_dev->dev.bus_id); + goto error_register; + } ep_dev->desc = &endpoint->desc; ep_dev->udev = udev; - ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... + ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor); ep_dev->dev.class = ep_class->class; ep_dev->dev.parent = parent; ep_dev->dev.release = ep_device_release; @@ -241,7 +308,7 @@ int usb_create_ep_files(struct device *parent, retval = device_register(&ep_dev->dev); if (retval) - goto error_register; + goto error_chrdev; retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); if (retval) goto error_group; @@ -261,6 +328,9 @@ error_group: destroy_endpoint_class(); return retval; +error_chrdev: + endpoint_free_minor(ep_dev); + error_register: kfree(ep_dev); error_alloc: @@ -271,14 +341,16 @@ exit: void usb_remove_ep_files(struct usb_host_endpoint *endpoint) { + struct ep_device *ep_dev = endpoint->ep_dev; - if (endpoint->ep_dev) { + if (ep_dev) { char name[8]; sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); - sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); - sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); - device_unregister(&endpoint->ep_dev->dev); + sysfs_remove_link(&ep_dev->dev.parent->kobj, name); + sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); + endpoint_free_minor(ep_dev); + device_unregister(&ep_dev->dev); endpoint->ep_dev = NULL; destroy_endpoint_class(); } -- cgit v1.2.3 From 958e8741bf9ff5d0f0b82b7cef578e96c764a288 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Apr 2002 12:14:34 -0700 Subject: USB: add driver for the USB debug devices It's a simple usb-serial driver that just creates a tty device to read and write from. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 11 +++++++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/usb_debug.c | 65 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 drivers/usb/serial/usb_debug.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 2a8dd4cc943d..2f4d303ee36f 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET To compile this driver as a module, choose M here: the module will be called omninet. +config USB_SERIAL_DEBUG + tristate "USB Debugging Device" + depends on USB_SERIAL + help + Say Y here if you have a USB debugging device used to recieve + debugging data from another machine. The most common of these + devices is the NetChip TurboCONNECT device. + + To compile this driver as a module, choose M here: the + module will be called usb-debug. + config USB_EZUSB bool depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index a5047dc599bb..61166ad450e6 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o +obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c new file mode 100644 index 000000000000..257a5e436873 --- /dev/null +++ b/drivers/usb/serial/usb_debug.c @@ -0,0 +1,65 @@ +/* + * USB Debug cable driver + * + * Copyright (C) 2006 Greg Kroah-Hartman + * + * 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 +#include +#include +#include +#include +#include + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0525, 0x127a) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver debug_driver = { + .name = "debug", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver debug_device = { + .driver = { + .owner = THIS_MODULE, + .name = "debug", + }, + .id_table = id_table, + .num_interrupt_in = NUM_DONT_CARE, + .num_bulk_in = NUM_DONT_CARE, + .num_bulk_out = NUM_DONT_CARE, + .num_ports = 1, +}; + +static int __init debug_init(void) +{ + int retval; + + retval = usb_serial_register(&debug_device); + if (retval) + return retval; + retval = usb_register(&debug_driver); + if (retval) + usb_serial_deregister(&debug_device); + return retval; +} + +static void __exit debug_exit(void) +{ + usb_deregister(&debug_driver); + usb_serial_deregister(&debug_device); +} + +module_init(debug_init); +module_exit(debug_exit); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From c066475e1fe3b3afbd613ddf5f1eca9be4fb6de0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 11 Aug 2006 01:55:12 -0700 Subject: USB: create a new thread for every USB device found during the probe sequence Might speed up some systems. If nothing else, a bad driver should not take the whole USB subsystem down with it. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/Kconfig | 15 +++++++++ drivers/usb/core/hub.c | 81 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 74 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 6e3b5358a760..f8324d8d06ac 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -72,6 +72,21 @@ config USB_SUSPEND If you are unsure about this, say N here. +config USB_MULTITHREAD_PROBE + bool "USB Multi-threaded probe (EXPERIMENTAL)" + depends on USB && EXPERIMENTAL + default n + help + Say Y here if you want the USB core to spawn a new thread for + every USB device that is probed. This can cause a small speedup + in boot times on systems with a lot of different USB devices. + + This option should be safe to enable, but if any odd probing + problems are found, please disable it, or dynamically turn it + off in the /sys/module/usbcore/parameters/multithread_probe + file + + When in doubt, say N. config USB_OTG bool diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c961a32f3176..f6e692180587 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -87,6 +87,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); static struct task_struct *khubd_task; +/* multithreaded probe logic */ +static int multithread_probe = +#ifdef CONFIG_USB_MULTITHREAD_PROBE + 1; +#else + 0; +#endif +module_param(multithread_probe, bool, S_IRUGO); +MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread"); + /* cycle leds on hubs that aren't blinking for attention */ static int blinkenlights = 0; module_param (blinkenlights, bool, S_IRUGO); @@ -1238,29 +1248,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string) static int __usb_port_suspend(struct usb_device *, int port1); #endif -/** - * usb_new_device - perform initial device setup (usbcore-internal) - * @udev: newly addressed device (in ADDRESS state) - * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors - * for any device configuration. The caller must have locked either - * the parent hub (if udev is a normal device) or else the - * usb_bus_list_lock (if udev is a root hub). The parent's pointer to - * udev has already been installed, but udev is not yet visible through - * sysfs or other filesystem code. - * - * Returns 0 for success (device is configured and listed, with its - * interfaces, in sysfs); else a negative errno value. - * - * This call is synchronous, and may not be used in an interrupt context. - * - * Only the hub driver or root-hub registrar should ever call this. - */ -int usb_new_device(struct usb_device *udev) +static int __usb_new_device(void *void_data) { + struct usb_device *udev = void_data; int err; + /* Lock ourself into memory in order to keep a probe sequence + * sleeping in a new thread from allowing us to be unloaded. + */ + if (!try_module_get(THIS_MODULE)) + return -EINVAL; + err = usb_get_configuration(udev); if (err < 0) { dev_err(&udev->dev, "can't read configurations, error %d\n", @@ -1356,13 +1354,52 @@ int usb_new_device(struct usb_device *udev) goto fail; } - return 0; +exit: + module_put(THIS_MODULE); + return err; fail: usb_set_device_state(udev, USB_STATE_NOTATTACHED); - return err; + goto exit; } +/** + * usb_new_device - perform initial device setup (usbcore-internal) + * @udev: newly addressed device (in ADDRESS state) + * + * This is called with devices which have been enumerated, but not yet + * configured. The device descriptor is available, but not descriptors + * for any device configuration. The caller must have locked either + * the parent hub (if udev is a normal device) or else the + * usb_bus_list_lock (if udev is a root hub). The parent's pointer to + * udev has already been installed, but udev is not yet visible through + * sysfs or other filesystem code. + * + * The return value for this function depends on if the + * multithread_probe variable is set or not. If it's set, it will + * return a if the probe thread was successfully created or not. If the + * variable is not set, it will return if the device is configured + * properly or not. interfaces, in sysfs); else a negative errno value. + * + * This call is synchronous, and may not be used in an interrupt context. + * + * Only the hub driver or root-hub registrar should ever call this. + */ +int usb_new_device(struct usb_device *udev) +{ + struct task_struct *probe_task; + int ret = 0; + + if (multithread_probe) { + probe_task = kthread_run(__usb_new_device, udev, + "usb-probe-%s", udev->devnum); + if (IS_ERR(probe_task)) + ret = PTR_ERR(probe_task); + } else + ret = __usb_new_device(udev); + + return ret; +} static int hub_port_status(struct usb_hub *hub, int port1, u16 *status, u16 *change) -- cgit v1.2.3 From 8c03356a559ced6fa78931f498193f776d67e445 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Nov 2006 14:42:16 -0500 Subject: EHCI: Fix root-hub and port suspend/resume problems This patch (as738b) fixes numerous problems in the controller/root-hub suspend/resume/remote-wakeup support in ehci-hcd: The bus_resume() routine should wake up only the ports that were suspended by bus_suspend(). Ports that were already suspended should remain that way. The interrupt mask is used to detect loss of power in the bus_resume() routine (if the mask is 0 then power was lost). However bus_suspend() always sets the mask to 0. Instead the mask should retain its normal value, with port-change-detect interrupts disabled if remote wakeup is turned off. The interrupt mask should be reset to its correct value at the end of bus_resume() regardless of whether power was lost. bus_resume() reinitializes the operational registers if power was lost. However those registers are not in the aux power well, hence they can lose their values whenever the controller is put into D3. They should always be reinitialized. When a port-change interrupt occurs and the root hub is suspended, the interrupt handler should request a root-hub resume instead of starting up the controller all by itself. There's no need for the interrupt handler to request a root-hub resume every time a suspended port sends a remote-wakeup request. The pci_resume() method doesn't need to check for connected ports when deciding whether or not to reset the controller. It can make that decision based on whether Vaux power was maintained. Even when the controller does not need to be reset, pci_resume() must undo the effect of pci_suspend() by re-enabling the interrupt mask. If power was lost, pci_resume() must not call ehci_run(). At this point the root hub is still supposed to be suspended, not running. It's enough to rewrite the command register and set the configured_flag. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 6 ++-- drivers/usb/host/ehci-hub.c | 67 ++++++++++++++++++++++++++++----------------- drivers/usb/host/ehci-pci.c | 40 +++++++++++---------------- drivers/usb/host/ehci.h | 1 + 4 files changed, 61 insertions(+), 53 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index f2ceb5fdbeb7..025d33313681 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -619,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) unsigned i = HCS_N_PORTS (ehci->hcs_params); /* resume root hub? */ - status = readl (&ehci->regs->command); - if (!(status & CMD_RUN)) - writel (status | CMD_RUN, &ehci->regs->command); + if (!(readl(&ehci->regs->command) & CMD_RUN)) + usb_hcd_resume_root_hub(hcd); while (i--) { int pstatus = readl (&ehci->regs->port_status [i]); @@ -638,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) */ ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); - usb_hcd_resume_root_hub(hcd); } } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 0a56dfa2745d..bfe5f307cba6 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); int port; + int mask; if (time_before (jiffies, ehci->next_statechange)) msleep(5); @@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->reclaim_ready = 1; ehci_work(ehci); - /* suspend any active/unsuspended ports, maybe allow wakeup */ + /* Unlike other USB host controller types, EHCI doesn't have + * any notion of "global" or bus-wide suspend. The driver has + * to manually suspend all the active unsuspended ports, and + * then manually resume them in the bus_resume() routine. + */ + ehci->bus_suspended = 0; while (port--) { u32 __iomem *reg = &ehci->regs->port_status [port]; u32 t1 = readl (reg) & ~PORT_RWC_BITS; u32 t2 = t1; - if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) + /* keep track of which ports we suspend */ + if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) && + !(t1 & PORT_SUSPEND)) { t2 |= PORT_SUSPEND; + set_bit(port, &ehci->bus_suspended); + } + + /* enable remote wakeup on all ports */ if (device_may_wakeup(&hcd->self.root_hub->dev)) t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; else @@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci_halt (ehci); hcd->state = HC_STATE_SUSPENDED; + /* allow remote wakeup */ + mask = INTR_MASK; + if (!device_may_wakeup(&hcd->self.root_hub->dev)) + mask &= ~STS_PCD; + writel(mask, &ehci->regs->intr_enable); + readl(&ehci->regs->intr_enable); + ehci->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irq (&ehci->lock); return 0; @@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); u32 temp; int i; - int intr_enable; if (time_before (jiffies, ehci->next_statechange)) msleep(5); @@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd) * the last user of the controller, not reset/pm hardware keeping * state we gave to it. */ + temp = readl(&ehci->regs->intr_enable); + ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss"); - /* re-init operational registers in case we lost power */ - if (readl (&ehci->regs->intr_enable) == 0) { - /* at least some APM implementations will try to deliver - * IRQs right away, so delay them until we're ready. - */ - intr_enable = 1; - writel (0, &ehci->regs->segment); - writel (ehci->periodic_dma, &ehci->regs->frame_list); - writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); - } else - intr_enable = 0; - ehci_dbg(ehci, "resume root hub%s\n", - intr_enable ? " after power loss" : ""); + /* at least some APM implementations will try to deliver + * IRQs right away, so delay them until we're ready. + */ + writel(0, &ehci->regs->intr_enable); + + /* re-init operational registers */ + writel(0, &ehci->regs->segment); + writel(ehci->periodic_dma, &ehci->regs->frame_list); + writel((u32) ehci->async->qh_dma, &ehci->regs->async_next); /* restore CMD_RUN, framelist size, and irq threshold */ writel (ehci->command, &ehci->regs->command); - /* take ports out of suspend */ + /* manually resume the ports we suspended during bus_suspend() */ i = HCS_N_PORTS (ehci->hcs_params); while (i--) { temp = readl (&ehci->regs->port_status [i]); temp &= ~(PORT_RWC_BITS | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); - if (temp & PORT_SUSPEND) { + if (test_bit(i, &ehci->bus_suspended) && + (temp & PORT_SUSPEND)) { ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); temp |= PORT_RESUME; } @@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd) mdelay (20); while (i--) { temp = readl (&ehci->regs->port_status [i]); - if ((temp & PORT_SUSPEND) == 0) - continue; - temp &= ~(PORT_RWC_BITS | PORT_RESUME); - writel (temp, &ehci->regs->port_status [i]); - ehci_vdbg (ehci, "resumed port %d\n", i + 1); + if (test_bit(i, &ehci->bus_suspended) && + (temp & PORT_SUSPEND)) { + temp &= ~(PORT_RWC_BITS | PORT_RESUME); + writel (temp, &ehci->regs->port_status [i]); + ehci_vdbg (ehci, "resumed port %d\n", i + 1); + } } (void) readl (&ehci->regs->command); @@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) hcd->state = HC_STATE_RUNNING; /* Now we can safely re-enable irqs */ - if (intr_enable) - writel (INTR_MASK, &ehci->regs->intr_enable); + writel(INTR_MASK, &ehci->regs->intr_enable); spin_unlock_irq (&ehci->lock); return 0; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index e51c1ed81ac4..4bc7970ba3ef 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message) static int ehci_pci_resume(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); - unsigned port; struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - int retval = -EINVAL; // maybe restore FLADJ @@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd) /* Mark hardware accessible again as we are out of D3 state by now */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - /* If CF is clear, we lost PCI Vaux power and need to restart. */ - if (readl(&ehci->regs->configured_flag) != FLAG_CF) - goto restart; - - /* If any port is suspended (or owned by the companion), - * we know we can/must resume the HC (and mustn't reset it). - * We just defer that to the root hub code. + /* If CF is still set, we maintained PCI Vaux power. + * Just undo the effect of ehci_pci_suspend(). */ - for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { - u32 status; - port--; - status = readl(&ehci->regs->port_status [port]); - if (!(status & PORT_POWER)) - continue; - if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { - usb_hcd_resume_root_hub(hcd); - return 0; - } + if (readl(&ehci->regs->configured_flag) == FLAG_CF) { + int mask = INTR_MASK; + + if (!device_may_wakeup(&hcd->self.root_hub->dev)) + mask &= ~STS_PCD; + writel(mask, &ehci->regs->intr_enable); + readl(&ehci->regs->intr_enable); + return 0; } -restart: ehci_dbg(ehci, "lost power, restarting\n"); usb_root_hub_lost_power(hcd->self.root_hub); @@ -307,13 +297,15 @@ restart: ehci_work(ehci); spin_unlock_irq(&ehci->lock); - /* restart; khubd will disconnect devices */ - retval = ehci_run(hcd); - /* here we "know" root ports should always stay powered */ ehci_port_power(ehci, 1); - return retval; + writel(ehci->command, &ehci->regs->command); + writel(FLAG_CF, &ehci->regs->configured_flag); + readl(&ehci->regs->command); /* unblock posted writes */ + + hcd->state = HC_STATE_SUSPENDED; + return 0; } #endif diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index bbc3082a73d7..74dbc6c8228f 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */ /* per root hub port */ unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; + unsigned long bus_suspended; /* per-HC memory pools (could be per-bus, but ...) */ struct dma_pool *qh_pool; /* qh per active urb */ -- cgit v1.2.3 From 40f122f343797d02390c5a157372cac0c5b50bb7 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 9 Nov 2006 14:44:33 -0500 Subject: USB: Add autosuspend support to the hub driver This patch (as742b) adds autosuspend/autoresume support to the USB hub driver. The largest aspect of the change is that we no longer need a special flag for root hubs that want to be resumed. Now every hub is autoresumed whenever khubd needs to access it. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f6e692180587..55812a5ac661 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -65,7 +65,6 @@ struct usb_hub { unsigned limited_power:1; unsigned quiescing:1; unsigned activating:1; - unsigned resume_root_hub:1; unsigned has_indicators:1; u8 indicator[USB_MAXCHILDREN]; @@ -328,6 +327,9 @@ static void kick_khubd(struct usb_hub *hub) { unsigned long flags; + /* Suppress autosuspend until khubd runs */ + to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; + spin_lock_irqsave(&hub_event_lock, flags); if (list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); @@ -509,7 +511,6 @@ static void hub_quiesce(struct usb_hub *hub) /* (nonblocking) khubd and related activity won't re-trigger */ hub->quiescing = 1; hub->activating = 0; - hub->resume_root_hub = 0; /* (blocking) stop khubd and related activity */ usb_kill_urb(hub->urb); @@ -525,7 +526,7 @@ static void hub_activate(struct usb_hub *hub) hub->quiescing = 0; hub->activating = 1; - hub->resume_root_hub = 0; + status = usb_submit_urb(hub->urb, GFP_NOIO); if (status < 0) dev_err(hub->intfdev, "activate --> %d\n", status); @@ -940,6 +941,7 @@ descriptor_error: INIT_WORK(&hub->leds, led_work, hub); usb_set_intfdata (intf, hub); + intf->needs_remote_wakeup = 1; if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs++; @@ -1938,6 +1940,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) } } + dev_dbg(&intf->dev, "%s\n", __FUNCTION__); + /* "global suspend" of the downstream HC-to-USB interface */ if (!hdev->parent) { struct usb_bus *bus = hdev->bus; @@ -1960,10 +1964,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) static int hub_resume(struct usb_interface *intf) { - struct usb_device *hdev = interface_to_usbdev(intf); struct usb_hub *hub = usb_get_intfdata (intf); + struct usb_device *hdev = hub->hdev; int status; + dev_dbg(&intf->dev, "%s\n", __FUNCTION__); + /* "global resume" of the downstream HC-to-USB interface */ if (!hdev->parent) { struct usb_bus *bus = hdev->bus; @@ -2002,7 +2008,6 @@ void usb_resume_root_hub(struct usb_device *hdev) { struct usb_hub *hub = hdev_to_hub(hdev); - hub->resume_root_hub = 1; kick_khubd(hub); } @@ -2639,16 +2644,13 @@ static void hub_events(void) intf = to_usb_interface(hub->intfdev); hub_dev = &intf->dev; - i = hub->resume_root_hub; - - dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n", + dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", hdev->state, hub->descriptor ? hub->descriptor->bNbrPorts : 0, /* NOTE: expects max 15 ports... */ (u16) hub->change_bits[0], - (u16) hub->event_bits[0], - i ? ", resume root" : ""); + (u16) hub->event_bits[0]); usb_get_intf(intf); spin_unlock_irq(&hub_event_lock); @@ -2669,16 +2671,16 @@ static void hub_events(void) goto loop; } - /* Is this is a root hub wanting to reactivate the downstream - * ports? If so, be sure the interface resumes even if its - * stub "device" node was never suspended. - */ - if (i) - usb_autoresume_device(hdev, 0); + /* Autoresume */ + ret = usb_autopm_get_interface(intf); + if (ret) { + dev_dbg(hub_dev, "Can't autoresume: %d\n", ret); + goto loop; + } - /* If this is an inactive or suspended hub, do nothing */ + /* If this is an inactive hub, do nothing */ if (hub->quiescing) - goto loop; + goto loop_autopm; if (hub->error) { dev_dbg (hub_dev, "resetting for error %d\n", @@ -2688,7 +2690,7 @@ static void hub_events(void) if (ret) { dev_dbg (hub_dev, "error resetting hub: %d\n", ret); - goto loop; + goto loop_autopm; } hub->nerrors = 0; @@ -2816,6 +2818,10 @@ static void hub_events(void) if (!hdev->parent && !hub->busy_bits[0]) usb_enable_root_hub_irq(hdev->bus); +loop_autopm: + /* Allow autosuspend if we're not going to run again */ + if (list_empty(&hub->event_list)) + usb_autopm_enable(intf); loop: usb_unlock_device(hdev); usb_put_intf(intf); @@ -2857,6 +2863,7 @@ static struct usb_driver hub_driver = { .post_reset = hub_post_reset, .ioctl = hub_ioctl, .id_table = hub_id_table, + .supports_autosuspend = 1, }; int usb_hub_init(void) -- cgit v1.2.3 From 1f9fc882d92f3ff390455836f98d7ddc36d4e4c3 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 20 Nov 2006 11:06:59 -0500 Subject: OHCI: make autostop conditional on CONFIG_PM Unlike UHCI, OHCI does not exert any DMA load on the system when no devices are connected. Consequently there is no advantage to doing an autostop other than the power savings, so we shouldn't compile the necessary code unless CONFIG_PM is enabled. This patch (as820) makes the root-hub suspend and resume routines conditional on CONFIG_PM. It also prevents autostop from activating if the device_may_wakeup flag isn't set; some people use this flag to alert the driver about Resume-Detect bugs in the hardware. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hub.c | 133 ++++++++++++++++++++++++++------------------ 1 file changed, 79 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 4c9492779ede..2441642cb7b4 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -56,7 +56,6 @@ static void finish_unlinks (struct ohci_hcd *, u16); #ifdef CONFIG_PM static int ohci_restart(struct ohci_hcd *ohci); -#endif static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) __releases(ohci->lock) @@ -187,7 +186,6 @@ __acquires(ohci->lock) ohci_dbg (ohci, "lost power\n"); status = -EBUSY; } -#ifdef CONFIG_PM if (status == -EBUSY) { if (!autostopped) { spin_unlock_irq (&ohci->lock); @@ -197,7 +195,6 @@ __acquires(ohci->lock) } return status; } -#endif if (status != -EINPROGRESS) return status; if (autostopped) @@ -291,8 +288,6 @@ skip_resume: return 0; } -#ifdef CONFIG_PM - static int ohci_bus_suspend (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); @@ -330,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd) return rc; } +/* Carry out polling-, autostop-, and autoresume-related state changes */ +static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, + int any_connected) +{ + int poll_rh = 1; + + switch (ohci->hc_control & OHCI_CTRL_HCFS) { + + case OHCI_USB_OPER: + /* keep on polling until we know a device is connected + * and RHSC is enabled */ + if (!ohci->autostop) { + if (any_connected || + !device_may_wakeup(&ohci_to_hcd(ohci) + ->self.root_hub->dev)) { + if (ohci_readl(ohci, &ohci->regs->intrenable) & + OHCI_INTR_RHSC) + poll_rh = 0; + } else { + ohci->autostop = 1; + ohci->next_statechange = jiffies + HZ; + } + + /* if no devices have been attached for one second, autostop */ + } else { + if (changed || any_connected) { + ohci->autostop = 0; + ohci->next_statechange = jiffies + + STATECHANGE_DELAY; + } else if (time_after_eq(jiffies, + ohci->next_statechange) + && !ohci->ed_rm_list + && !(ohci->hc_control & + OHCI_SCHED_ENABLES)) { + ohci_rh_suspend(ohci, 1); + } + } + break; + + /* if there is a port change, autostart or ask to be resumed */ + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + if (changed) { + if (ohci->autostop) + ohci_rh_resume(ohci); + else + usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); + } else { + /* everything is idle, no need for polling */ + poll_rh = 0; + } + break; + } + return poll_rh; +} + +#else /* CONFIG_PM */ + +static inline int ohci_rh_resume(struct ohci_hcd *ohci) +{ + return 0; +} + +/* Carry out polling-related state changes. + * autostop isn't used when CONFIG_PM is turned off. + */ +static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, + int any_connected) +{ + int poll_rh = 1; + + /* keep on polling until RHSC is enabled */ + if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) + poll_rh = 0; + return poll_rh; +} + #endif /* CONFIG_PM */ /*-------------------------------------------------------------------------*/ @@ -382,55 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) } } - hcd->poll_rh = 1; - - /* carry out appropriate state changes */ - switch (ohci->hc_control & OHCI_CTRL_HCFS) { - - case OHCI_USB_OPER: - /* keep on polling until we know a device is connected - * and RHSC is enabled */ - if (!ohci->autostop) { - if (any_connected) { - if (ohci_readl(ohci, &ohci->regs->intrenable) & - OHCI_INTR_RHSC) - hcd->poll_rh = 0; - } else { - ohci->autostop = 1; - ohci->next_statechange = jiffies + HZ; - } - - /* if no devices have been attached for one second, autostop */ - } else { - if (changed || any_connected) { - ohci->autostop = 0; - ohci->next_statechange = jiffies + - STATECHANGE_DELAY; - } else if (device_may_wakeup(&hcd->self.root_hub->dev) - && time_after_eq(jiffies, - ohci->next_statechange) - && !ohci->ed_rm_list - && !(ohci->hc_control & - OHCI_SCHED_ENABLES)) { - ohci_rh_suspend (ohci, 1); - } - } - break; - - /* if there is a port change, autostart or ask to be resumed */ - case OHCI_USB_SUSPEND: - case OHCI_USB_RESUME: - if (changed) { - if (ohci->autostop) - ohci_rh_resume (ohci); - else - usb_hcd_resume_root_hub (hcd); - } else { - /* everything is idle, no need for polling */ - hcd->poll_rh = 0; - } - break; - } + hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, + any_connected); done: spin_unlock_irqrestore (&ohci->lock, flags); -- cgit v1.2.3 From ce3615879ae85373c03744b45b7c2d7ae5e29b2a Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 20 Nov 2006 11:12:22 -0500 Subject: USB: struct usb_device: change flag to bitflag This patch (as816) changes an existing flag in the usb_device structure to a bitflag, preparing the way for more bitflags to come in the future. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 2 +- include/linux/usb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 7729c0744886..5684d8722922 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) err = -EINVAL; goto errout; } else { - dev->have_langid = -1; + dev->have_langid = 1; dev->string_langid = tbuf[2] | (tbuf[3]<< 8); /* always use the first langid listed */ dev_dbg (&dev->dev, "default language 0x%04x\n", diff --git a/include/linux/usb.h b/include/linux/usb.h index 864c6c21c21e..5634a2d91ec0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -362,7 +362,7 @@ struct usb_device { u8 portnum; /* Parent port number (origin 1) */ u8 level; /* Number of USB hub ancestors */ - int have_langid; /* whether string_langid is valid */ + unsigned have_langid:1; /* whether string_langid is valid */ int string_langid; /* language ID for strings */ /* static strings from the device */ -- cgit v1.2.3 From d25450c68767481f7c9cc4823a6da8235db40be6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 20 Nov 2006 11:14:30 -0500 Subject: USB hub: simplify remote-wakeup handling This patch (as817) simplifies the remote-wakeup processing in the hub driver. Now instead of using a specialized code path, it relies on the standard USB resume routines. The hub_port_resume() function does an initial get_port_status() to see whether the port has already resumed itself (as it does when a remote-wakeup request is sent). This will slow down handling of other resume events slightly, but not enough to matter. The patch also changes the hub_port_status() routine, making it return an error if a short reply is received. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 43 ++++++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 55812a5ac661..46df5e60764b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1409,10 +1409,12 @@ static int hub_port_status(struct usb_hub *hub, int port1, int ret; ret = get_port_status(hub->hdev, port1, &hub->status->port); - if (ret < 0) + if (ret < 4) { dev_err (hub->intfdev, "%s failed (err = %d)\n", __FUNCTION__, ret); - else { + if (ret >= 0) + ret = -EIO; + } else { *status = le16_to_cpu(hub->status->port.wPortStatus); *change = le16_to_cpu(hub->status->port.wPortChange); ret = 0; @@ -1760,6 +1762,12 @@ static int hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) { int status; + u16 portchange, portstatus; + + /* Skip the initial Clear-Suspend step for a remote wakeup */ + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND)) + goto SuspendCleared; // dev_dbg(hub->intfdev, "resume port %d\n", port1); @@ -1773,9 +1781,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) "can't resume port %d, status %d\n", port1, status); } else { - u16 devstatus; - u16 portchange; - /* drive resume for at least 20 msec */ if (udev) dev_dbg(&udev->dev, "usb %sresume\n", @@ -1790,16 +1795,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) * stop resume signaling. Then finish the resume * sequence. */ - devstatus = portchange = 0; - status = hub_port_status(hub, port1, - &devstatus, &portchange); + status = hub_port_status(hub, port1, &portstatus, &portchange); +SuspendCleared: if (status < 0 - || (devstatus & LIVE_FLAGS) != LIVE_FLAGS - || (devstatus & USB_PORT_STAT_SUSPEND) != 0 + || (portstatus & LIVE_FLAGS) != LIVE_FLAGS + || (portstatus & USB_PORT_STAT_SUSPEND) != 0 ) { dev_dbg(hub->intfdev, "port %d status %04x.%04x after resume, %d\n", - port1, portchange, devstatus, status); + port1, portchange, portstatus, status); if (status >= 0) status = -ENODEV; } else { @@ -1860,23 +1864,16 @@ static int remote_wakeup(struct usb_device *udev) { int status = 0; - /* All this just to avoid sending a port-resume message - * to the parent hub! */ - usb_lock_device(udev); - usb_pm_lock(udev); if (udev->state == USB_STATE_SUSPENDED) { dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); - /* TRSMRCY = 10 msec */ - msleep(10); - status = finish_port_resume(udev); + status = usb_autoresume_device(udev, 1); + + /* Give the interface drivers a chance to do something, + * then autosuspend the device again. */ if (status == 0) - udev->dev.power.power_state.event = PM_EVENT_ON; + usb_autosuspend_device(udev, 1); } - usb_pm_unlock(udev); - - if (status == 0) - usb_autoresume_device(udev, 0); usb_unlock_device(udev); return status; } -- cgit v1.2.3 From ee49fb5dc89d34f1794ac9362fa97c1a640f7ddd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 22 Nov 2006 16:55:54 -0500 Subject: USB: keep count of unsuspended children This patch (as818b) simplifies autosuspend processing by keeping track of the number of unsuspended children of each USB hub. This will permit us to avoid a good deal of unnecessary work all the time; we will no longer have to create a bunch of workqueue entries to carry out autosuspend requests, only to have them fail because one of the hub's children isn't suspended. The basic idea is simple. There already is a usage counter in the usb_device structure for preventing autosuspends. The patch just increments that counter for every unsuspended child. There's only one tricky part: When a device disconnects we need to remember whether it was suspended at the time (leave the counter alone) or not (decrement the counter). Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 34 +++++++++++++++++++++++----------- drivers/usb/core/hub.c | 14 ++++++++++++++ include/linux/usb.h | 1 + 3 files changed, 38 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 40c1bf09b2b7..0fa15bd62c48 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1048,7 +1048,7 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg) /* If the suspend succeeded, propagate it up the tree */ } else if (parent) - usb_autosuspend_device(parent, 0); + usb_autosuspend_device(parent, 1); // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); return status; @@ -1096,9 +1096,25 @@ int usb_resume_both(struct usb_device *udev) /* Propagate the resume up the tree, if necessary */ if (udev->state == USB_STATE_SUSPENDED) { if (parent) { - usb_pm_lock(parent); - parent->auto_pm = 1; - status = usb_resume_both(parent); + status = usb_autoresume_device(parent, 1); + if (status == 0) { + status = usb_resume_device(udev); + if (status) { + usb_autosuspend_device(parent, 1); + + /* It's possible usb_resume_device() + * failed after the port was + * unsuspended, causing udev to be + * logically disconnected. We don't + * want usb_disconnect() to autosuspend + * the parent again, so tell it that + * udev disconnected while still + * suspended. */ + if (udev->state == + USB_STATE_NOTATTACHED) + udev->discon_suspended = 1; + } + } } else { /* We can't progagate beyond the USB subsystem, @@ -1107,11 +1123,9 @@ int usb_resume_both(struct usb_device *udev) if (udev->dev.parent->power.power_state.event != PM_EVENT_ON) status = -EHOSTUNREACH; - } - if (status == 0) - status = usb_resume_device(udev); - if (parent) - usb_pm_unlock(parent); + else + status = usb_resume_device(udev); + } } else { /* Needed only for setting udev->dev.power.power_state.event @@ -1119,8 +1133,6 @@ int usb_resume_both(struct usb_device *udev) status = usb_resume_device(udev); } - /* Now the parent won't suspend until we are finished */ - if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 46df5e60764b..e46d38b18249 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1039,6 +1039,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev) if (udev->children[i]) recursively_mark_NOTATTACHED(udev->children[i]); } + if (udev->state == USB_STATE_SUSPENDED) + udev->discon_suspended = 1; udev->state = USB_STATE_NOTATTACHED; } @@ -1228,6 +1230,14 @@ void usb_disconnect(struct usb_device **pdev) *pdev = NULL; spin_unlock_irq(&device_state_lock); + /* Decrement the parent's count of unsuspended children */ + if (udev->parent) { + usb_pm_lock(udev); + if (!udev->discon_suspended) + usb_autosuspend_device(udev->parent, 1); + usb_pm_unlock(udev); + } + put_device(&udev->dev); } @@ -1356,6 +1366,10 @@ static int __usb_new_device(void *void_data) goto fail; } + /* Increment the parent's count of unsuspended children */ + if (udev->parent) + usb_autoresume_device(udev->parent, 1); + exit: module_put(THIS_MODULE); return err; diff --git a/include/linux/usb.h b/include/linux/usb.h index 5634a2d91ec0..0cd73edeef13 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -362,6 +362,7 @@ struct usb_device { u8 portnum; /* Parent port number (origin 1) */ u8 level; /* Number of USB hub ancestors */ + unsigned discon_suspended:1; /* Disconnected while suspended */ unsigned have_langid:1; /* whether string_langid is valid */ int string_langid; /* language ID for strings */ -- cgit v1.2.3 From 94fcda1f8ab5e0cacc381c5ca1cc9aa6ad523576 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 20 Nov 2006 11:38:46 -0500 Subject: usbcore: remove unused argument in autosuspend Thanks to several earlier patches, usb_autosuspend_device() and usb_autoresume_device() are never called with a second argument other than 1. This patch (as819) removes the now-redundant argument. It also consolidates some common code between those two routines, putting it into a new subroutine called usb_autopm_do_device(). And it includes a sizable kerneldoc update for the affected functions. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 4 +- drivers/usb/core/driver.c | 102 +++++++++++++++++++++++++-------------------- drivers/usb/core/hub.c | 12 +++--- drivers/usb/core/message.c | 6 +-- drivers/usb/core/usb.h | 9 ++-- 5 files changed, 71 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index fed92be63b5e..3ed4cb2d56d9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file) dev = inode->i_private; if (!dev) goto out; - ret = usb_autoresume_device(dev, 1); + ret = usb_autoresume_device(dev); if (ret) goto out; @@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file) releaseintf(ps, ifnum); } destroy_all_async(ps); - usb_autosuspend_device(dev, 1); + usb_autosuspend_device(dev); usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 0fa15bd62c48..d6eb5ce1dd1d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev) if (id) { dev_dbg(dev, "%s - got id\n", __FUNCTION__); - error = usb_autoresume_device(udev, 1); + error = usb_autoresume_device(udev); if (error) return error; @@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev) } else intf->condition = USB_INTERFACE_BOUND; - usb_autosuspend_device(udev, 1); + usb_autosuspend_device(udev); } return error; @@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev) /* Autoresume for set_interface call below */ udev = interface_to_usbdev(intf); - error = usb_autoresume_device(udev, 1); + error = usb_autoresume_device(udev); /* release all urbs for this interface */ usb_disable_interface(interface_to_usbdev(intf), intf); @@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev) intf->needs_remote_wakeup = 0; if (!error) - usb_autosuspend_device(udev, 1); + usb_autosuspend_device(udev); return 0; } @@ -940,6 +940,8 @@ done: return status; } +#ifdef CONFIG_USB_SUSPEND + /* Internal routine to check whether we may autosuspend a device. */ static int autosuspend_check(struct usb_device *udev) { @@ -970,6 +972,12 @@ static int autosuspend_check(struct usb_device *udev) return 0; } +#else + +#define autosuspend_check(udev) 0 + +#endif + /** * usb_suspend_both - suspend a USB device and its interfaces * @udev: the usb_device to suspend @@ -1048,7 +1056,7 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg) /* If the suspend succeeded, propagate it up the tree */ } else if (parent) - usb_autosuspend_device(parent, 1); + usb_autosuspend_device(parent); // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); return status; @@ -1096,11 +1104,11 @@ int usb_resume_both(struct usb_device *udev) /* Propagate the resume up the tree, if necessary */ if (udev->state == USB_STATE_SUSPENDED) { if (parent) { - status = usb_autoresume_device(parent, 1); + status = usb_autoresume_device(parent); if (status == 0) { status = usb_resume_device(udev); if (status) { - usb_autosuspend_device(parent, 1); + usb_autosuspend_device(parent); /* It's possible usb_resume_device() * failed after the port was @@ -1146,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev) #ifdef CONFIG_USB_SUSPEND +/* Internal routine to adjust a device's usage counter and change + * its autosuspend state. + */ +static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt) +{ + int status = 0; + + usb_pm_lock(udev); + udev->pm_usage_cnt += inc_usage_cnt; + WARN_ON(udev->pm_usage_cnt < 0); + if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) { + udev->auto_pm = 1; + status = usb_resume_both(udev); + if (status != 0) + udev->pm_usage_cnt -= inc_usage_cnt; + } else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0) + queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, + USB_AUTOSUSPEND_DELAY); + usb_pm_unlock(udev); + return status; +} + /** * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces * @udev: the usb_device to autosuspend - * @dec_usage_cnt: flag to decrement @udev's PM-usage counter * * This routine should be called when a core subsystem is finished using * @udev and wants to allow it to autosuspend. Examples would be when * @udev's device file in usbfs is closed or after a configuration change. * - * @dec_usage_cnt should be 1 if the subsystem previously incremented - * @udev's usage counter (such as by passing 1 to usb_autoresume_device); - * otherwise it should be 0. - * - * If the usage counter for @udev or any of its active interfaces is greater - * than 0, the autosuspend request will not be queued. (If an interface - * driver does not support autosuspend then its usage counter is permanently - * positive.) Likewise, if an interface driver requires remote-wakeup - * capability during autosuspend but remote wakeup is disabled, the - * autosuspend will fail. + * @udev's usage counter is decremented. If it or any of the usage counters + * for an active interface is greater than 0, no autosuspend request will be + * queued. (If an interface driver does not support autosuspend then its + * usage counter is permanently positive.) Furthermore, if an interface + * driver requires remote-wakeup capability during autosuspend but remote + * wakeup is disabled, the autosuspend will fail. * * Often the caller will hold @udev's device lock, but this is not * necessary. * * This routine can run only in process context. */ -void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) +void usb_autosuspend_device(struct usb_device *udev) { - usb_pm_lock(udev); - udev->pm_usage_cnt -= dec_usage_cnt; - if (autosuspend_check(udev) == 0) - queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, - USB_AUTOSUSPEND_DELAY); - usb_pm_unlock(udev); + int status; + + status = usb_autopm_do_device(udev, -1); // dev_dbg(&udev->dev, "%s: cnt %d\n", // __FUNCTION__, udev->pm_usage_cnt); } @@ -1186,39 +1208,27 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) /** * usb_autoresume_device - immediately autoresume a USB device and its interfaces * @udev: the usb_device to autoresume - * @inc_usage_cnt: flag to increment @udev's PM-usage counter * * This routine should be called when a core subsystem wants to use @udev - * and needs to guarantee that it is not suspended. In addition, the - * caller can prevent @udev from being autosuspended subsequently. (Note - * that this will not prevent suspend events originating in the PM core.) - * Examples would be when @udev's device file in usbfs is opened (autosuspend - * should be prevented until the file is closed) or when a remote-wakeup - * request is received (later autosuspends should not be prevented). + * and needs to guarantee that it is not suspended. No autosuspend will + * occur until usb_autosuspend_device is called. (Note that this will not + * prevent suspend events originating in the PM core.) Examples would be + * when @udev's device file in usbfs is opened or when a remote-wakeup + * request is received. * - * @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent - * autosuspends. This prevention will persist until the usage counter is - * decremented again (such as by passing 1 to usb_autosuspend_device). - * Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged. - * Regardless, if the autoresume fails then the usage counter is not - * incremented. + * @udev's usage counter is incremented to prevent subsequent autosuspends. + * However if the autoresume fails then the usage counter is re-decremented. * * Often the caller will hold @udev's device lock, but this is not * necessary (and attempting it might cause deadlock). * * This routine can run only in process context. */ -int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) +int usb_autoresume_device(struct usb_device *udev) { int status; - usb_pm_lock(udev); - udev->pm_usage_cnt += inc_usage_cnt; - udev->auto_pm = 1; - status = usb_resume_both(udev); - if (status != 0) - udev->pm_usage_cnt -= inc_usage_cnt; - usb_pm_unlock(udev); + status = usb_autopm_do_device(udev, 1); // dev_dbg(&udev->dev, "%s: status %d cnt %d\n", // __FUNCTION__, status, udev->pm_usage_cnt); return status; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index e46d38b18249..0ce393eb3c4b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1234,7 +1234,7 @@ void usb_disconnect(struct usb_device **pdev) if (udev->parent) { usb_pm_lock(udev); if (!udev->discon_suspended) - usb_autosuspend_device(udev->parent, 1); + usb_autosuspend_device(udev->parent); usb_pm_unlock(udev); } @@ -1368,7 +1368,7 @@ static int __usb_new_device(void *void_data) /* Increment the parent's count of unsuspended children */ if (udev->parent) - usb_autoresume_device(udev->parent, 1); + usb_autoresume_device(udev->parent); exit: module_put(THIS_MODULE); @@ -1881,12 +1881,12 @@ static int remote_wakeup(struct usb_device *udev) usb_lock_device(udev); if (udev->state == USB_STATE_SUSPENDED) { dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); - status = usb_autoresume_device(udev, 1); + status = usb_autoresume_device(udev); /* Give the interface drivers a chance to do something, * then autosuspend the device again. */ if (status == 0) - usb_autosuspend_device(udev, 1); + usb_autosuspend_device(udev); } usb_unlock_device(udev); return status; @@ -3099,7 +3099,7 @@ int usb_reset_composite_device(struct usb_device *udev, } /* Prevent autosuspend during the reset */ - usb_autoresume_device(udev, 1); + usb_autoresume_device(udev); if (iface && iface->condition != USB_INTERFACE_BINDING) iface = NULL; @@ -3142,7 +3142,7 @@ int usb_reset_composite_device(struct usb_device *udev, } } - usb_autosuspend_device(udev, 1); + usb_autosuspend_device(udev); return ret; } EXPORT_SYMBOL(usb_reset_composite_device); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 5684d8722922..29b0fa9ff9d0 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1398,7 +1398,7 @@ free_interfaces: } /* Wake up the device so we can send it the Set-Config request */ - ret = usb_autoresume_device(dev, 1); + ret = usb_autoresume_device(dev); if (ret) goto free_interfaces; @@ -1421,7 +1421,7 @@ free_interfaces: dev->actconfig = cp; if (!cp) { usb_set_device_state(dev, USB_STATE_ADDRESS); - usb_autosuspend_device(dev, 1); + usb_autosuspend_device(dev); goto free_interfaces; } usb_set_device_state(dev, USB_STATE_CONFIGURED); @@ -1490,7 +1490,7 @@ free_interfaces: usb_create_sysfs_intf_files (intf); } - usb_autosuspend_device(dev, 1); + usb_autosuspend_device(dev); return 0; } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 13322e33f912..17830a81be14 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {} #define USB_AUTOSUSPEND_DELAY (HZ*2) -extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt); -extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt); +extern void usb_autosuspend_device(struct usb_device *udev); +extern int usb_autoresume_device(struct usb_device *udev); #else -#define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0) -static inline int usb_autoresume_device(struct usb_device *udev, - int inc_busy_cnt) +#define usb_autosuspend_device(udev) do {} while (0) +static inline int usb_autoresume_device(struct usb_device *udev) { return 0; } -- cgit v1.2.3 From 009af1ff78bfc30b9a27807dd0207fc32848218a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 27 Oct 2006 16:12:30 -0700 Subject: PCI: Let PCI_MULTITHREAD_PROBE not be broken It's not really broken, but people keep running into other problems caused by it. Re-enable it so that the drivers get stress tested. Signed-off-by: Greg Kroah-Hartman --- drivers/pci/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 5f1b9f58070e..ecc50db8585a 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -19,7 +19,7 @@ config PCI_MSI config PCI_MULTITHREAD_PROBE bool "PCI Multi-threaded probe (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL && BROKEN + depends on PCI && EXPERIMENTAL help Say Y here if you want the PCI core to spawn a new thread for every PCI device that is probed. This can cause a huge -- cgit v1.2.3 From e65e5fb5ceb02aaea7b65bf8b3b0d0c9057718b6 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 7 Nov 2006 18:21:21 +1100 Subject: PCI: Make some MSI-X #defines generic Move some MSI-X #defines into pci_regs.h so they can be used outside of drivers/pci. Signed-off-by: Michael Ellerman Signed-off-by: Greg Kroah-Hartman --- drivers/pci/msi.h | 8 -------- include/linux/pci_regs.h | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index f0cca1772f9c..3898f5237144 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,14 +6,6 @@ #ifndef MSI_H #define MSI_H -/* - * MSI-X Address Register - */ -#define PCI_MSIX_FLAGS_QSIZE 0x7FF -#define PCI_MSIX_FLAGS_ENABLE (1 << 15) -#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) -#define PCI_MSIX_FLAGS_BITMASK (1 << 0) - #define PCI_MSIX_ENTRY_SIZE 16 #define PCI_MSIX_ENTRY_LOWER_ADDR_OFFSET 0 #define PCI_MSIX_ENTRY_UPPER_ADDR_OFFSET 4 diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index c321316f1bc7..064b1dc71c22 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -292,6 +292,12 @@ #define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ #define PCI_MSI_MASK_BIT 16 /* Mask bits register */ +/* MSI-X registers (these are at offset PCI_MSI_FLAGS) */ +#define PCI_MSIX_FLAGS_QSIZE 0x7FF +#define PCI_MSIX_FLAGS_ENABLE (1 << 15) +#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) +#define PCI_MSIX_FLAGS_BITMASK (1 << 0) + /* CompactPCI Hotswap Register */ #define PCI_CHSWP_CSR 2 /* Control and Status Register */ -- cgit v1.2.3 From cc692a5f1e9816671b77da77c6d6c463156ba1c7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 8 Nov 2006 16:17:15 -0800 Subject: PCI: save/restore PCI-X state Shouldn't PCI-X state be saved/restored? No device really needs this right now. qla24xx (fc HBA) and mthca (infiniband) don't do suspend, and sky2 resets its tweaks when links are brought up. Signed-off-by: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a544997399b3..0eaf381ae93e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -490,6 +490,47 @@ static void pci_restore_pcie_state(struct pci_dev *dev) kfree(save_state); } + +static int pci_save_pcix_state(struct pci_dev *dev) +{ + int pos, i = 0; + struct pci_cap_saved_state *save_state; + u16 *cap; + + pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); + if (pos <= 0) + return 0; + + save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL); + if (!save_state) { + dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n"); + return -ENOMEM; + } + cap = (u16 *)&save_state->data[0]; + + pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]); + pci_add_saved_cap(dev, save_state); + return 0; +} + +static void pci_restore_pcix_state(struct pci_dev *dev) +{ + int i = 0, pos; + struct pci_cap_saved_state *save_state; + u16 *cap; + + save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX); + pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); + if (!save_state || pos <= 0) + return; + cap = (u16 *)&save_state->data[0]; + + pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]); + pci_remove_saved_cap(save_state); + kfree(save_state); +} + + /** * pci_save_state - save the PCI configuration space of a device before suspending * @dev: - PCI device that we're dealing with @@ -507,6 +548,8 @@ pci_save_state(struct pci_dev *dev) return i; if ((i = pci_save_pcie_state(dev)) != 0) return i; + if ((i = pci_save_pcix_state(dev)) != 0) + return i; return 0; } @@ -538,6 +581,7 @@ pci_restore_state(struct pci_dev *dev) dev->saved_config_space[i]); } } + pci_restore_pcix_state(dev); pci_restore_msi_state(dev); pci_restore_msix_state(dev); return 0; -- cgit v1.2.3 From 368c73d4f689dae0807d0a2aa74c61fd2b9b075f Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 4 Oct 2006 00:41:26 +0100 Subject: PCI: quirks: fix the festering mess that claims to handle IDE quirks The number of permutations of crap we do is amazing and almost all of it has the wrong effect in 2.6. At the heart of this is the PCI SFF magic which says that compatibility mode PCI IDE controllers use ISA IRQ routing and hard coded addresses not the BAR values. The old quirks variously clears them, sets them, adjusts them and then IDE ignores the result. In order to drive all this garbage out and to do it portably we need to handle the SFF rules directly and properly. Because we know the device BAR 0-3 are not used in compatibility mode we load them with the values that are implied (and indeed which many controllers actually thoughtfully put there in this mode anyway). This removes special cases in the IDE layer and libata which now knows that bar 0/1/2/3 always contain the correct address. It means our resource allocation map is accurate from boot, not "mostly accurate" after ide is loaded, and it shoots lots of code. There is also lots more code and magic constant knowledge to shoot once this is in and settled. Been in my test tree for a while both with drivers/ide and with libata. Wants some -mm shakedown in case I've missed something dumb or there are corner cases lurking. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- arch/i386/pci/fixup.c | 46 --------------------------------------- drivers/pci/probe.c | 27 +++++++++++++++++++++++ drivers/pci/quirks.c | 59 +++------------------------------------------------ 3 files changed, 30 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c index c1949ff38d61..cde1170b01a1 100644 --- a/arch/i386/pci/fixup.c +++ b/arch/i386/pci/fixup.c @@ -74,52 +74,6 @@ static void __devinit pci_fixup_ncr53c810(struct pci_dev *d) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810); -static void __devinit pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - DBG("PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); - -static void __devinit pci_fixup_ide_trash(struct pci_dev *d) -{ - int i; - - /* - * Runs the fixup only for the first IDE controller - * (Shai Fultheim - shai@ftcon.com) - */ - static int called = 0; - if (called) - return; - called = 1; - - /* - * There exist PCI IDE controllers which have utter garbage - * in first four base registers. Ignore that. - */ - DBG("PCI: IDE base address trash cleared for %s\n", pci_name(d)); - for(i=0; i<4; i++) - d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0; -} -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash); - static void __devinit pci_fixup_latency(struct pci_dev *d) { /* diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e159d6604494..0eeac60042b3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -679,6 +679,33 @@ static int pci_setup_device(struct pci_dev * dev) pci_read_bases(dev, 6, PCI_ROM_ADDRESS); pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor); pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device); + + /* + * Do the ugly legacy mode stuff here rather than broken chip + * quirk code. Legacy mode ATA controllers have fixed + * addresses. These are not always echoed in BAR0-3, and + * BAR0-3 in a few cases contain junk! + */ + if (class == PCI_CLASS_STORAGE_IDE) { + u8 progif; + pci_read_config_byte(dev, PCI_CLASS_PROG, &progif); + if ((progif & 1) == 0) { + dev->resource[0].start = 0x1F0; + dev->resource[0].end = 0x1F7; + dev->resource[0].flags = IORESOURCE_IO; + dev->resource[1].start = 0x3F6; + dev->resource[1].end = 0x3F6; + dev->resource[1].flags = IORESOURCE_IO; + } + if ((progif & 4) == 0) { + dev->resource[2].start = 0x170; + dev->resource[2].end = 0x177; + dev->resource[2].flags = IORESOURCE_IO; + dev->resource[3].start = 0x376; + dev->resource[3].end = 0x376; + dev->resource[3].flags = IORESOURCE_IO; + } + } break; case PCI_HEADER_TYPE_BRIDGE: /* bridge header */ diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5b4483811691..9ca9b9bf6160 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -796,56 +796,6 @@ static void __init quirk_mediagx_master(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master ); -/* - * As per PCI spec, ignore base address registers 0-3 of the IDE controllers - * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and - * secondary channels respectively). If the device reports Compatible mode - * but does use BAR0-3 for address decoding, we assume that firmware has - * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374). - * Exceptions (if they exist) must be handled in chip/architecture specific - * fixups. - * - * Note: for non x86 people. You may need an arch specific quirk to handle - * moving IDE devices to native mode as well. Some plug in card devices power - * up in compatible mode and assume the BIOS will adjust them. - * - * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as - * we do now ? We don't want is pci_enable_device to come along - * and assign new resources. Both approaches work for that. - */ -static void __devinit quirk_ide_bases(struct pci_dev *dev) -{ - struct resource *res; - int first_bar = 2, last_bar = 0; - - if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - - res = &dev->resource[0]; - - /* primary channel: ProgIf bit 0, BAR0, BAR1 */ - if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { - res[0].start = res[0].end = res[0].flags = 0; - res[1].start = res[1].end = res[1].flags = 0; - first_bar = 0; - last_bar = 1; - } - - /* secondary channel: ProgIf bit 2, BAR2, BAR3 */ - if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { - res[2].start = res[2].end = res[2].flags = 0; - res[3].start = res[3].end = res[3].flags = 0; - last_bar = 3; - } - - if (!last_bar) - return; - - printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", - first_bar, last_bar, pci_name(dev)); -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases); - /* * Ensure C0 rev restreaming is off. This is normally done by * the BIOS but in the odd case it is not the results are corruption @@ -880,11 +830,10 @@ static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev) prog &= ~5; pdev->class &= ~5; pci_write_config_byte(pdev, PCI_CLASS_PROG, prog); - /* need to re-assign BARs for compat mode */ - quirk_ide_bases(pdev); + /* PCI layer will sort out resources */ } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide ); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide ); /* * Intel 82801CAM ICH3-M datasheet says IDE modes must be the same @@ -900,11 +849,9 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev) prog &= ~5; pdev->class &= ~5; pci_write_config_byte(pdev, PCI_CLASS_PROG, prog); - /* need to re-assign BARs for compat mode */ - quirk_ide_bases(pdev); } } -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, quirk_ide_samemode); /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. -- cgit v1.2.3 From ebf5a24829def5d066922ceebde61dd57fdc6b1e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 10 Oct 2006 08:01:20 -0600 Subject: PCI: Use pci_generic_prep_mwi on sparc64 The setting of the CACHE_LINE_SIZE register in sparc64's pci initialisation code isn't quite adequate as the device may have incompatible requirements. The generic code tests for this, so switch sparc64 over to using it. Since sparc64 has different L1 cache line size and PCI cache line size, it would need to override the generic code like i386 and ia64 do. We know what the cache line size is at compile time though, so introduce a new optional constant PCI_CACHE_LINE_BYTES. Signed-off-by: Matthew Wilcox Signed-off-by: David Miller Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- arch/sparc64/kernel/pci.c | 9 --------- drivers/pci/pci.c | 8 +++++++- include/asm-sparc64/pci.h | 6 ++---- 3 files changed, 9 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index e02f01b644af..dfc41cd4bb5d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c @@ -646,13 +646,4 @@ int pci_domain_nr(struct pci_bus *pbus) } EXPORT_SYMBOL(pci_domain_nr); -int pcibios_prep_mwi(struct pci_dev *dev) -{ - /* We set correct PCI_CACHE_LINE_SIZE register values for every - * device probed on this platform. So there is nothing to check - * and this always succeeds. - */ - return 0; -} - #endif /* !(CONFIG_PCI) */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0eaf381ae93e..bc88c30a418b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -876,8 +876,14 @@ pci_set_master(struct pci_dev *dev) } #ifndef HAVE_ARCH_PCI_MWI + +#ifndef PCI_CACHE_LINE_BYTES +#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES +#endif + /* This can be overridden by arch code. */ -u8 pci_cache_line_size = L1_CACHE_BYTES >> 2; +/* Don't forget this is measured in 32-bit words, not bytes */ +u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; /** * pci_generic_prep_mwi - helper function for pci_set_mwi diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index e1ea67bc32f2..ca6560288ae8 100644 --- a/include/asm-sparc64/pci.h +++ b/include/asm-sparc64/pci.h @@ -18,6 +18,8 @@ #define PCI_IRQ_NONE 0xffffffff +#define PCI_CACHE_LINE_BYTES 64 + static inline void pcibios_set_master(struct pci_dev *dev) { /* No special bus mastering setup handling */ @@ -291,10 +293,6 @@ extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state, int write_combine); -/* Platform specific MWI support. */ -#define HAVE_ARCH_PCI_MWI -extern int pcibios_prep_mwi(struct pci_dev *dev); - extern void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res); -- cgit v1.2.3 From edb2d97eb57b7a21c9256260562de6a65dda86cc Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 10 Oct 2006 08:01:21 -0600 Subject: PCI: Replace HAVE_ARCH_PCI_MWI with PCI_DISABLE_MWI pSeries is the only architecture left using HAVE_ARCH_PCI_MWI and it's really inappropriate for its needs. It really wants to disable MWI altogether. So here are a pair of stub implementations for pci_set_mwi and pci_clear_mwi. Also rename pci_generic_prep_mwi to pci_set_cacheline_size since that better reflects what it does. Signed-off-by: Matthew Wilcox Cc: Paul Mackerras Acked-by: Jeff Garzik Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci.c | 31 ++++++++++++++++++------------- include/asm-powerpc/pci.h | 20 +++++++------------- 2 files changed, 25 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bc88c30a418b..427991741cf3 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -875,7 +875,17 @@ pci_set_master(struct pci_dev *dev) pcibios_set_master(dev); } -#ifndef HAVE_ARCH_PCI_MWI +#ifdef PCI_DISABLE_MWI +int pci_set_mwi(struct pci_dev *dev) +{ + return 0; +} + +void pci_clear_mwi(struct pci_dev *dev) +{ +} + +#else #ifndef PCI_CACHE_LINE_BYTES #define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES @@ -886,17 +896,17 @@ pci_set_master(struct pci_dev *dev) u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4; /** - * pci_generic_prep_mwi - helper function for pci_set_mwi - * @dev: the PCI device for which MWI is enabled + * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed + * @dev: the PCI device for which MWI is to be enabled * - * Helper function for generic implementation of pcibios_prep_mwi - * function. Originally copied from drivers/net/acenic.c. + * Helper function for pci_set_mwi. + * Originally copied from drivers/net/acenic.c. * Copyright 1998-2001 by Jes Sorensen, . * * RETURNS: An appropriate -ERRNO error value on error, or zero for success. */ static int -pci_generic_prep_mwi(struct pci_dev *dev) +pci_set_cacheline_size(struct pci_dev *dev) { u8 cacheline_size; @@ -922,7 +932,6 @@ pci_generic_prep_mwi(struct pci_dev *dev) return -EINVAL; } -#endif /* !HAVE_ARCH_PCI_MWI */ /** * pci_set_mwi - enables memory-write-invalidate PCI transaction @@ -940,12 +949,7 @@ pci_set_mwi(struct pci_dev *dev) int rc; u16 cmd; -#ifdef HAVE_ARCH_PCI_MWI - rc = pcibios_prep_mwi(dev); -#else - rc = pci_generic_prep_mwi(dev); -#endif - + rc = pci_set_cacheline_size(dev); if (rc) return rc; @@ -976,6 +980,7 @@ pci_clear_mwi(struct pci_dev *dev) pci_write_config_word(dev, PCI_COMMAND, cmd); } } +#endif /* ! PCI_DISABLE_MWI */ /** * pci_intx - enables/disables PCI INTx for device dev diff --git a/include/asm-powerpc/pci.h b/include/asm-powerpc/pci.h index 46afd29b904e..721c97f09b20 100644 --- a/include/asm-powerpc/pci.h +++ b/include/asm-powerpc/pci.h @@ -62,19 +62,13 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) } #ifdef CONFIG_PPC64 -#define HAVE_ARCH_PCI_MWI 1 -static inline int pcibios_prep_mwi(struct pci_dev *dev) -{ - /* - * We would like to avoid touching the cacheline size or MWI bit - * but we cant do that with the current pcibios_prep_mwi - * interface. pSeries firmware sets the cacheline size (which is not - * the cpu cacheline size in all cases) and hardware treats MWI - * the same as memory write. So we dont touch the cacheline size - * here and allow the generic code to set the MWI bit. - */ - return 0; -} + +/* + * We want to avoid touching the cacheline size or MWI bit. + * pSeries firmware sets the cacheline size (which is not the cpu cacheline + * size in all cases) and hardware treats MWI the same as memory write. + */ +#define PCI_DISABLE_MWI extern struct dma_mapping_ops pci_dma_ops; -- cgit v1.2.3 From 9f581f162e2b304be25dee49bf3945d4ed65dfb6 Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 4 Oct 2006 16:49:35 -0500 Subject: Altix: SN ACPI hotplug support. A few minor changes to the way slot/device fixup is done. No need to be calling sn_pci_controller_fixup(), as a root bus cannot be hotplugged. Signed-off-by: John Keller Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/sgi_hotplug.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index b62ad31a9739..5d188c558386 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -205,21 +205,6 @@ static struct hotplug_slot * sn_hp_destroy(void) return bss_hotplug_slot; } -static void sn_bus_alloc_data(struct pci_dev *dev) -{ - struct pci_bus *subordinate_bus; - struct pci_dev *child; - - sn_pci_fixup_slot(dev); - - /* Recursively sets up the sn_irq_info structs */ - if (dev->subordinate) { - subordinate_bus = dev->subordinate; - list_for_each_entry(child, &subordinate_bus->devices, bus_list) - sn_bus_alloc_data(child); - } -} - static void sn_bus_free_data(struct pci_dev *dev) { struct pci_bus *subordinate_bus; @@ -337,6 +322,11 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot, return rc; } +/* + * Power up and configure the slot via a SAL call to PROM. + * Scan slot (and any children), do any platform specific fixup, + * and find device driver. + */ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) { struct slot *slot = bss_hotplug_slot->private; @@ -345,6 +335,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) int func, num_funcs; int new_ppb = 0; int rc; + void pcibios_fixup_device_resources(struct pci_dev *); /* Serialize the Linux PCI infrastructure */ mutex_lock(&sn_hotplug_mutex); @@ -367,9 +358,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) return -ENODEV; } - sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus), - slot->pci_bus->number, - slot->pci_bus); /* * Map SN resources for all functions on the card * to the Linux PCI interface and tell the drivers @@ -380,6 +368,13 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) PCI_DEVFN(slot->device_num + 1, PCI_FUNC(func))); if (dev) { + /* Need to do slot fixup on PPB before fixup of children + * (PPB's pcidev_info needs to be in pcidev_info list + * before child's SN_PCIDEV_INFO() call to setup + * pdi_host_pcidev_info). + */ + pcibios_fixup_device_resources(dev); + sn_pci_fixup_slot(dev); if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { unsigned char sec_bus; pci_read_config_byte(dev, PCI_SECONDARY_BUS, @@ -387,12 +382,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) new_bus = pci_add_new_bus(dev->bus, dev, sec_bus); pci_scan_child_bus(new_bus); - sn_pci_controller_fixup(pci_domain_nr(new_bus), - new_bus->number, - new_bus); new_ppb = 1; } - sn_bus_alloc_data(dev); pci_dev_put(dev); } } -- cgit v1.2.3 From a2302c68d923537436b1114aa207787c1a31bd50 Mon Sep 17 00:00:00 2001 From: John Keller Date: Wed, 4 Oct 2006 16:49:52 -0500 Subject: Altix: Initial ACPI support - ROM shadowing. Support a shadowed ROM when running with an ACPI capable PROM. Define a new dev.resource flag IORESOURCE_ROM_BIOS_COPY to describe the case of a BIOS shadowed ROM, which can then be used to avoid pci_map_rom() making an unneeded call to pci_enable_rom(). Signed-off-by: John Keller Signed-off-by: Greg Kroah-Hartman --- arch/ia64/sn/kernel/io_acpi_init.c | 33 +++++++++++++++++++++++++++++++++ arch/ia64/sn/kernel/io_common.c | 5 +++-- arch/ia64/sn/kernel/io_init.c | 3 +++ drivers/pci/rom.c | 9 ++++++--- include/linux/ioport.h | 1 + 5 files changed, 46 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/sn/kernel/io_acpi_init.c b/arch/ia64/sn/kernel/io_acpi_init.c index a9dc36901b19..99d7f278612a 100644 --- a/arch/ia64/sn/kernel/io_acpi_init.c +++ b/arch/ia64/sn/kernel/io_acpi_init.c @@ -169,6 +169,39 @@ sn_acpi_bus_fixup(struct pci_bus *bus) } } +/* + * sn_acpi_slot_fixup - Perform any SN specific slot fixup. + * At present there does not appear to be + * any generic way to handle a ROM image + * that has been shadowed by the PROM, so + * we pass a pointer to it within the + * pcidev_info structure. + */ + +void +sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info) +{ + void __iomem *addr; + size_t size; + + if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) { + /* + * A valid ROM image exists and has been shadowed by the + * PROM. Setup the pci_dev ROM resource to point to + * the shadowed copy. + */ + size = dev->resource[PCI_ROM_RESOURCE].end - + dev->resource[PCI_ROM_RESOURCE].start; + addr = + ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE], + size); + dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr; + dev->resource[PCI_ROM_RESOURCE].end = + (unsigned long) addr + size; + dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY; + } +} + static struct acpi_driver acpi_sn_hubdev_driver = { .name = "SGI HUBDEV Driver", .ids = "SGIHUB,SGITIO", diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c index 12531de6754c..d4dd8f4b6b8d 100644 --- a/arch/ia64/sn/kernel/io_common.c +++ b/arch/ia64/sn/kernel/io_common.c @@ -286,9 +286,10 @@ void sn_pci_fixup_slot(struct pci_dev *dev) list_add_tail(&pcidev_info->pdi_list, &(SN_PLATFORM_DATA(dev->bus)->pcidev_info)); - if (!SN_ACPI_BASE_SUPPORT()) + if (SN_ACPI_BASE_SUPPORT()) + sn_acpi_slot_fixup(dev, pcidev_info); + else sn_more_slot_fixup(dev, pcidev_info); - /* * Using the PROMs values for the PCI host bus, get the Linux * PCI host_pci_dev struct and set up host bus linkages diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 990224a44121..9ad843e0383b 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -210,6 +210,9 @@ sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info) dev->resource[idx].parent = &ioport_resource; else dev->resource[idx].parent = &iomem_resource; + /* If ROM, mark as shadowed in PROM */ + if (idx == PCI_ROM_RESOURCE) + dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY; } /* Create a pci_window in the pci_controller struct for * each device resource. diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index e1dcefc69bb4..d087e0817715 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -81,7 +81,8 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) start = (loff_t)0xC0000; *size = 0x20000; /* cover C000:0 through E000:0 */ } else { - if (res->flags & IORESOURCE_ROM_COPY) { + if (res->flags & + (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) { *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); return (void __iomem *)(unsigned long) pci_resource_start(pdev, PCI_ROM_RESOURCE); @@ -165,7 +166,8 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size) if (!rom) return NULL; - if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW)) + if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW | + IORESOURCE_ROM_BIOS_COPY)) return rom; res->start = (unsigned long)kmalloc(*size, GFP_KERNEL); @@ -191,7 +193,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom) { struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; - if (res->flags & IORESOURCE_ROM_COPY) + if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) return; iounmap(rom); @@ -215,6 +217,7 @@ void pci_remove_rom(struct pci_dev *pdev) sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | + IORESOURCE_ROM_BIOS_COPY | IORESOURCE_ROM_COPY))) pci_disable_rom(pdev); } diff --git a/include/linux/ioport.h b/include/linux/ioport.h index d42c83399071..cf8696d4a138 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -89,6 +89,7 @@ struct resource_list { #define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */ #define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */ #define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */ +#define IORESOURCE_ROM_BIOS_COPY (1<<3) /* ROM is BIOS copy, resource field overlaid */ /* PC/ISA/whatever - the normal PC address spaces: IO and memory */ extern struct resource ioport_resource; -- cgit v1.2.3 From 467c442f092e22acf86a3b4ad4863d097d7257da Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Oct 2006 13:07:58 -0800 Subject: acpiphp: fix use of list_for_each macro This patch fixes invalid usage of list_for_each() list_for_each (node, &bridge_list) { bridge = (struct acpiphp_bridge *)node; ... } This code works while the member of list node is located at the head of struct acpiphp_bridge. Signed-off-by: Akinobu Mita Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_glue.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 16167b016266..0b9d0db1590a 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1693,14 +1693,10 @@ void __exit acpiphp_glue_exit(void) */ int __init acpiphp_get_num_slots(void) { - struct list_head *node; struct acpiphp_bridge *bridge; - int num_slots; - - num_slots = 0; + int num_slots = 0; - list_for_each (node, &bridge_list) { - bridge = (struct acpiphp_bridge *)node; + list_for_each_entry (bridge, &bridge_list, list) { dbg("Bus %04x:%02x has %d slot%s\n", pci_domain_nr(bridge->pci_bus), bridge->pci_bus->number, bridge->nr_slots, -- cgit v1.2.3 From 0a9dee2739fd4385e83c3316e3f3bee641796638 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Mon, 30 Oct 2006 13:08:04 -0800 Subject: acpiphp: fix missing acpiphp_glue_exit() acpiphp_glue_exit() needs to be called to unwind when no slots found. (It fixes data corruption when reloading acpiphp driver with no such devices) Signed-off-by: Akinobu Mita Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index c57d9d5ce84e..c8b690741149 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -303,8 +303,10 @@ static int __init init_acpi(void) /* read initial number of slots */ if (!retval) { num_slots = acpiphp_get_num_slots(); - if (num_slots == 0) + if (num_slots == 0) { + acpiphp_glue_exit(); retval = -ENODEV; + } } return retval; -- cgit v1.2.3 From 0dcb2b7e722f62b886f28b01150860de67d219fa Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Mon, 30 Oct 2006 13:08:12 -0800 Subject: pci: clear osc support flags if no _OSC method So it looks like pci aer code will call pci_osc_support_set to tell the firmware about OSC_EXT_PCI_CONFIG_SUPPORT flag. that causes ctrlset_buf[OSC_SUPPORT_TYPE] to evaluate to true when pciehp calls pci_osc_control_set() is called (to attempt to use OSC to gain native pcie control from firmware), regardless of whether or not _OSC was actually successfully executed. That causes this section of code: if (ctrlset_buf[OSC_SUPPORT_TYPE] && ((global_ctrlsets & ctrlset) != ctrlset)) { return AE_SUPPORT; } to be hit. This patch will reset the OSC_SUPPORT_TYPE field if _OSC fails, and then would allow pciehp to go ahead and try to run _OSC again. Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-acpi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index bb7456c1dbac..a064f36a0805 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -36,6 +36,7 @@ acpi_query_osc ( struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; union acpi_object *out_obj; u32 osc_dw0; + acpi_status *ret_status = (acpi_status *)retval; /* Setting up input parameters */ @@ -56,6 +57,7 @@ acpi_query_osc ( if (ACPI_FAILURE (status)) { printk(KERN_DEBUG "Evaluate _OSC Set fails. Status = 0x%04x\n", status); + *ret_status = status; return status; } out_obj = output.pointer; @@ -90,6 +92,7 @@ acpi_query_osc ( query_osc_out: kfree(output.pointer); + *ret_status = status; return status; } @@ -166,6 +169,7 @@ run_osc_out: acpi_status pci_osc_support_set(u32 flags) { u32 temp; + acpi_status retval; if (!(flags & OSC_SUPPORT_MASKS)) { return AE_TYPE; @@ -179,9 +183,13 @@ acpi_status pci_osc_support_set(u32 flags) acpi_get_devices ( PCI_ROOT_HID_STRING, acpi_query_osc, ctrlset_buf, - NULL ); + (void **) &retval ); ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; ctrlset_buf[OSC_CONTROL_TYPE] = temp; + if (ACPI_FAILURE(retval)) { + /* no osc support at all */ + ctrlset_buf[OSC_SUPPORT_TYPE] = 0; + } return AE_OK; } EXPORT_SYMBOL(pci_osc_support_set); -- cgit v1.2.3 From 50bf14b3ff05fb6e10688021b96f95d30a300f8d Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 8 Nov 2006 19:53:59 -0800 Subject: pci: fix __pci_register_driver error handling __pci_register_driver() error path forgot to unwind. driver_unregister() needs to be called when pci_create_newid_file() failed. Signed-off-by: Akinobu Mita Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 194f1d21d3d7..84ec9c8f6703 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -445,9 +445,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) /* register with core */ error = driver_register(&drv->driver); + if (error) + return error; - if (!error) - error = pci_create_newid_file(drv); + error = pci_create_newid_file(drv); + if (error) + driver_unregister(&drv->driver); return error; } -- cgit v1.2.3 From 7ea7e98fd8d02351c43ef4ab35d70f3aaa26c31d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 19 Oct 2006 09:41:28 -0600 Subject: PCI: Block on access to temporarily unavailable pci device The existing implementation of pci_block_user_cfg_access() was recently criticised for providing out of date information and for returning errors on write, which applications won't be expecting. This reimplementation uses a global wait queue and a bit per device. I've open-coded prepare_to_wait() / finish_wait() as I could optimise it significantly by knowing that the pci_lock protected us at all points. It looked a bit funny to be doing a spin_unlock_irqsave(); schedule(), so I used spin_lock_irq() for the _user versions of pci_read_config and pci_write_config. Not carrying a flags pointer around made the code much less nasty. Attempts to block an already blocked device hit a BUG() and attempts to unblock an already unblocked device hit a WARN(). If we need to block access to a device from userspace, it's because it's unsafe for even another bit of the kernel to access the device. An attempt to block a device for a second time means we're about to access the device to perform some other operation, which could provoke undefined behaviour from the device. Signed-off-by: Matthew Wilcox Acked-by: Adam Belay Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/pci/access.c | 75 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/access.c b/drivers/pci/access.c index ea16805a153c..73a58c73d526 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "pci.h" @@ -63,30 +64,42 @@ EXPORT_SYMBOL(pci_bus_write_config_byte); EXPORT_SYMBOL(pci_bus_write_config_word); EXPORT_SYMBOL(pci_bus_write_config_dword); -static u32 pci_user_cached_config(struct pci_dev *dev, int pos) -{ - u32 data; +/* + * The following routines are to prevent the user from accessing PCI config + * space when it's unsafe to do so. Some devices require this during BIST and + * we're required to prevent it during D-state transitions. + * + * We have a bit per device to indicate it's blocked and a global wait queue + * for callers to sleep on until devices are unblocked. + */ +static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait); - data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])]; - data >>= (pos % sizeof(dev->saved_config_space[0])) * 8; - return data; +static noinline void pci_wait_ucfg(struct pci_dev *dev) +{ + DECLARE_WAITQUEUE(wait, current); + + __add_wait_queue(&pci_ucfg_wait, &wait); + do { + set_current_state(TASK_UNINTERRUPTIBLE); + spin_unlock_irq(&pci_lock); + schedule(); + spin_lock_irq(&pci_lock); + } while (dev->block_ucfg_access); + __remove_wait_queue(&pci_ucfg_wait, &wait); } #define PCI_USER_READ_CONFIG(size,type) \ int pci_user_read_config_##size \ (struct pci_dev *dev, int pos, type *val) \ { \ - unsigned long flags; \ int ret = 0; \ u32 data = -1; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ - spin_lock_irqsave(&pci_lock, flags); \ - if (likely(!dev->block_ucfg_access)) \ - ret = dev->bus->ops->read(dev->bus, dev->devfn, \ + spin_lock_irq(&pci_lock); \ + if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ + ret = dev->bus->ops->read(dev->bus, dev->devfn, \ pos, sizeof(type), &data); \ - else if (pos < sizeof(dev->saved_config_space)) \ - data = pci_user_cached_config(dev, pos); \ - spin_unlock_irqrestore(&pci_lock, flags); \ + spin_unlock_irq(&pci_lock); \ *val = (type)data; \ return ret; \ } @@ -95,14 +108,13 @@ int pci_user_read_config_##size \ int pci_user_write_config_##size \ (struct pci_dev *dev, int pos, type val) \ { \ - unsigned long flags; \ int ret = -EIO; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ - spin_lock_irqsave(&pci_lock, flags); \ - if (likely(!dev->block_ucfg_access)) \ - ret = dev->bus->ops->write(dev->bus, dev->devfn, \ + spin_lock_irq(&pci_lock); \ + if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ + ret = dev->bus->ops->write(dev->bus, dev->devfn, \ pos, sizeof(type), val); \ - spin_unlock_irqrestore(&pci_lock, flags); \ + spin_unlock_irq(&pci_lock); \ return ret; \ } @@ -117,21 +129,23 @@ PCI_USER_WRITE_CONFIG(dword, u32) * pci_block_user_cfg_access - Block userspace PCI config reads/writes * @dev: pci device struct * - * This function blocks any userspace PCI config accesses from occurring. - * When blocked, any writes will be bit bucketed and reads will return the - * data saved using pci_save_state for the first 64 bytes of config - * space and return 0xff for all other config reads. - **/ + * When user access is blocked, any reads or writes to config space will + * sleep until access is unblocked again. We don't allow nesting of + * block/unblock calls. + */ void pci_block_user_cfg_access(struct pci_dev *dev) { unsigned long flags; + int was_blocked; - pci_save_state(dev); - - /* spinlock to synchronize with anyone reading config space now */ spin_lock_irqsave(&pci_lock, flags); + was_blocked = dev->block_ucfg_access; dev->block_ucfg_access = 1; spin_unlock_irqrestore(&pci_lock, flags); + + /* If we BUG() inside the pci_lock, we're guaranteed to hose + * the machine */ + BUG_ON(was_blocked); } EXPORT_SYMBOL_GPL(pci_block_user_cfg_access); @@ -140,14 +154,19 @@ EXPORT_SYMBOL_GPL(pci_block_user_cfg_access); * @dev: pci device struct * * This function allows userspace PCI config accesses to resume. - **/ + */ void pci_unblock_user_cfg_access(struct pci_dev *dev) { unsigned long flags; - /* spinlock to synchronize with anyone reading saved config space */ spin_lock_irqsave(&pci_lock, flags); + + /* This indicates a problem in the caller, but we don't need + * to kill them, unlike a double-block above. */ + WARN_ON(!dev->block_ucfg_access); + dev->block_ucfg_access = 0; + wake_up_all(&pci_ucfg_wait); spin_unlock_irqrestore(&pci_lock, flags); } EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); -- cgit v1.2.3 From bae94d02371c402408a4edfb95e71e88dbd3e973 Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Wed, 22 Nov 2006 12:40:31 -0800 Subject: PCI: switch pci_{enable,disable}_device() to be nestable Changes the pci_{enable,disable}_device() functions to work in a nested basis, so that eg, three calls to enable_device() require three calls to disable_device(). The reason for this is to simplify PCI drivers for multi-interface/capability devices. These are devices that cram more than one interface in a single function. A relevant example of that is the Wireless [USB] Host Controller Interface (similar to EHCI) [see http://www.intel.com/technology/comms/wusb/whci.htm]. In these kind of devices, multiple interfaces are accessed through a single bar and IRQ line. For that, the drivers map only the smallest area of the bar to access their register banks and use shared IRQ handlers. However, because the order at which those drivers load cannot be known ahead of time, the sequence in which the calls to pci_enable_device() and pci_disable_device() cannot be predicted. Thus: 1. driverA starts pci_enable_device() 2. driverB starts pci_enable_device() 3. driverA shutdown pci_disable_device() 4. driverB shutdown pci_disable_device() between steps 3 and 4, driver B would loose access to it's device, even if it didn't intend to. By using this modification, the device won't be disabled until all the callers to enable() have called disable(). This is implemented by replacing 'struct pci_dev->is_enabled' from a bitfield to an atomic use count. Each caller to enable increments it, each caller to disable decrements it. When the count increments from 0 to 1, __pci_enable_device() is called to actually enable the device. When it drops to zero, pci_disable_device() actually does the disabling. We keep the backend __pci_enable_device() for pci_default_resume() to use and also change the sysfs method implementation, so that userspace enabling/disabling the device doesn't disable it one time too much. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/pci/pci-driver.c | 4 ++-- drivers/pci/pci-sysfs.c | 33 +++++++++++++++++++++------------ drivers/pci/pci.c | 40 +++++++++++++++++++++++++++++++++------- drivers/pci/pci.h | 1 + include/linux/pci.h | 3 ++- 5 files changed, 59 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 84ec9c8f6703..e5ae3a0c13bb 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -329,8 +329,8 @@ static int pci_default_resume(struct pci_dev *pci_dev) /* restore the PCI config space */ pci_restore_state(pci_dev); /* if the device was enabled before suspend, reenable */ - if (pci_dev->is_enabled) - retval = pci_enable_device(pci_dev); + if (atomic_read(&pci_dev->enable_cnt)) + retval = __pci_enable_device(pci_dev); /* if the device was busmaster before the suspend, make it busmaster again */ if (pci_dev->is_busmaster) pci_set_master(pci_dev); diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index f952bfea48a6..7a94076752d0 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -42,7 +42,6 @@ pci_config_attr(subsystem_vendor, "0x%04x\n"); pci_config_attr(subsystem_device, "0x%04x\n"); pci_config_attr(class, "0x%06x\n"); pci_config_attr(irq, "%u\n"); -pci_config_attr(is_enabled, "%u\n"); static ssize_t broken_parity_status_show(struct device *dev, struct device_attribute *attr, @@ -112,26 +111,36 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8), (u8)(pci_dev->class)); } -static ssize_t -is_enabled_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) + +static ssize_t is_enabled_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t count) { + ssize_t result = -EINVAL; struct pci_dev *pdev = to_pci_dev(dev); - int retval = 0; /* this can crash the machine when done on the "wrong" device */ if (!capable(CAP_SYS_ADMIN)) return count; - if (*buf == '0') - pci_disable_device(pdev); + if (*buf == '0') { + if (atomic_read(&pdev->enable_cnt) != 0) + pci_disable_device(pdev); + else + result = -EIO; + } else if (*buf == '1') + result = pci_enable_device(pdev); + + return result < 0 ? result : count; +} - if (*buf == '1') - retval = pci_enable_device(pdev); +static ssize_t is_enabled_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pci_dev *pdev; - if (retval) - return retval; - return count; + pdev = to_pci_dev (dev); + return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); } static ssize_t diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 427991741cf3..5a14b73cf3a1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -612,29 +612,50 @@ pci_enable_device_bars(struct pci_dev *dev, int bars) } /** - * pci_enable_device - Initialize device before it's used by a driver. + * __pci_enable_device - Initialize device before it's used by a driver. * @dev: PCI device to be initialized * * Initialize device before it's used by a driver. Ask low-level code * to enable I/O and memory. Wake up the device if it was suspended. * Beware, this function can fail. + * + * Note this function is a backend and is not supposed to be called by + * normal code, use pci_enable_device() instead. */ int -pci_enable_device(struct pci_dev *dev) +__pci_enable_device(struct pci_dev *dev) { int err; - if (dev->is_enabled) - return 0; - err = pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1); if (err) return err; pci_fixup_device(pci_fixup_enable, dev); - dev->is_enabled = 1; return 0; } +/** + * pci_enable_device - Initialize device before it's used by a driver. + * @dev: PCI device to be initialized + * + * Initialize device before it's used by a driver. Ask low-level code + * to enable I/O and memory. Wake up the device if it was suspended. + * Beware, this function can fail. + * + * Note we don't actually enable the device many times if we call + * this function repeatedly (we just increment the count). + */ +int pci_enable_device(struct pci_dev *dev) +{ + int result; + if (atomic_add_return(1, &dev->enable_cnt) > 1) + return 0; /* already enabled */ + result = __pci_enable_device(dev); + if (result < 0) + atomic_dec(&dev->enable_cnt); + return result; +} + /** * pcibios_disable_device - disable arch specific PCI resources for device dev * @dev: the PCI device to disable @@ -651,12 +672,18 @@ void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {} * * Signal to the system that the PCI device is not in use by the system * anymore. This only involves disabling PCI bus-mastering, if active. + * + * Note we don't actually disable the device until all callers of + * pci_device_enable() have called pci_device_disable(). */ void pci_disable_device(struct pci_dev *dev) { u16 pci_command; + if (atomic_sub_return(1, &dev->enable_cnt) != 0) + return; + if (dev->msi_enabled) disable_msi_mode(dev, pci_find_capability(dev, PCI_CAP_ID_MSI), PCI_CAP_ID_MSI); @@ -672,7 +699,6 @@ pci_disable_device(struct pci_dev *dev) dev->is_busmaster = 0; pcibios_disable_device(dev); - dev->is_enabled = 0; } /** diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 6bf327db5c5e..398852f526a6 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,5 +1,6 @@ /* Functions internal to the PCI core code */ +extern int __must_check __pci_enable_device(struct pci_dev *); extern int pci_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); diff --git a/include/linux/pci.h b/include/linux/pci.h index 09be0f81b27b..01c707261f9c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -51,6 +51,7 @@ #include #include #include +#include #include /* File state for mmap()s on /proc/bus/pci/X/Y */ @@ -159,7 +160,6 @@ struct pci_dev { unsigned int transparent:1; /* Transparent PCI bridge */ unsigned int multifunction:1;/* Part of multi-function device */ /* keep track of device state */ - unsigned int is_enabled:1; /* pci_enable_device has been called */ unsigned int is_busmaster:1; /* device is busmaster */ unsigned int no_msi:1; /* device may not use msi */ unsigned int no_d1d2:1; /* only allow d0 or d3 */ @@ -167,6 +167,7 @@ struct pci_dev { unsigned int broken_parity_status:1; /* Device generates false positive parity */ unsigned int msi_enabled:1; unsigned int msix_enabled:1; + atomic_t enable_cnt; /* pci_enable_device has been called */ u32 saved_config_space[16]; /* config space saved at suspend time */ struct hlist_head saved_cap_space; -- cgit v1.2.3 From 95ddc5f25590e31843a09357365d5cbc6ec978db Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Wed, 22 Nov 2006 12:40:32 -0800 Subject: PCI: pci_{enable,disable}_device() nestable ports Change drivers/message/i20 pci driver to simply do a nestable enable()/disable() instead of checking for it. Signed-off-by: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/message/i2o/pci.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index 62f1ac08332c..8287f95c8c42 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c @@ -320,7 +320,6 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, struct i2o_controller *c; int rc; struct pci_dev *i960 = NULL; - int enabled = pdev->is_enabled; printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); @@ -330,12 +329,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, return -ENODEV; } - if (!enabled) - if ((rc = pci_enable_device(pdev))) { - printk(KERN_WARNING "i2o: couldn't enable device %s\n", - pci_name(pdev)); - return rc; - } + if ((rc = pci_enable_device(pdev))) { + printk(KERN_WARNING "i2o: couldn't enable device %s\n", + pci_name(pdev)); + return rc; + } if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { printk(KERN_WARNING "i2o: no suitable DMA found for %s\n", @@ -442,8 +440,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, i2o_iop_free(c); disable: - if (!enabled) - pci_disable_device(pdev); + pci_disable_device(pdev); return rc; } -- cgit v1.2.3 From adbc2a102252994c36102008293b52760613d6c3 Mon Sep 17 00:00:00 2001 From: Jason Gaston Date: Wed, 22 Nov 2006 15:19:12 -0800 Subject: i2c-i801: SMBus patch for Intel ICH9 This updated patch adds the Intel ICH9 LPC and SMBus Controller DID's. Thi= s patch relies on the irq ICH9 patch to pci_ids.h. Signed-off-by: Jason Gaston Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 510816c16da3..04bee524e31a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -125,6 +125,7 @@ config I2C_I801 ICH7 ESB2 ICH8 + ICH9 This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index bbb2fbee836f..c7be2fdbd86b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -33,6 +33,7 @@ ICH7 27DA ESB2 269B ICH8 283E + ICH9 2930 This driver supports several versions of Intel's I/O Controller Hubs (ICH). For SMBus support, they are similar to the PIIX4 and are part of Intel's '810' and other chipsets. @@ -457,6 +458,7 @@ static struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, { 0, } }; -- cgit v1.2.3 From ac9e98918776d8fa6dc38bfa6d298a7dbcbac2cb Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Mon, 13 Nov 2006 15:12:45 -0800 Subject: PCI: Change memory allocation for acpiphp slots Change memory allocation for acpiphp slots Change the "struct slot" that acpiphp uses for managing it's slots to directly contain the memory for the needed struct hotplug_slot_info and the slot's name. This way we need only two memory allocations per slot instead of four. While we are at it: make_slot_name() is just a wrapper around snprintf() knowing the right arguments to call it. Since the function makes just one function call and is only called from one place I inlined it by hand. Finally this fixes a possible bug waiting for someone to hit it. There were two unused local variables in acpiphp_register_hotplug_slot(). gcc did not find them because they were used in memory allocations with sizeof(*var). They had the same types as the target of the allocation, but nevertheless this was just weird. Signed-off-by: Rolf Eike Beer Acked-by: Matthew Wilcox Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/acpiphp.h | 4 ++-- drivers/pci/hotplug/acpiphp_core.c | 35 +++++------------------------------ 2 files changed, 7 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 59c5b242d86d..ddbadd95387e 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -62,10 +62,10 @@ struct acpiphp_slot; struct slot { struct hotplug_slot *hotplug_slot; struct acpiphp_slot *acpi_slot; + struct hotplug_slot_info info; + char name[SLOT_NAME_SIZE]; }; - - /** * struct acpiphp_bridge - PCI bridge information * diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index c8b690741149..40c79b03c7ef 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -312,18 +312,6 @@ static int __init init_acpi(void) return retval; } - -/** - * make_slot_name - make a slot name that appears in pcihpfs - * @slot: slot to name - * - */ -static void make_slot_name(struct slot *slot) -{ - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%u", - slot->acpi_slot->sun); -} - /** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free @@ -334,8 +322,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot) dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot); } @@ -344,26 +330,19 @@ static void release_slot(struct hotplug_slot *hotplug_slot) int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) { struct slot *slot; - struct hotplug_slot *hotplug_slot; - struct hotplug_slot_info *hotplug_slot_info; int retval = -ENOMEM; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) goto error; - slot->hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); + slot->hotplug_slot = kzalloc(sizeof(*slot->hotplug_slot), GFP_KERNEL); if (!slot->hotplug_slot) goto error_slot; - slot->hotplug_slot->info = kzalloc(sizeof(*hotplug_slot_info), - GFP_KERNEL); - if (!slot->hotplug_slot->info) - goto error_hpslot; + slot->hotplug_slot->info = &slot->info; - slot->hotplug_slot->name = kzalloc(SLOT_NAME_SIZE, GFP_KERNEL); - if (!slot->hotplug_slot->name) - goto error_info; + slot->hotplug_slot->name = slot->name; slot->hotplug_slot->private = slot; slot->hotplug_slot->release = &release_slot; @@ -378,21 +357,17 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; acpiphp_slot->slot = slot; - make_slot_name(slot); + snprintf(slot->name, sizeof(slot->name), "%u", slot->acpi_slot->sun); retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - goto error_name; + goto error_hpslot; } info("Slot [%s] registered\n", slot->hotplug_slot->name); return 0; -error_name: - kfree(slot->hotplug_slot->name); -error_info: - kfree(slot->hotplug_slot->info); error_hpslot: kfree(slot->hotplug_slot); error_slot: -- cgit v1.2.3 From a57ed79ef1b71f6da44ebeabb41d019d172fb261 Mon Sep 17 00:00:00 2001 From: John Rose Date: Mon, 13 Nov 2006 15:12:52 -0800 Subject: PCI: rpaphp: change device tree examination Change the criterion that RPA PCI Hotplug and RPA DLPAR use when determining the hotplug capabilities of a given device node. The "device_type" property is less consistent than "name" across PCI nodes on newer hardware. Signed-off-by: John Rose Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/rpadlpar_core.c | 2 +- drivers/pci/hotplug/rpaphp_core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index 46825fee3ae4..72383467a0d5 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -63,7 +63,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name, char *type; int rc; - while ((np = of_find_node_by_type(np, "pci"))) { + while ((np = of_find_node_by_name(np, "pci"))) { rc = rpaphp_get_drc_props(np, NULL, &name, &type, NULL); if (rc == 0) if (!strcmp(drc_name, name) && !strcmp(drc_type, type)) diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 141486df235b..71a2cb8baa4a 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -356,7 +356,7 @@ static int __init rpaphp_init(void) info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); init_MUTEX(&rpaphp_sem); - while ((dn = of_find_node_by_type(dn, "pci"))) + while ((dn = of_find_node_by_name(dn, "pci"))) rpaphp_add_slot(dn); return 0; -- cgit v1.2.3 From 407f452b05f9e5d019c07077d05238bca1b45c4c Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 13 Nov 2006 15:13:00 -0800 Subject: pciehp: remove unnecessary free_irq This patch fixes the problem that the following error messages is reported when pciehp driver is rmmoded. Trying to free already-free IRQ XX The cause of this problem is that pciehp driver is doing unknown 2nd free_irq at driver unloading. This patch removes this unknown 2nd free_irq call. Note: The pciehp driver should be adapted to standard device driver mode. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_core.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index f93e81e2d2c7..f13f31323e85 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -521,14 +521,9 @@ static void __exit unload_pciehpd(void) } -static int hpdriver_context = 0; - static void pciehp_remove (struct pcie_device *device) { - printk("%s ENTRY\n", __FUNCTION__); - printk("%s -> Call free_irq for irq = %d\n", - __FUNCTION__, device->irq); - free_irq(device->irq, &hpdriver_context); + /* XXX - Needs to be adapted to device driver model */ } #ifdef CONFIG_PM -- cgit v1.2.3 From 9d167dc367f22c07285137370816b83b4be9c697 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 13 Nov 2006 15:13:09 -0800 Subject: pciehp: remove unnecessary pci_disable_msi This patch fixes the problem that "irq XX: nobody cared" kernel oops is reported when pciehp is once rmmoded and insmoded again. The cause of this problem is pciehp driver calls pci_disable_msi() at controller release time, even though it must be done by PCI Express Port Bus driver. This patch removes unnecessary pci_disable_msi() call from pciehp driver. Signed-off-by: Kenji Kaneshige Signed-off-by: Kristen Carlson Accardi Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/pciehp_hpc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 1c551c697c35..6d3f580f2666 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -718,8 +718,6 @@ static void hpc_release_ctlr(struct controller *ctrl) if (php_ctlr->irq) { free_irq(php_ctlr->irq, ctrl); php_ctlr->irq = 0; - if (!pcie_mch_quirk) - pci_disable_msi(php_ctlr->pci_dev); } } if (php_ctlr->pci_dev) -- cgit v1.2.3 From b0d974e90d6f9fbf3a926defbbc76543cff74426 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 17 Nov 2006 02:19:25 +0100 Subject: PCI: ibmphp_pci.c: fix NULL dereference The correct order is: NULL check before dereference Spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/pci/hotplug/ibmphp_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index d87a9e3eaeeb..d8f05d7a3c72 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -1371,12 +1371,12 @@ static int unconfigure_boot_bridge (u8 busno, u8 device, u8 function) } bus = ibmphp_find_res_bus (sec_number); - debug ("bus->busno is %x\n", bus->busno); - debug ("sec_number is %x\n", sec_number); if (!bus) { err ("cannot find Bus structure for the bridged device\n"); return -EINVAL; } + debug("bus->busno is %x\n", bus->busno); + debug("sec_number is %x\n", sec_number); ibmphp_remove_bus (bus, busno); -- cgit v1.2.3 From 116af378201ef793424cd10508ccf18b06d8a021 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 25 Oct 2006 13:44:59 +1000 Subject: Driver core: add notification of bus events I finally did as you suggested and added the notifier to the struct bus_type itself. There are still problems to be expected is something attaches to a bus type where the code can hook in different struct device sub-classes (which is imho a big bogosity but I won't even try to argue that case now) but it will solve nicely a number of issues I've had so far. That also means that clients interested in registering for such notifications have to do it before devices are added and after bus types are registered. Fortunately, most bus types that matter for the various usage scenarios I have in mind are registerd at postcore_initcall time, which means I have a really nice spot at arch_initcall time to add my notifiers. There are 4 notifications provided. Device being added (before hooked to the bus) and removed (failure of previous case or after being unhooked from the bus), along with driver being bound to a device and about to be unbound. The usage I have for these are: - The 2 first ones are used to maintain a struct device_ext that is hooked to struct device.firmware_data. This structure contains for now a pointer to the Open Firmware node related to the device (if any), the NUMA node ID (for quick access to it) and the DMA operations pointers & iommu table instance for DMA to/from this device. For bus types I own (like IBM VIO or EBUS), I just maintain that structure directly from the bus code when creating the devices. But for bus types managed by generic code like PCI or platform (actually, of_platform which is a variation of platform linked to Open Firmware device-tree), I need this notifier. - The other two ones have a completely different usage scenario. I have cases where multiple devices and their drivers depend on each other. For example, the IBM EMAC network driver needs to attach to a MAL DMA engine which is a separate device, and a PHY interface which is also a separate device. They are all of_platform_device's (well, about to be with my upcoming patches) but there is no say in what precise order the core will "probe" them and instanciate the various modules. The solution I found for that is to have the drivers for emac to use multithread_probe, and wait for a driver to be bound to the target MAL and PHY control devices (the device-tree contains reference to the MAL and PHY interface nodes, which I can then match to of_platform_devices). Right now, I've been polling, but with that notifier, I can more cleanly wait (with a timeout of course). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 14 ++++++++++++++ drivers/base/core.c | 12 ++++++++++++ drivers/base/dd.c | 10 ++++++++++ include/linux/device.h | 25 +++++++++++++++++++++++++ 4 files changed, 61 insertions(+) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 7d8a7ce73fb3..ed3e8a2be64a 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -724,6 +724,8 @@ int bus_register(struct bus_type * bus) { int retval; + BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier); + retval = kobject_set_name(&bus->subsys.kset.kobj, "%s", bus->name); if (retval) goto out; @@ -782,6 +784,18 @@ void bus_unregister(struct bus_type * bus) subsystem_unregister(&bus->subsys); } +int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&bus->bus_notifier, nb); +} +EXPORT_SYMBOL_GPL(bus_register_notifier); + +int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&bus->bus_notifier, nb); +} +EXPORT_SYMBOL_GPL(bus_unregister_notifier); + int __init buses_init(void) { return subsystem_register(&bus_subsys); diff --git a/drivers/base/core.c b/drivers/base/core.c index 002fde46d38d..d4f35d8902a2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -428,6 +429,11 @@ int device_add(struct device *dev) if (platform_notify) platform_notify(dev); + /* notify clients of device entry (new way) */ + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->bus_notifier, + BUS_NOTIFY_ADD_DEVICE, dev); + dev->uevent_attr.attr.name = "uevent"; dev->uevent_attr.attr.mode = S_IWUSR; if (dev->driver) @@ -504,6 +510,9 @@ int device_add(struct device *dev) BusError: device_pm_remove(dev); PMError: + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->bus_notifier, + BUS_NOTIFY_DEL_DEVICE, dev); device_remove_groups(dev); GroupError: device_remove_attrs(dev); @@ -622,6 +631,9 @@ void device_del(struct device * dev) */ if (platform_notify_remove) platform_notify_remove(dev); + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->bus_notifier, + BUS_NOTIFY_DEL_DEVICE, dev); bus_remove_device(dev); device_pm_remove(dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index c5d6bb4290ad..9c88b1e34bc3 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -52,6 +52,11 @@ int device_bind_driver(struct device *dev) pr_debug("bound device '%s' to driver '%s'\n", dev->bus_id, dev->driver->name); + + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->bus_notifier, + BUS_NOTIFY_BOUND_DRIVER, dev); + klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, kobject_name(&dev->kobj)); @@ -288,6 +293,11 @@ static void __device_release_driver(struct device * dev) sysfs_remove_link(&dev->kobj, "driver"); klist_remove(&dev->knode_driver); + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->bus_notifier, + BUS_NOTIFY_UNBIND_DRIVER, + dev); + if (dev->bus && dev->bus->remove) dev->bus->remove(dev); else if (drv->remove) diff --git a/include/linux/device.h b/include/linux/device.h index 9d4f6a963936..b00e02711393 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -42,6 +42,8 @@ struct bus_type { struct klist klist_devices; struct klist klist_drivers; + struct blocking_notifier_head bus_notifier; + struct bus_attribute * bus_attrs; struct device_attribute * dev_attrs; struct driver_attribute * drv_attrs; @@ -75,6 +77,29 @@ int __must_check bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int (*fn)(struct device_driver *, void *)); +/* + * Bus notifiers: Get notified of addition/removal of devices + * and binding/unbinding of drivers to devices. + * In the long run, it should be a replacement for the platform + * notify hooks. + */ +struct notifier_block; + +extern int bus_register_notifier(struct bus_type *bus, + struct notifier_block *nb); +extern int bus_unregister_notifier(struct bus_type *bus, + struct notifier_block *nb); + +/* All 4 notifers below get called with the target struct device * + * as an argument. Note that those functions are likely to be called + * with the device semaphore held in the core, so be careful. + */ +#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ +#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ +#define BUS_NOTIFY_BOUND_DRIVER 0x00000003 /* driver bound to device */ +#define BUS_NOTIFY_UNBIND_DRIVER 0x00000004 /* driver about to be + unbound */ + /* driverfs interface for exporting bus attributes */ struct bus_attribute { -- cgit v1.2.3 From 1901fb2604fbcd53201f38725182ea807581159e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sat, 7 Oct 2006 21:55:55 +0200 Subject: Driver core: fix "driver" symlink timing Create the "driver" link before the child device may be created by the probing logic. This makes it possible for userspace (udev), to determine the driver property of the parent device, at the time the child device is created. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 82 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9c88b1e34bc3..510e7884975f 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -26,28 +26,12 @@ #define to_drv(node) container_of(node, struct device_driver, kobj.entry) -/** - * device_bind_driver - bind a driver to one device. - * @dev: device. - * - * Allow manual attachment of a driver to a device. - * Caller must have already set @dev->driver. - * - * Note that this does not modify the bus reference count - * nor take the bus's rwsem. Please verify those are accounted - * for before calling this. (It is ok to call with no other effort - * from a driver's probe() method.) - * - * This function must be called with @dev->sem held. - */ -int device_bind_driver(struct device *dev) +static void driver_bound(struct device *dev) { - int ret; - if (klist_node_attached(&dev->knode_driver)) { printk(KERN_WARNING "%s: device %s already bound\n", __FUNCTION__, kobject_name(&dev->kobj)); - return 0; + return; } pr_debug("bound device '%s' to driver '%s'\n", @@ -58,6 +42,12 @@ int device_bind_driver(struct device *dev) BUS_NOTIFY_BOUND_DRIVER, dev); klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); +} + +static int driver_sysfs_add(struct device *dev) +{ + int ret; + ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, kobject_name(&dev->kobj)); if (ret == 0) { @@ -70,6 +60,36 @@ int device_bind_driver(struct device *dev) return ret; } +static void driver_sysfs_remove(struct device *dev) +{ + struct device_driver *drv = dev->driver; + + if (drv) { + sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); + sysfs_remove_link(&dev->kobj, "driver"); + } +} + +/** + * device_bind_driver - bind a driver to one device. + * @dev: device. + * + * Allow manual attachment of a driver to a device. + * Caller must have already set @dev->driver. + * + * Note that this does not modify the bus reference count + * nor take the bus's rwsem. Please verify those are accounted + * for before calling this. (It is ok to call with no other effort + * from a driver's probe() method.) + * + * This function must be called with @dev->sem held. + */ +int device_bind_driver(struct device *dev) +{ + driver_bound(dev); + return driver_sysfs_add(dev); +} + struct stupid_thread_structure { struct device_driver *drv; struct device *dev; @@ -90,30 +110,32 @@ static int really_probe(void *void_data) drv->bus->name, drv->name, dev->bus_id); dev->driver = drv; + if (driver_sysfs_add(dev)) { + printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", + __FUNCTION__, dev->bus_id); + goto probe_failed; + } + if (dev->bus->probe) { ret = dev->bus->probe(dev); - if (ret) { - dev->driver = NULL; + if (ret) goto probe_failed; - } } else if (drv->probe) { ret = drv->probe(dev); - if (ret) { - dev->driver = NULL; + if (ret) goto probe_failed; - } - } - if (device_bind_driver(dev)) { - printk(KERN_ERR "%s: device_bind_driver(%s) failed\n", - __FUNCTION__, dev->bus_id); - /* How does undo a ->probe? We're screwed. */ } + + driver_bound(dev); ret = 1; pr_debug("%s: Bound Device %s to Driver %s\n", drv->bus->name, dev->bus_id, drv->name); goto done; probe_failed: + driver_sysfs_remove(dev); + dev->driver = NULL; + if (ret == -ENODEV || ret == -ENXIO) { /* Driver matched, but didn't support device * or device not found. @@ -289,7 +311,7 @@ static void __device_release_driver(struct device * dev) drv = dev->driver; if (drv) { get_driver(drv); - sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); + driver_sysfs_remove(dev); sysfs_remove_link(&dev->kobj, "driver"); klist_remove(&dev->knode_driver); -- cgit v1.2.3 From f0ee61a6cecd100301a60d99feb187776533b2a2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 23 Oct 2006 10:40:54 -0700 Subject: Driver Core: Move virtual_device_parent() to core.c It doesn't need to be global or in device.h Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 17 ----------------- drivers/base/core.c | 17 +++++++++++++++++ include/linux/device.h | 2 -- 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/base/class.c b/drivers/base/class.c index 0ff267a248db..2e705f6abb4c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -893,23 +893,6 @@ void class_interface_unregister(struct class_interface *class_intf) class_put(parent); } -int virtual_device_parent(struct device *dev) -{ - if (!dev->class) - return -ENODEV; - - if (!dev->class->virtual_dir) { - static struct kobject *virtual_dir = NULL; - - if (!virtual_dir) - virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); - dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); - } - - dev->kobj.parent = dev->class->virtual_dir; - return 0; -} - int __init classes_init(void) { int retval; diff --git a/drivers/base/core.c b/drivers/base/core.c index d4f35d8902a2..dbcd40b987d2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -384,6 +384,23 @@ void device_initialize(struct device *dev) device_init_wakeup(dev, 0); } +static int virtual_device_parent(struct device *dev) +{ + if (!dev->class) + return -ENODEV; + + if (!dev->class->virtual_dir) { + static struct kobject *virtual_dir = NULL; + + if (!virtual_dir) + virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual"); + dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name); + } + + dev->kobj.parent = dev->class->virtual_dir; + return 0; +} + /** * device_add - add device to device hierarchy. * @dev: device. diff --git a/include/linux/device.h b/include/linux/device.h index b00e02711393..00b29e0c5ce0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -440,8 +440,6 @@ extern struct device *device_create(struct class *cls, struct device *parent, __attribute__((format(printf,4,5))); extern void device_destroy(struct class *cls, dev_t devt); -extern int virtual_device_parent(struct device *dev); - /* * Platform "fixup" functions - allow the platform to have their say * about devices and actions that the general device layer doesn't -- cgit v1.2.3 From 40fa54226f518a9bc97ed1d711c0016e416e3782 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 24 Oct 2006 00:37:58 +0100 Subject: Driver core: make old versions of udev work properly If CONFIG_SYSFS_DEPRECATED is enabled, old versions of udev will work properly with devices that are associated with a class. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 59 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index dbcd40b987d2..8f8347b9197f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -384,6 +384,19 @@ void device_initialize(struct device *dev) device_init_wakeup(dev, 0); } +#ifdef CONFIG_SYSFS_DEPRECATED +int setup_parent(struct device *dev, struct device *parent) +{ + /* Set the parent to the class, not the parent device */ + /* this keeps sysfs from having a symlink to make old udevs happy */ + if (dev->class) + dev->kobj.parent = &dev->class->subsys.kset.kobj; + else if (parent) + dev->kobj.parent = &parent->kobj; + + return 0; +} +#else static int virtual_device_parent(struct device *dev) { if (!dev->class) @@ -401,6 +414,22 @@ static int virtual_device_parent(struct device *dev) return 0; } +int setup_parent(struct device *dev, struct device *parent) +{ + int error; + + /* if this is a class device, and has no parent, create one */ + if ((dev->class) && (parent == NULL)) { + error = virtual_device_parent(dev); + if (error) + return error; + } else if (parent) + dev->kobj.parent = &parent->kobj; + + return 0; +} +#endif + /** * device_add - add device to device hierarchy. * @dev: device. @@ -423,23 +452,18 @@ int device_add(struct device *dev) if (!dev || !strlen(dev->bus_id)) goto Error; - /* if this is a class device, and has no parent, create one */ - if ((dev->class) && (dev->parent == NULL)) { - error = virtual_device_parent(dev); - if (error) - goto Error; - } + pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); parent = get_device(dev->parent); - pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id); + error = setup_parent(dev, parent); + if (error) + goto Error; /* first, register with generic layer. */ kobject_set_name(&dev->kobj, "%s", dev->bus_id); - if (parent) - dev->kobj.parent = &parent->kobj; - - if ((error = kobject_add(&dev->kobj))) + error = kobject_add(&dev->kobj); + if (error) goto Error; /* notify platform of device entry */ @@ -484,8 +508,11 @@ int device_add(struct device *dev) if (dev->class) { sysfs_create_link(&dev->kobj, &dev->class->subsys.kset.kobj, "subsystem"); - sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, - dev->bus_id); + /* If this is not a "fake" compatible device, then create the + * symlink from the class to the device. */ + if (dev->kobj.parent != &dev->class->subsys.kset.kobj) + sysfs_create_link(&dev->class->subsys.kset.kobj, + &dev->kobj, dev->bus_id); if (parent) { sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); class_name = make_class_name(dev->class->name, &dev->kobj); @@ -623,7 +650,11 @@ void device_del(struct device * dev) } if (dev->class) { sysfs_remove_link(&dev->kobj, "subsystem"); - sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); + /* If this is not a "fake" compatible device, remove the + * symlink from the class to the device. */ + if (dev->kobj.parent != &dev->class->subsys.kset.kobj) + sysfs_remove_link(&dev->class->subsys.kset.kobj, + dev->bus_id); class_name = make_class_name(dev->class->name, &dev->kobj); if (parent) { sysfs_remove_link(&dev->kobj, "device"); -- cgit v1.2.3 From b9cafc7d5b8af0c71896f60dfcff40c71bd38a9a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Sep 2006 11:23:28 +0200 Subject: CONFIG_SYSFS_DEPRECATED - bus symlinks Turn off the bus symlinks if CONFIG_SYSFS_DEPRECATED is enabled Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ed3e8a2be64a..472810f8e6e7 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -355,6 +355,21 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev) } } +#ifdef CONFIG_SYSFS_DEPRECATED +static int make_deprecated_bus_links(struct device *dev) +{ + return sysfs_create_link(&dev->kobj, + &dev->bus->subsys.kset.kobj, "bus"); +} + +static void remove_deprecated_bus_links(struct device *dev) +{ + sysfs_remove_link(&dev->kobj, "bus"); +} +#else +static inline int make_deprecated_bus_links(struct device *dev) { return 0; } +static inline void remove_deprecated_bus_links(struct device *dev) { } +#endif /** * bus_add_device - add device to bus @@ -381,8 +396,7 @@ int bus_add_device(struct device * dev) &dev->bus->subsys.kset.kobj, "subsystem"); if (error) goto out_subsys; - error = sysfs_create_link(&dev->kobj, - &dev->bus->subsys.kset.kobj, "bus"); + error = make_deprecated_bus_links(dev); if (error) goto out_deprecated; } @@ -436,7 +450,7 @@ void bus_remove_device(struct device * dev) { if (dev->bus) { sysfs_remove_link(&dev->kobj, "subsystem"); - sysfs_remove_link(&dev->kobj, "bus"); + remove_deprecated_bus_links(dev); sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); device_remove_attrs(dev->bus, dev); if (dev->is_registered) { -- cgit v1.2.3 From 99ef3ef8d5f2f5b5312627127ad63df27c0d0d05 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Sep 2006 11:23:28 +0200 Subject: CONFIG_SYSFS_DEPRECATED - device symlinks Turn off device symlinks CONFIG_SYSFS_DEPRECATED is enabled. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 8f8347b9197f..b565b7e9d40b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -513,11 +513,13 @@ int device_add(struct device *dev) if (dev->kobj.parent != &dev->class->subsys.kset.kobj) sysfs_create_link(&dev->class->subsys.kset.kobj, &dev->kobj, dev->bus_id); +#ifdef CONFIG_SYSFS_DEPRECATED if (parent) { sysfs_create_link(&dev->kobj, &dev->parent->kobj, "device"); class_name = make_class_name(dev->class->name, &dev->kobj); sysfs_create_link(&dev->parent->kobj, &dev->kobj, class_name); } +#endif } if ((error = device_add_attrs(dev))) @@ -639,7 +641,6 @@ void put_device(struct device * dev) void device_del(struct device * dev) { struct device * parent = dev->parent; - char *class_name = NULL; struct class_interface *class_intf; if (parent) @@ -655,12 +656,16 @@ void device_del(struct device * dev) if (dev->kobj.parent != &dev->class->subsys.kset.kobj) sysfs_remove_link(&dev->class->subsys.kset.kobj, dev->bus_id); - class_name = make_class_name(dev->class->name, &dev->kobj); +#ifdef CONFIG_SYSFS_DEPRECATED if (parent) { - sysfs_remove_link(&dev->kobj, "device"); + char *class_name = make_class_name(dev->class->name, + &dev->kobj); sysfs_remove_link(&dev->parent->kobj, class_name); + kfree(class_name); + sysfs_remove_link(&dev->kobj, "device"); } - kfree(class_name); +#endif + down(&dev->class->sem); /* notify any interfaces that the device is now gone */ list_for_each_entry(class_intf, &dev->class->interfaces, node) @@ -869,8 +874,10 @@ int device_rename(struct device *dev, char *new_name) pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if ((dev->class) && (dev->parent)) old_class_name = make_class_name(dev->class->name, &dev->kobj); +#endif if (dev->class) { old_symlink_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); @@ -885,6 +892,7 @@ int device_rename(struct device *dev, char *new_name) error = kobject_rename(&dev->kobj, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { new_class_name = make_class_name(dev->class->name, &dev->kobj); if (new_class_name) { @@ -893,6 +901,8 @@ int device_rename(struct device *dev, char *new_name) sysfs_remove_link(&dev->parent->kobj, old_class_name); } } +#endif + if (dev->class) { sysfs_remove_link(&dev->class->subsys.kset.kobj, old_symlink_name); -- cgit v1.2.3 From a87cb2ac4a78c590583b52a3ed196adc6c25b6c9 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Sep 2006 11:23:28 +0200 Subject: CONFIG_SYSFS_DEPRECATED - PHYSDEV* uevent variables Disable the PHYSDEV* uevent variables if CONFIG_SYSFS_DEPRECATED is enabled. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index b565b7e9d40b..f544adc5a5e2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -154,20 +154,24 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, "MINOR=%u", MINOR(dev->devt)); } +#ifdef CONFIG_SYSFS_DEPRECATED /* add bus name (same as SUBSYSTEM, deprecated) */ if (dev->bus) add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "PHYSDEVBUS=%s", dev->bus->name); +#endif /* add driver name (PHYSDEV* values are deprecated)*/ if (dev->driver) { add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "DRIVER=%s", dev->driver->name); +#ifdef CONFIG_SYSFS_DEPRECATED add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, "PHYSDEVDRIVER=%s", dev->driver->name); +#endif } /* terminate, set to next free slot, shrink available space */ -- cgit v1.2.3 From 805fab474ed75f9603dbde6fa74a2976868b4bd2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 14 Sep 2006 11:23:28 +0200 Subject: CONFIG_SYSFS_DEPRECATED - class symlinks Turn off class symlinks CONFIG_SYSFS_DEPRECATED is enabled. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 149 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 98 insertions(+), 51 deletions(-) (limited to 'drivers') diff --git a/drivers/base/class.c b/drivers/base/class.c index 2e705f6abb4c..f098881f45b2 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -352,6 +352,92 @@ static const char *class_uevent_name(struct kset *kset, struct kobject *kobj) return class_dev->class->name; } +#ifdef CONFIG_SYSFS_DEPRECATED +char *make_class_name(const char *name, struct kobject *kobj) +{ + char *class_name; + int size; + + size = strlen(name) + strlen(kobject_name(kobj)) + 2; + + class_name = kmalloc(size, GFP_KERNEL); + if (!class_name) + return ERR_PTR(-ENOMEM); + + strcpy(class_name, name); + strcat(class_name, ":"); + strcat(class_name, kobject_name(kobj)); + return class_name; +} + +static int deprecated_class_uevent(char **envp, int num_envp, int *cur_index, + char *buffer, int buffer_size, + int *cur_len, + struct class_device *class_dev) +{ + struct device *dev = class_dev->dev; + char *path; + + if (!dev) + return 0; + + /* add device, backing this class device (deprecated) */ + path = kobject_get_path(&dev->kobj, GFP_KERNEL); + + add_uevent_var(envp, num_envp, cur_index, buffer, buffer_size, + cur_len, "PHYSDEVPATH=%s", path); + kfree(path); + + if (dev->bus) + add_uevent_var(envp, num_envp, cur_index, + buffer, buffer_size, cur_len, + "PHYSDEVBUS=%s", dev->bus->name); + + if (dev->driver) + add_uevent_var(envp, num_envp, cur_index, + buffer, buffer_size, cur_len, + "PHYSDEVDRIVER=%s", dev->driver->name); + return 0; +} + +static int make_deprecated_class_device_links(struct class_device *class_dev) +{ + char *class_name; + int error; + + if (!class_dev->dev) + return 0; + + class_name = make_class_name(class_dev->class->name, &class_dev->kobj); + error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, + class_name); + kfree(class_name); + return error; +} + +static void remove_deprecated_class_device_links(struct class_device *class_dev) +{ + char *class_name; + + if (!class_dev->dev) + return; + + class_name = make_class_name(class_dev->class->name, &class_dev->kobj); + sysfs_remove_link(&class_dev->dev->kobj, class_name); + kfree(class_name); +} +#else +static inline int deprecated_class_uevent(char **envp, int num_envp, + int *cur_index, char *buffer, + int buffer_size, int *cur_len, + struct class_device *class_dev) +{ return 0; } +static inline int make_deprecated_class_device_links(struct class_device *cd) +{ return 0; } +static void remove_deprecated_class_device_links(struct class_device *cd) +{ } +#endif + static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, int num_envp, char *buffer, int buffer_size) { @@ -362,25 +448,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj, char **envp, pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id); - if (class_dev->dev) { - /* add device, backing this class device (deprecated) */ - struct device *dev = class_dev->dev; - char *path = kobject_get_path(&dev->kobj, GFP_KERNEL); - - add_uevent_var(envp, num_envp, &i, buffer, buffer_size, - &length, "PHYSDEVPATH=%s", path); - kfree(path); - - if (dev->bus) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVBUS=%s", dev->bus->name); - - if (dev->driver) - add_uevent_var(envp, num_envp, &i, - buffer, buffer_size, &length, - "PHYSDEVDRIVER=%s", dev->driver->name); - } + deprecated_class_uevent(envp, num_envp, &i, buffer, buffer_size, + &length, class_dev); if (MAJOR(class_dev->devt)) { add_uevent_var(envp, num_envp, &i, @@ -506,29 +575,11 @@ void class_device_initialize(struct class_device *class_dev) INIT_LIST_HEAD(&class_dev->node); } -char *make_class_name(const char *name, struct kobject *kobj) -{ - char *class_name; - int size; - - size = strlen(name) + strlen(kobject_name(kobj)) + 2; - - class_name = kmalloc(size, GFP_KERNEL); - if (!class_name) - return ERR_PTR(-ENOMEM); - - strcpy(class_name, name); - strcat(class_name, ":"); - strcat(class_name, kobject_name(kobj)); - return class_name; -} - int class_device_add(struct class_device *class_dev) { struct class *parent_class = NULL; struct class_device *parent_class_dev = NULL; struct class_interface *class_intf; - char *class_name = NULL; int error = -EINVAL; class_dev = class_device_get(class_dev); @@ -599,19 +650,17 @@ int class_device_add(struct class_device *class_dev) goto out5; if (class_dev->dev) { - class_name = make_class_name(class_dev->class->name, - &class_dev->kobj); error = sysfs_create_link(&class_dev->kobj, &class_dev->dev->kobj, "device"); if (error) goto out6; - error = sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, - class_name); - if (error) - goto out7; } error = class_device_add_groups(class_dev); + if (error) + goto out7; + + error = make_deprecated_class_device_links(class_dev); if (error) goto out8; @@ -629,8 +678,7 @@ int class_device_add(struct class_device *class_dev) goto out1; out8: - if (class_dev->dev) - sysfs_remove_link(&class_dev->kobj, class_name); + class_device_remove_groups(class_dev); out7: if (class_dev->dev) sysfs_remove_link(&class_dev->kobj, "device"); @@ -649,7 +697,6 @@ int class_device_add(struct class_device *class_dev) class_put(parent_class); out1: class_device_put(class_dev); - kfree(class_name); return error; } @@ -726,7 +773,6 @@ void class_device_del(struct class_device *class_dev) struct class *parent_class = class_dev->class; struct class_device *parent_device = class_dev->parent; struct class_interface *class_intf; - char *class_name = NULL; if (parent_class) { down(&parent_class->sem); @@ -738,10 +784,8 @@ void class_device_del(struct class_device *class_dev) } if (class_dev->dev) { - class_name = make_class_name(class_dev->class->name, - &class_dev->kobj); + remove_deprecated_class_device_links(class_dev); sysfs_remove_link(&class_dev->kobj, "device"); - sysfs_remove_link(&class_dev->dev->kobj, class_name); } sysfs_remove_link(&class_dev->kobj, "subsystem"); class_device_remove_file(class_dev, &class_dev->uevent_attr); @@ -755,7 +799,6 @@ void class_device_del(struct class_device *class_dev) class_device_put(parent_device); class_put(parent_class); - kfree(class_name); } void class_device_unregister(struct class_device *class_dev) @@ -804,14 +847,17 @@ int class_device_rename(struct class_device *class_dev, char *new_name) pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if (class_dev->dev) old_class_name = make_class_name(class_dev->class->name, &class_dev->kobj); +#endif strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); +#ifdef CONFIG_SYSFS_DEPRECATED if (class_dev->dev) { new_class_name = make_class_name(class_dev->class->name, &class_dev->kobj); @@ -819,6 +865,7 @@ int class_device_rename(struct class_device *class_dev, char *new_name) new_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name); } +#endif class_device_put(class_dev); kfree(old_class_name); -- cgit v1.2.3 From 805952a889c4d0fdab23307c14c5ce9571f81233 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert vt code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/char/vt.c | 81 +++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 8e4413f6fbaf..87587b4385ab 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -112,7 +112,7 @@ struct con_driver { const struct consw *con; const char *desc; - struct class_device *class_dev; + struct device *dev; int node; int first; int last; @@ -3023,10 +3023,10 @@ static inline int vt_unbind(struct con_driver *con) } #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ -static ssize_t store_bind(struct class_device *class_device, +static ssize_t store_bind(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct con_driver *con = class_get_devdata(class_device); + struct con_driver *con = dev_get_drvdata(dev); int bind = simple_strtoul(buf, NULL, 0); if (bind) @@ -3037,17 +3037,19 @@ static ssize_t store_bind(struct class_device *class_device, return count; } -static ssize_t show_bind(struct class_device *class_device, char *buf) +static ssize_t show_bind(struct device *dev, struct device_attribute *attr, + char *buf) { - struct con_driver *con = class_get_devdata(class_device); + struct con_driver *con = dev_get_drvdata(dev); int bind = con_is_bound(con->con); return snprintf(buf, PAGE_SIZE, "%i\n", bind); } -static ssize_t show_name(struct class_device *class_device, char *buf) +static ssize_t show_name(struct device *dev, struct device_attribute *attr, + char *buf) { - struct con_driver *con = class_get_devdata(class_device); + struct con_driver *con = dev_get_drvdata(dev); return snprintf(buf, PAGE_SIZE, "%s %s\n", (con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)", @@ -3055,43 +3057,40 @@ static ssize_t show_name(struct class_device *class_device, char *buf) } -static struct class_device_attribute class_device_attrs[] = { +static struct device_attribute device_attrs[] = { __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind), __ATTR(name, S_IRUGO, show_name, NULL), }; -static int vtconsole_init_class_device(struct con_driver *con) +static int vtconsole_init_device(struct con_driver *con) { int i; int error = 0; con->flag |= CON_DRIVER_FLAG_ATTR; - class_set_devdata(con->class_dev, con); - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { - error = class_device_create_file(con->class_dev, - &class_device_attrs[i]); + dev_set_drvdata(con->dev, con); + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { + error = device_create_file(con->dev, &device_attrs[i]); if (error) break; } if (error) { while (--i >= 0) - class_device_remove_file(con->class_dev, - &class_device_attrs[i]); + device_remove_file(con->dev, &device_attrs[i]); con->flag &= ~CON_DRIVER_FLAG_ATTR; } return error; } -static void vtconsole_deinit_class_device(struct con_driver *con) +static void vtconsole_deinit_device(struct con_driver *con) { int i; if (con->flag & CON_DRIVER_FLAG_ATTR) { - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(con->class_dev, - &class_device_attrs[i]); + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) + device_remove_file(con->dev, &device_attrs[i]); con->flag &= ~CON_DRIVER_FLAG_ATTR; } } @@ -3179,18 +3178,17 @@ int register_con_driver(const struct consw *csw, int first, int last) if (retval) goto err; - con_driver->class_dev = class_device_create(vtconsole_class, NULL, - MKDEV(0, con_driver->node), - NULL, "vtcon%i", - con_driver->node); + con_driver->dev = device_create(vtconsole_class, NULL, + MKDEV(0, con_driver->node), + "vtcon%i", con_driver->node); - if (IS_ERR(con_driver->class_dev)) { - printk(KERN_WARNING "Unable to create class_device for %s; " + if (IS_ERR(con_driver->dev)) { + printk(KERN_WARNING "Unable to create device for %s; " "errno = %ld\n", con_driver->desc, - PTR_ERR(con_driver->class_dev)); - con_driver->class_dev = NULL; + PTR_ERR(con_driver->dev)); + con_driver->dev = NULL; } else { - vtconsole_init_class_device(con_driver); + vtconsole_init_device(con_driver); } err: @@ -3226,12 +3224,12 @@ int unregister_con_driver(const struct consw *csw) if (con_driver->con == csw && con_driver->flag & CON_DRIVER_FLAG_MODULE) { - vtconsole_deinit_class_device(con_driver); - class_device_destroy(vtconsole_class, - MKDEV(0, con_driver->node)); + vtconsole_deinit_device(con_driver); + device_destroy(vtconsole_class, + MKDEV(0, con_driver->node)); con_driver->con = NULL; con_driver->desc = NULL; - con_driver->class_dev = NULL; + con_driver->dev = NULL; con_driver->node = 0; con_driver->flag = 0; con_driver->first = 0; @@ -3289,19 +3287,18 @@ static int __init vtconsole_class_init(void) for (i = 0; i < MAX_NR_CON_DRIVER; i++) { struct con_driver *con = ®istered_con_driver[i]; - if (con->con && !con->class_dev) { - con->class_dev = - class_device_create(vtconsole_class, NULL, - MKDEV(0, con->node), NULL, - "vtcon%i", con->node); + if (con->con && !con->dev) { + con->dev = device_create(vtconsole_class, NULL, + MKDEV(0, con->node), + "vtcon%i", con->node); - if (IS_ERR(con->class_dev)) { + if (IS_ERR(con->dev)) { printk(KERN_WARNING "Unable to create " - "class_device for %s; errno = %ld\n", - con->desc, PTR_ERR(con->class_dev)); - con->class_dev = NULL; + "device for %s; errno = %ld\n", + con->desc, PTR_ERR(con->dev)); + con->dev = NULL; } else { - vtconsole_init_class_device(con); + vtconsole_init_device(con); } } } -- cgit v1.2.3 From cd15422b9f39155e2d9ea56ae95c6f62aa5df42e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert vc code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/char/vc_screen.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index bd7a98c6ea7a..f442b574b44a 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -476,16 +476,16 @@ static struct class *vc_class; void vcs_make_sysfs(struct tty_struct *tty) { - class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), - NULL, "vcs%u", tty->index + 1); - class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), - NULL, "vcsa%u", tty->index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), + "vcs%u", tty->index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), + "vcsa%u", tty->index + 1); } void vcs_remove_sysfs(struct tty_struct *tty) { - class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); - class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); } int __init vcs_init(void) @@ -494,7 +494,7 @@ int __init vcs_init(void) panic("unable to get major %d for vcs device", VCS_MAJOR); vc_class = class_create(THIS_MODULE, "vc"); - class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); - class_device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs"); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa"); return 0; } -- cgit v1.2.3 From 94fbcded4ea0dc14cbfb222a5c68372f150d1476 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 27 Jul 2006 16:16:04 -0700 Subject: Driver core: change misc class_devices to be real devices This also ment that some of the misc drivers had to also be fixed up as they were assuming the device was a class_device. Signed-off-by: Greg Kroah-Hartman --- drivers/char/hw_random/core.c | 38 +++++++++++++++++++------------------- drivers/char/misc.c | 13 ++++--------- drivers/char/tpm/tpm.c | 2 +- drivers/input/serio/serio_raw.c | 2 +- include/linux/miscdevice.h | 5 ++--- 5 files changed, 27 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 154a81d328c1..ebace201bec6 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -162,7 +162,8 @@ static struct miscdevice rng_miscdev = { }; -static ssize_t hwrng_attr_current_store(struct class_device *class, +static ssize_t hwrng_attr_current_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t len) { int err; @@ -192,7 +193,8 @@ static ssize_t hwrng_attr_current_store(struct class_device *class, return err ? : len; } -static ssize_t hwrng_attr_current_show(struct class_device *class, +static ssize_t hwrng_attr_current_show(struct device *dev, + struct device_attribute *attr, char *buf) { int err; @@ -210,7 +212,8 @@ static ssize_t hwrng_attr_current_show(struct class_device *class, return ret; } -static ssize_t hwrng_attr_available_show(struct class_device *class, +static ssize_t hwrng_attr_available_show(struct device *dev, + struct device_attribute *attr, char *buf) { int err; @@ -234,20 +237,18 @@ static ssize_t hwrng_attr_available_show(struct class_device *class, return ret; } -static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, - hwrng_attr_current_show, - hwrng_attr_current_store); -static CLASS_DEVICE_ATTR(rng_available, S_IRUGO, - hwrng_attr_available_show, - NULL); +static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR, + hwrng_attr_current_show, + hwrng_attr_current_store); +static DEVICE_ATTR(rng_available, S_IRUGO, + hwrng_attr_available_show, + NULL); static void unregister_miscdev(void) { - class_device_remove_file(rng_miscdev.class, - &class_device_attr_rng_available); - class_device_remove_file(rng_miscdev.class, - &class_device_attr_rng_current); + device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available); + device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current); misc_deregister(&rng_miscdev); } @@ -258,20 +259,19 @@ static int register_miscdev(void) err = misc_register(&rng_miscdev); if (err) goto out; - err = class_device_create_file(rng_miscdev.class, - &class_device_attr_rng_current); + err = device_create_file(rng_miscdev.this_device, + &dev_attr_rng_current); if (err) goto err_misc_dereg; - err = class_device_create_file(rng_miscdev.class, - &class_device_attr_rng_available); + err = device_create_file(rng_miscdev.this_device, + &dev_attr_rng_available); if (err) goto err_remove_current; out: return err; err_remove_current: - class_device_remove_file(rng_miscdev.class, - &class_device_attr_rng_current); + device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current); err_misc_dereg: misc_deregister(&rng_miscdev); goto out; diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 62ebe09656e3..7a484fc7cb9e 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -169,11 +169,6 @@ fail: return err; } -/* - * TODO for 2.7: - * - add a struct kref to struct miscdevice and make all usages of - * them dynamic. - */ static struct class *misc_class; static const struct file_operations misc_fops = { @@ -228,10 +223,10 @@ int misc_register(struct miscdevice * misc) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); - misc->class = class_device_create(misc_class, NULL, dev, misc->dev, + misc->this_device = device_create(misc_class, misc->parent, dev, "%s", misc->name); - if (IS_ERR(misc->class)) { - err = PTR_ERR(misc->class); + if (IS_ERR(misc->this_device)) { + err = PTR_ERR(misc->this_device); goto out; } @@ -264,7 +259,7 @@ int misc_deregister(struct miscdevice * misc) down(&misc_sem); list_del(&misc->list); - class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); + device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); if (i < DYNAMIC_MINORS && i>0) { misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); } diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 6ad2d3bb945c..6e1329d404d2 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -1130,7 +1130,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vend scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num); chip->vendor.miscdev.name = devname; - chip->vendor.miscdev.dev = dev; + chip->vendor.miscdev.parent = dev; chip->dev = get_device(dev); if (misc_register(&chip->vendor.miscdev)) { diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index ba2a2035d648..7c8d0399ae82 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -297,7 +297,7 @@ static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) serio_raw->dev.minor = PSMOUSE_MINOR; serio_raw->dev.name = serio_raw->name; - serio_raw->dev.dev = &serio->dev; + serio_raw->dev.parent = &serio->dev; serio_raw->dev.fops = &serio_raw_fops; err = misc_register(&serio_raw->dev); diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index b03cfb91e228..326da7d500c7 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h @@ -31,15 +31,14 @@ #define HPET_MINOR 228 struct device; -struct class_device; struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; - struct device *dev; - struct class_device *class; + struct device *parent; + struct device *this_device; }; extern int misc_register(struct miscdevice * misc); -- cgit v1.2.3 From 01107d343076c34b9e1ce5d073292bd7f3097fda Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert tty core to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Also fixes up the isdn drivers that were putting something in the class device's directory. Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 19 ++++++++++--------- drivers/isdn/gigaset/common.c | 2 +- drivers/isdn/gigaset/gigaset.h | 2 +- drivers/isdn/gigaset/interface.c | 10 +++++----- drivers/isdn/gigaset/proc.c | 19 ++++++++++--------- include/linux/tty.h | 5 ++--- 6 files changed, 29 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index e90ea39c7c4b..50dc49205a23 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -3612,7 +3612,8 @@ static struct class *tty_class; * This field is optional, if there is no known struct device * for this tty device it can be set to NULL safely. * - * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error). + * Returns a pointer to the struct device for this tty device + * (or ERR_PTR(-EFOO) on error). * * This call is required to be made to register an individual tty device * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If @@ -3622,8 +3623,8 @@ static struct class *tty_class; * Locking: ?? */ -struct class_device *tty_register_device(struct tty_driver *driver, - unsigned index, struct device *device) +struct device *tty_register_device(struct tty_driver *driver, unsigned index, + struct device *device) { char name[64]; dev_t dev = MKDEV(driver->major, driver->minor_start) + index; @@ -3639,7 +3640,7 @@ struct class_device *tty_register_device(struct tty_driver *driver, else tty_line_name(driver, index, name); - return class_device_create(tty_class, NULL, dev, device, "%s", name); + return device_create(tty_class, device, dev, name); } /** @@ -3655,7 +3656,7 @@ struct class_device *tty_register_device(struct tty_driver *driver, void tty_unregister_device(struct tty_driver *driver, unsigned index) { - class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); + device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index); } EXPORT_SYMBOL(tty_register_device); @@ -3895,20 +3896,20 @@ static int __init tty_init(void) if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) panic("Couldn't register /dev/tty driver\n"); - class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); + device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty"); cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); - class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); + device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console"); #ifdef CONFIG_UNIX98_PTYS cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); - class_device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); + device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx"); #endif #ifdef CONFIG_VT @@ -3916,7 +3917,7 @@ static int __init tty_init(void) if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) panic("Couldn't register /dev/tty0 driver\n"); - class_device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); + device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0"); vty_init(); #endif diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c index 5800beeebb85..defd5743dba6 100644 --- a/drivers/isdn/gigaset/common.c +++ b/drivers/isdn/gigaset/common.c @@ -702,7 +702,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, cs->open_count = 0; cs->dev = NULL; cs->tty = NULL; - cs->class = NULL; + cs->tty_dev = NULL; cs->cidmode = cidmode != 0; //if(onechannel) { //FIXME diff --git a/drivers/isdn/gigaset/gigaset.h b/drivers/isdn/gigaset/gigaset.h index 884bd72c1bf4..06298cc52bf5 100644 --- a/drivers/isdn/gigaset/gigaset.h +++ b/drivers/isdn/gigaset/gigaset.h @@ -444,7 +444,7 @@ struct cardstate { struct gigaset_driver *driver; unsigned minor_index; struct device *dev; - struct class_device *class; + struct device *tty_dev; const struct gigaset_ops *ops; diff --git a/drivers/isdn/gigaset/interface.c b/drivers/isdn/gigaset/interface.c index 596f3aebe2f7..7edea015867e 100644 --- a/drivers/isdn/gigaset/interface.c +++ b/drivers/isdn/gigaset/interface.c @@ -625,13 +625,13 @@ void gigaset_if_init(struct cardstate *cs) return; tasklet_init(&cs->if_wake_tasklet, &if_wake, (unsigned long) cs); - cs->class = tty_register_device(drv->tty, cs->minor_index, NULL); + cs->tty_dev = tty_register_device(drv->tty, cs->minor_index, NULL); - if (!IS_ERR(cs->class)) - class_set_devdata(cs->class, cs); + if (!IS_ERR(cs->tty_dev)) + dev_set_drvdata(cs->tty_dev, cs); else { warn("could not register device to the tty subsystem"); - cs->class = NULL; + cs->tty_dev = NULL; } } @@ -645,7 +645,7 @@ void gigaset_if_free(struct cardstate *cs) tasklet_disable(&cs->if_wake_tasklet); tasklet_kill(&cs->if_wake_tasklet); - cs->class = NULL; + cs->tty_dev = NULL; tty_unregister_device(drv->tty, cs->minor_index); } diff --git a/drivers/isdn/gigaset/proc.c b/drivers/isdn/gigaset/proc.c index 9ad840e95dbe..e767afa55abf 100644 --- a/drivers/isdn/gigaset/proc.c +++ b/drivers/isdn/gigaset/proc.c @@ -16,11 +16,12 @@ #include "gigaset.h" #include -static ssize_t show_cidmode(struct class_device *class, char *buf) +static ssize_t show_cidmode(struct device *dev, + struct device_attribute *attr, char *buf) { int ret; unsigned long flags; - struct cardstate *cs = class_get_devdata(class); + struct cardstate *cs = dev_get_drvdata(dev); spin_lock_irqsave(&cs->lock, flags); ret = sprintf(buf, "%u\n", cs->cidmode); @@ -29,10 +30,10 @@ static ssize_t show_cidmode(struct class_device *class, char *buf) return ret; } -static ssize_t set_cidmode(struct class_device *class, +static ssize_t set_cidmode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct cardstate *cs = class_get_devdata(class); + struct cardstate *cs = dev_get_drvdata(dev); long int value; char *end; @@ -64,25 +65,25 @@ static ssize_t set_cidmode(struct class_device *class, return count; } -static CLASS_DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); +static DEVICE_ATTR(cidmode, S_IRUGO|S_IWUSR, show_cidmode, set_cidmode); /* free sysfs for device */ void gigaset_free_dev_sysfs(struct cardstate *cs) { - if (!cs->class) + if (!cs->tty_dev) return; gig_dbg(DEBUG_INIT, "removing sysfs entries"); - class_device_remove_file(cs->class, &class_device_attr_cidmode); + device_remove_file(cs->tty_dev, &dev_attr_cidmode); } /* initialize sysfs for device */ void gigaset_init_dev_sysfs(struct cardstate *cs) { - if (!cs->class) + if (!cs->tty_dev) return; gig_dbg(DEBUG_INIT, "setting up sysfs"); - if (class_device_create_file(cs->class, &class_device_attr_cidmode)) + if (device_create_file(cs->tty_dev, &dev_attr_cidmode)) dev_err(cs->dev, "could not create sysfs attribute\n"); } diff --git a/include/linux/tty.h b/include/linux/tty.h index 44091c0db0b4..65321f911c1e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -276,9 +276,8 @@ extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc); extern int tty_unregister_ldisc(int disc); extern int tty_register_driver(struct tty_driver *driver); extern int tty_unregister_driver(struct tty_driver *driver); -extern struct class_device *tty_register_device(struct tty_driver *driver, - unsigned index, - struct device *dev); +extern struct device *tty_register_device(struct tty_driver *driver, + unsigned index, struct device *dev); extern void tty_unregister_device(struct tty_driver *driver, unsigned index); extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, int buflen); -- cgit v1.2.3 From 38ca6c34d385f143027ff40dd271c61adcc9b23c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 7 Aug 2006 22:19:37 -0700 Subject: Driver core: convert raw device code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/char/raw.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 89b718e326e5..3b32313f6eb4 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -127,9 +127,9 @@ raw_ioctl(struct inode *inode, struct file *filp, static void bind_device(struct raw_config_request *rq) { - class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); - class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), - NULL, "raw%d", rq->raw_minor); + device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); + device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), + "raw%d", rq->raw_minor); } /* @@ -200,7 +200,7 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, if (rq.block_major == 0 && rq.block_minor == 0) { /* unbind */ rawdev->binding = NULL; - class_device_destroy(raw_class, + device_destroy(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor)); } else { rawdev->binding = bdget(dev); @@ -283,7 +283,7 @@ static int __init raw_init(void) ret = PTR_ERR(raw_class); goto error_region; } - class_device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); + device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl"); return 0; @@ -295,7 +295,7 @@ error: static void __exit raw_exit(void) { - class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); + device_destroy(raw_class, MKDEV(RAW_MAJOR, 0)); class_destroy(raw_class); cdev_del(&raw_cdev); unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); -- cgit v1.2.3 From ac11d0601bbe73c92e31b393eeb1225593788d4c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 3 Jul 2006 13:46:24 -0700 Subject: I2C: convert i2c-dev to use struct device instead of struct class_device As class_device is going away eventually... Cc: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/i2c/i2c-dev.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 3f869033ed70..94a4e9a3013c 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -42,7 +42,7 @@ static struct i2c_driver i2cdev_driver; struct i2c_dev { struct list_head list; struct i2c_adapter *adap; - struct class_device *class_dev; + struct device *dev; }; #define I2C_MINORS 256 @@ -92,15 +92,16 @@ static void return_i2c_dev(struct i2c_dev *i2c_dev) spin_unlock(&i2c_dev_list_lock); } -static ssize_t show_adapter_name(struct class_device *class_dev, char *buf) +static ssize_t show_adapter_name(struct device *dev, + struct device_attribute *attr, char *buf) { - struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(class_dev->devt)); + struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt)); if (!i2c_dev) return -ENODEV; return sprintf(buf, "%s\n", i2c_dev->adap->name); } -static CLASS_DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); +static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); static ssize_t i2cdev_read (struct file *file, char __user *buf, size_t count, loff_t *offset) @@ -413,15 +414,14 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) return PTR_ERR(i2c_dev); /* register this i2c device with the driver core */ - i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL, - MKDEV(I2C_MAJOR, adap->nr), - &adap->dev, "i2c-%d", - adap->nr); - if (!i2c_dev->class_dev) { + i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, + MKDEV(I2C_MAJOR, adap->nr), + "i2c-%d", adap->nr); + if (!i2c_dev->dev) { res = -ENODEV; goto error; } - res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name); + res = device_create_file(i2c_dev->dev, &dev_attr_name); if (res) goto error_destroy; @@ -429,7 +429,7 @@ static int i2cdev_attach_adapter(struct i2c_adapter *adap) adap->name, adap->nr); return 0; error_destroy: - class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); + device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); error: return_i2c_dev(i2c_dev); kfree(i2c_dev); @@ -444,9 +444,9 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap) if (!i2c_dev) /* attach_adapter must have failed */ return 0; - class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name); + device_remove_file(i2c_dev->dev, &dev_attr_name); return_i2c_dev(i2c_dev); - class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); + device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); kfree(i2c_dev); pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); -- cgit v1.2.3 From 9a6a2a5e0b57d25c1bf6eb9b8c958940e156b059 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Sep 2006 17:00:10 +0200 Subject: Driver core: convert PPP code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/net/ppp_generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index f5802e7b08e9..c6de566188e4 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -860,7 +860,7 @@ static int __init ppp_init(void) err = PTR_ERR(ppp_class); goto out_chrdev; } - class_device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL, "ppp"); + device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp"); } out: @@ -2675,7 +2675,7 @@ static void __exit ppp_cleanup(void) cardmap_destroy(&all_ppp_units); if (unregister_chrdev(PPP_MAJOR, "ppp") != 0) printk(KERN_ERR "PPP: failed to unregister PPP device\n"); - class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); + device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); class_destroy(ppp_class); } -- cgit v1.2.3 From 04880edae5e1027d61241beb5ac37b520755f2ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Sep 2006 17:00:10 +0200 Subject: Driver core: convert ppdev code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/char/ppdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index efc485edad1c..c1e3dd837fc8 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -752,13 +752,13 @@ static const struct file_operations pp_fops = { static void pp_attach(struct parport *port) { - class_device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number), - NULL, "parport%d", port->number); + device_create(ppdev_class, NULL, MKDEV(PP_MAJOR, port->number), + "parport%d", port->number); } static void pp_detach(struct parport *port) { - class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); + device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); } static struct parport_driver pp_driver = { -- cgit v1.2.3 From fcaf71fd51f9cfc504455d3e19ec242e4b2073ed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 12 Sep 2006 17:00:10 +0200 Subject: Driver core: convert mmc code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/mmc/mmc_queue.c | 4 ++-- drivers/mmc/mmc_sysfs.c | 20 ++++++++++---------- drivers/mmc/wbsd.c | 6 +++--- include/linux/mmc/host.h | 8 ++++---- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/mmc_queue.c b/drivers/mmc/mmc_queue.c index 4ccdd82b680f..61a1de85cb23 100644 --- a/drivers/mmc/mmc_queue.c +++ b/drivers/mmc/mmc_queue.c @@ -130,8 +130,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock u64 limit = BLK_BOUNCE_HIGH; int ret; - if (host->dev->dma_mask && *host->dev->dma_mask) - limit = *host->dev->dma_mask; + if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) + limit = *mmc_dev(host)->dma_mask; mq->card = card; mq->queue = blk_init_queue(mmc_request, lock); diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index 10cc9734eaa0..ac5329636045 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c @@ -199,7 +199,7 @@ void mmc_init_card(struct mmc_card *card, struct mmc_host *host) memset(card, 0, sizeof(struct mmc_card)); card->host = host; device_initialize(&card->dev); - card->dev.parent = card->host->dev; + card->dev.parent = mmc_dev(host); card->dev.bus = &mmc_bus_type; card->dev.release = mmc_release_card; } @@ -242,7 +242,7 @@ void mmc_remove_card(struct mmc_card *card) } -static void mmc_host_classdev_release(struct class_device *dev) +static void mmc_host_classdev_release(struct device *dev) { struct mmc_host *host = cls_dev_to_mmc_host(dev); kfree(host); @@ -250,7 +250,7 @@ static void mmc_host_classdev_release(struct class_device *dev) static struct class mmc_host_class = { .name = "mmc_host", - .release = mmc_host_classdev_release, + .dev_release = mmc_host_classdev_release, }; static DEFINE_IDR(mmc_host_idr); @@ -267,10 +267,10 @@ struct mmc_host *mmc_alloc_host_sysfs(int extra, struct device *dev) if (host) { memset(host, 0, sizeof(struct mmc_host) + extra); - host->dev = dev; - host->class_dev.dev = host->dev; + host->parent = dev; + host->class_dev.parent = dev; host->class_dev.class = &mmc_host_class; - class_device_initialize(&host->class_dev); + device_initialize(&host->class_dev); } return host; @@ -292,10 +292,10 @@ int mmc_add_host_sysfs(struct mmc_host *host) if (err) return err; - snprintf(host->class_dev.class_id, BUS_ID_SIZE, + snprintf(host->class_dev.bus_id, BUS_ID_SIZE, "mmc%d", host->index); - return class_device_add(&host->class_dev); + return device_add(&host->class_dev); } /* @@ -303,7 +303,7 @@ int mmc_add_host_sysfs(struct mmc_host *host) */ void mmc_remove_host_sysfs(struct mmc_host *host) { - class_device_del(&host->class_dev); + device_del(&host->class_dev); spin_lock(&mmc_host_lock); idr_remove(&mmc_host_idr, host->index); @@ -315,7 +315,7 @@ void mmc_remove_host_sysfs(struct mmc_host *host) */ void mmc_free_host_sysfs(struct mmc_host *host) { - class_device_put(&host->class_dev); + put_device(&host->class_dev); } static struct workqueue_struct *workqueue; diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index ced309b37a8f..682e62b0b09d 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1488,7 +1488,7 @@ static void __devinit wbsd_request_dma(struct wbsd_host *host, int dma) /* * Translate the address to a physical address. */ - host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer, + host->dma_addr = dma_map_single(mmc_dev(host->mmc), host->dma_buffer, WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); /* @@ -1512,7 +1512,7 @@ kfree: */ BUG_ON(1); - dma_unmap_single(host->mmc->dev, host->dma_addr, + dma_unmap_single(mmc_dev(host->mmc), host->dma_addr, WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); host->dma_addr = (dma_addr_t)NULL; @@ -1530,7 +1530,7 @@ err: static void __devexit wbsd_release_dma(struct wbsd_host *host) { if (host->dma_addr) { - dma_unmap_single(host->mmc->dev, host->dma_addr, + dma_unmap_single(mmc_dev(host->mmc), host->dma_addr, WBSD_DMA_SIZE, DMA_BIDIRECTIONAL); } kfree(host->dma_buffer); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 587264a58d56..528e7d3fecb1 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -74,8 +74,8 @@ struct mmc_card; struct device; struct mmc_host { - struct device *dev; - struct class_device class_dev; + struct device *parent; + struct device class_dev; int index; const struct mmc_host_ops *ops; unsigned int f_min; @@ -125,8 +125,8 @@ static inline void *mmc_priv(struct mmc_host *host) return (void *)host->private; } -#define mmc_dev(x) ((x)->dev) -#define mmc_hostname(x) ((x)->class_dev.class_id) +#define mmc_dev(x) ((x)->parent) +#define mmc_hostname(x) ((x)->class_dev.bus_id) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_resume_host(struct mmc_host *); -- cgit v1.2.3 From e55c8790d40fdbc6887b4e3e52afefe4b03f1311 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Sep 2006 07:30:59 -0700 Subject: Driver core: convert firmware code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/base/firmware_class.c | 119 ++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 14615694ae9a..4bad2870c485 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -21,6 +21,8 @@ #include #include "base.h" +#define to_dev(obj) container_of(obj, struct device, kobj) + MODULE_AUTHOR("Manuel Estrada Sainz "); MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_LICENSE("GPL"); @@ -86,12 +88,12 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count) static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); -static void fw_class_dev_release(struct class_device *class_dev); +static void fw_dev_release(struct device *dev); -static int firmware_class_uevent(struct class_device *class_dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int firmware_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); int i = 0, len = 0; if (!test_bit(FW_STATUS_READY, &fw_priv->status)) @@ -110,21 +112,21 @@ static int firmware_class_uevent(struct class_device *class_dev, char **envp, static struct class firmware_class = { .name = "firmware", - .uevent = firmware_class_uevent, - .release = fw_class_dev_release, + .dev_uevent = firmware_uevent, + .dev_release = fw_dev_release, }; -static ssize_t -firmware_loading_show(struct class_device *class_dev, char *buf) +static ssize_t firmware_loading_show(struct device *dev, + struct device_attribute *attr, char *buf) { - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status); return sprintf(buf, "%d\n", loading); } /** * firmware_loading_store - set value in the 'loading' control file - * @class_dev: class_device pointer + * @dev: device pointer * @buf: buffer to scan for loading control value * @count: number of bytes in @buf * @@ -134,11 +136,11 @@ firmware_loading_show(struct class_device *class_dev, char *buf) * 0: Conclude the load and hand the data to the driver code. * -1: Conclude the load with an error and discard any written data. **/ -static ssize_t -firmware_loading_store(struct class_device *class_dev, - const char *buf, size_t count) +static ssize_t firmware_loading_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); int loading = simple_strtol(buf, NULL, 10); switch (loading) { @@ -174,15 +176,14 @@ firmware_loading_store(struct class_device *class_dev, return count; } -static CLASS_DEVICE_ATTR(loading, 0644, - firmware_loading_show, firmware_loading_store); +static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static ssize_t firmware_data_read(struct kobject *kobj, char *buffer, loff_t offset, size_t count) { - struct class_device *class_dev = to_class_dev(kobj); - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct device *dev = to_dev(kobj); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware *fw; ssize_t ret_count = count; @@ -234,7 +235,7 @@ fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) /** * firmware_data_write - write method for firmware - * @kobj: kobject for the class_device + * @kobj: kobject for the device * @buffer: buffer being written * @offset: buffer offset for write in total data store area * @count: buffer size @@ -246,8 +247,8 @@ static ssize_t firmware_data_write(struct kobject *kobj, char *buffer, loff_t offset, size_t count) { - struct class_device *class_dev = to_class_dev(kobj); - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct device *dev = to_dev(kobj); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); struct firmware *fw; ssize_t retval; @@ -280,13 +281,12 @@ static struct bin_attribute firmware_attr_data_tmpl = { .write = firmware_data_write, }; -static void -fw_class_dev_release(struct class_device *class_dev) +static void fw_dev_release(struct device *dev) { - struct firmware_priv *fw_priv = class_get_devdata(class_dev); + struct firmware_priv *fw_priv = dev_get_drvdata(dev); kfree(fw_priv); - kfree(class_dev); + kfree(dev); module_put(THIS_MODULE); } @@ -298,26 +298,23 @@ firmware_class_timeout(u_long data) fw_load_abort(fw_priv); } -static inline void -fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) +static inline void fw_setup_device_id(struct device *f_dev, struct device *dev) { /* XXX warning we should watch out for name collisions */ - strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); + strlcpy(f_dev->bus_id, dev->bus_id, BUS_ID_SIZE); } -static int -fw_register_class_device(struct class_device **class_dev_p, - const char *fw_name, struct device *device) +static int fw_register_device(struct device **dev_p, const char *fw_name, + struct device *device) { int retval; struct firmware_priv *fw_priv = kzalloc(sizeof(*fw_priv), GFP_KERNEL); - struct class_device *class_dev = kzalloc(sizeof(*class_dev), - GFP_KERNEL); + struct device *f_dev = kzalloc(sizeof(*f_dev), GFP_KERNEL); - *class_dev_p = NULL; + *dev_p = NULL; - if (!fw_priv || !class_dev) { + if (!fw_priv || !f_dev) { printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__); retval = -ENOMEM; goto error_kfree; @@ -331,55 +328,54 @@ fw_register_class_device(struct class_device **class_dev_p, fw_priv->timeout.data = (u_long) fw_priv; init_timer(&fw_priv->timeout); - fw_setup_class_device_id(class_dev, device); - class_dev->dev = device; - class_dev->class = &firmware_class; - class_set_devdata(class_dev, fw_priv); - retval = class_device_register(class_dev); + fw_setup_device_id(f_dev, device); + f_dev->parent = device; + f_dev->class = &firmware_class; + dev_set_drvdata(f_dev, fw_priv); + retval = device_register(f_dev); if (retval) { - printk(KERN_ERR "%s: class_device_register failed\n", + printk(KERN_ERR "%s: device_register failed\n", __FUNCTION__); goto error_kfree; } - *class_dev_p = class_dev; + *dev_p = f_dev; return 0; error_kfree: kfree(fw_priv); - kfree(class_dev); + kfree(f_dev); return retval; } -static int -fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, - const char *fw_name, struct device *device, int uevent) +static int fw_setup_device(struct firmware *fw, struct device **dev_p, + const char *fw_name, struct device *device, + int uevent) { - struct class_device *class_dev; + struct device *f_dev; struct firmware_priv *fw_priv; int retval; - *class_dev_p = NULL; - retval = fw_register_class_device(&class_dev, fw_name, device); + *dev_p = NULL; + retval = fw_register_device(&f_dev, fw_name, device); if (retval) goto out; /* Need to pin this module until class device is destroyed */ __module_get(THIS_MODULE); - fw_priv = class_get_devdata(class_dev); + fw_priv = dev_get_drvdata(f_dev); fw_priv->fw = fw; - retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); + retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); if (retval) { printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", __FUNCTION__); goto error_unreg; } - retval = class_device_create_file(class_dev, - &class_device_attr_loading); + retval = device_create_file(f_dev, &dev_attr_loading); if (retval) { - printk(KERN_ERR "%s: class_device_create_file failed\n", + printk(KERN_ERR "%s: device_create_file failed\n", __FUNCTION__); goto error_unreg; } @@ -388,11 +384,11 @@ fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p, set_bit(FW_STATUS_READY, &fw_priv->status); else set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status); - *class_dev_p = class_dev; + *dev_p = f_dev; goto out; error_unreg: - class_device_unregister(class_dev); + device_unregister(f_dev); out: return retval; } @@ -401,7 +397,7 @@ static int _request_firmware(const struct firmware **firmware_p, const char *name, struct device *device, int uevent) { - struct class_device *class_dev; + struct device *f_dev; struct firmware_priv *fw_priv; struct firmware *firmware; int retval; @@ -417,12 +413,11 @@ _request_firmware(const struct firmware **firmware_p, const char *name, goto out; } - retval = fw_setup_class_device(firmware, &class_dev, name, device, - uevent); + retval = fw_setup_device(firmware, &f_dev, name, device, uevent); if (retval) goto error_kfree_fw; - fw_priv = class_get_devdata(class_dev); + fw_priv = dev_get_drvdata(f_dev); if (uevent) { if (loading_timeout > 0) { @@ -430,7 +425,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, add_timer(&fw_priv->timeout); } - kobject_uevent(&class_dev->kobj, KOBJ_ADD); + kobject_uevent(&f_dev->kobj, KOBJ_ADD); wait_for_completion(&fw_priv->completion); set_bit(FW_STATUS_DONE, &fw_priv->status); del_timer_sync(&fw_priv->timeout); @@ -445,7 +440,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name, } fw_priv->fw = NULL; mutex_unlock(&fw_lock); - class_device_unregister(class_dev); + device_unregister(f_dev); goto out; error_kfree_fw: -- cgit v1.2.3 From 78cde0887930f5d11a56fc51b013f2672fba0e6f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Sep 2006 07:30:59 -0700 Subject: Driver core: convert fb code to use struct device Converts from using struct "class_device" to "struct device" making everything show up properly in /sys/devices/ with symlinks from the /sys/class directory. Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbmem.c | 16 ++--- drivers/video/fbsysfs.c | 163 +++++++++++++++++++++++++++--------------------- include/linux/fb.h | 8 +-- 3 files changed, 103 insertions(+), 84 deletions(-) (limited to 'drivers') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 93ffcdd95f50..e973a87fbb01 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1296,14 +1296,14 @@ register_framebuffer(struct fb_info *fb_info) break; fb_info->node = i; - fb_info->class_device = class_device_create(fb_class, NULL, MKDEV(FB_MAJOR, i), - fb_info->device, "fb%d", i); - if (IS_ERR(fb_info->class_device)) { + fb_info->dev = device_create(fb_class, fb_info->device, + MKDEV(FB_MAJOR, i), "fb%d", i); + if (IS_ERR(fb_info->dev)) { /* Not fatal */ - printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device)); - fb_info->class_device = NULL; + printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev)); + fb_info->dev = NULL; } else - fb_init_class_device(fb_info); + fb_init_device(fb_info); if (fb_info->pixmap.addr == NULL) { fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL); @@ -1356,8 +1356,8 @@ unregister_framebuffer(struct fb_info *fb_info) fb_destroy_modelist(&fb_info->modelist); registered_fb[i]=NULL; num_registered_fb--; - fb_cleanup_class_device(fb_info); - class_device_destroy(fb_class, MKDEV(FB_MAJOR, i)); + fb_cleanup_device(fb_info); + device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); return 0; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index d3a50417ed9a..323bdf6fc7d5 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -73,7 +73,7 @@ EXPORT_SYMBOL(framebuffer_alloc); * * @info: frame buffer info structure * - * Drop the reference count of the class_device embedded in the + * Drop the reference count of the device embedded in the * framebuffer info structure. * */ @@ -120,10 +120,10 @@ static int mode_string(char *buf, unsigned int offset, m, mode->xres, mode->yres, v, mode->refresh); } -static ssize_t store_mode(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_mode(struct device *device, struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); char mstr[100]; struct fb_var_screeninfo var; struct fb_modelist *modelist; @@ -151,9 +151,10 @@ static ssize_t store_mode(struct class_device *class_device, const char * buf, return -EINVAL; } -static ssize_t show_mode(struct class_device *class_device, char *buf) +static ssize_t show_mode(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); if (!fb_info->mode) return 0; @@ -161,10 +162,11 @@ static ssize_t show_mode(struct class_device *class_device, char *buf) return mode_string(buf, 0, fb_info->mode); } -static ssize_t store_modes(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_modes(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); LIST_HEAD(old_list); int i = count / sizeof(struct fb_videomode); @@ -186,9 +188,10 @@ static ssize_t store_modes(struct class_device *class_device, const char * buf, return 0; } -static ssize_t show_modes(struct class_device *class_device, char *buf) +static ssize_t show_modes(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); unsigned int i; struct list_head *pos; struct fb_modelist *modelist; @@ -203,10 +206,10 @@ static ssize_t show_modes(struct class_device *class_device, char *buf) return i; } -static ssize_t store_bpp(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_bpp(struct device *device, struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char ** last = NULL; int err; @@ -218,16 +221,18 @@ static ssize_t store_bpp(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_bpp(struct class_device *class_device, char *buf) +static ssize_t show_bpp(struct device *device, struct device_attribute *attr, + char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } -static ssize_t store_rotate(struct class_device *class_device, const char *buf, - size_t count) +static ssize_t store_rotate(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char **last = NULL; int err; @@ -242,17 +247,19 @@ static ssize_t store_rotate(struct class_device *class_device, const char *buf, } -static ssize_t show_rotate(struct class_device *class_device, char *buf) +static ssize_t show_rotate(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); } -static ssize_t store_virtual(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_virtual(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -269,23 +276,26 @@ static ssize_t store_virtual(struct class_device *class_device, return count; } -static ssize_t show_virtual(struct class_device *class_device, char *buf) +static ssize_t show_virtual(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual, fb_info->var.yres_virtual); } -static ssize_t show_stride(struct class_device *class_device, char *buf) +static ssize_t show_stride(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->fix.line_length); } -static ssize_t store_blank(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_blank(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); char *last = NULL; int err; @@ -299,42 +309,48 @@ static ssize_t store_blank(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_blank(struct class_device *class_device, char *buf) +static ssize_t show_blank(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_console(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_console(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t show_console(struct class_device *class_device, char *buf) +static ssize_t show_console(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_cursor(struct class_device *class_device, - const char * buf, size_t count) +static ssize_t store_cursor(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t show_cursor(struct class_device *class_device, char *buf) +static ssize_t show_cursor(struct device *device, + struct device_attribute *attr, char *buf) { -// struct fb_info *fb_info = class_get_devdata(class_device); +// struct fb_info *fb_info = dev_get_drvdata(device); return 0; } -static ssize_t store_pan(struct class_device *class_device, const char * buf, - size_t count) +static ssize_t store_pan(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); struct fb_var_screeninfo var; char *last = NULL; int err; @@ -355,24 +371,27 @@ static ssize_t store_pan(struct class_device *class_device, const char * buf, return count; } -static ssize_t show_pan(struct class_device *class_device, char *buf) +static ssize_t show_pan(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset, fb_info->var.xoffset); } -static ssize_t show_name(struct class_device *class_device, char *buf) +static ssize_t show_name(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%s\n", fb_info->fix.id); } -static ssize_t store_fbstate(struct class_device *class_device, - const char *buf, size_t count) +static ssize_t store_fbstate(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); u32 state; char *last = NULL; @@ -385,17 +404,19 @@ static ssize_t store_fbstate(struct class_device *class_device, return count; } -static ssize_t show_fbstate(struct class_device *class_device, char *buf) +static ssize_t show_fbstate(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); } #ifdef CONFIG_FB_BACKLIGHT -static ssize_t store_bl_curve(struct class_device *class_device, - const char *buf, size_t count) +static ssize_t store_bl_curve(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); u8 tmp_curve[FB_BACKLIGHT_LEVELS]; unsigned int i; @@ -432,9 +453,10 @@ static ssize_t store_bl_curve(struct class_device *class_device, return count; } -static ssize_t show_bl_curve(struct class_device *class_device, char *buf) +static ssize_t show_bl_curve(struct device *device, + struct device_attribute *attr, char *buf) { - struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_info *fb_info = dev_get_drvdata(device); ssize_t len = 0; unsigned int i; @@ -465,7 +487,7 @@ static ssize_t show_bl_curve(struct class_device *class_device, char *buf) /* When cmap is added back in it should be a binary attribute * not a text one. Consideration should also be given to converting * fbdev to use configfs instead of sysfs */ -static struct class_device_attribute class_device_attrs[] = { +static struct device_attribute device_attrs[] = { __ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp), __ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank), __ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console), @@ -483,17 +505,16 @@ static struct class_device_attribute class_device_attrs[] = { #endif }; -int fb_init_class_device(struct fb_info *fb_info) +int fb_init_device(struct fb_info *fb_info) { int i, error = 0; - class_set_devdata(fb_info->class_device, fb_info); + dev_set_drvdata(fb_info->dev, fb_info); fb_info->class_flag |= FB_SYSFS_FLAG_ATTR; - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) { - error = class_device_create_file(fb_info->class_device, - &class_device_attrs[i]); + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) { + error = device_create_file(fb_info->dev, &device_attrs[i]); if (error) break; @@ -501,22 +522,20 @@ int fb_init_class_device(struct fb_info *fb_info) if (error) { while (--i >= 0) - class_device_remove_file(fb_info->class_device, - &class_device_attrs[i]); + device_remove_file(fb_info->dev, &device_attrs[i]); fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; } return 0; } -void fb_cleanup_class_device(struct fb_info *fb_info) +void fb_cleanup_device(struct fb_info *fb_info) { unsigned int i; if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) { - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(fb_info->class_device, - &class_device_attrs[i]); + for (i = 0; i < ARRAY_SIZE(device_attrs); i++) + device_remove_file(fb_info->dev, &device_attrs[i]); fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; } diff --git a/include/linux/fb.h b/include/linux/fb.h index 3e69241e6a81..fa23e0671bb3 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -774,8 +774,8 @@ struct fb_info { #endif struct fb_ops *fbops; - struct device *device; - struct class_device *class_device; /* sysfs per device attrs */ + struct device *device; /* This is the parent */ + struct device *dev; /* This is this fb device */ int class_flag; /* private sysfs flags */ #ifdef CONFIG_FB_TILEBLITTING struct fb_tile_ops *tileops; /* Tile Blitting */ @@ -910,8 +910,8 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, /* drivers/video/fbsysfs.c */ extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev); extern void framebuffer_release(struct fb_info *info); -extern int fb_init_class_device(struct fb_info *fb_info); -extern void fb_cleanup_class_device(struct fb_info *head); +extern int fb_init_device(struct fb_info *fb_info); +extern void fb_cleanup_device(struct fb_info *head); extern void fb_bl_default_curve(struct fb_info *fb_info, u8 off, u8 min, u8 max); /* drivers/video/fbmon.c */ -- cgit v1.2.3 From ebf644c4623bc3eb57683199cd2b9080028b0f6f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 25 Jul 2006 17:13:31 -0700 Subject: Driver core: change mem class_devices to be real devices Signed-off-by: Greg Kroah-Hartman --- drivers/char/mem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 55473371b7c6..e67eef4867ba 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -980,10 +980,10 @@ static int __init chr_dev_init(void) mem_class = class_create(THIS_MODULE, "mem"); for (i = 0; i < ARRAY_SIZE(devlist); i++) - class_device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), - NULL, devlist[i].name); - + device_create(mem_class, NULL, + MKDEV(MEM_MAJOR, devlist[i].minor), + devlist[i].name); + return 0; } -- cgit v1.2.3 From 465ae641e4a3e5028aa9c85d3843259aa28a22ce Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 11 Nov 2006 17:18:42 +1100 Subject: ACPI: Change ACPI to use dev_archdata instead of firmware_data Change ACPI to use dev_archdata instead of firmware_data This patch changes ACPI to use the new dev_archdata on i386, x86_64 and ia64 (is there any other arch using ACPI ?) to store it's acpi_handle. It also removes the firmware_data field from struct device as this was the only user. Only build-tested on x86 Signed-off-by: Benjamin Herrenschmidt Cc: Len Brown Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/glue.c | 20 +++++++++++--------- include/acpi/acpi_bus.h | 2 +- include/asm-i386/device.h | 10 +++++++++- include/asm-ia64/device.h | 10 +++++++++- include/asm-x86_64/device.h | 10 +++++++++- include/linux/device.h | 2 -- 6 files changed, 39 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 10f160dc75b1..a2f46d587d55 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c @@ -267,9 +267,9 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) { acpi_status status; - if (dev->firmware_data) { + if (dev->archdata.acpi_handle) { printk(KERN_WARNING PREFIX - "Drivers changed 'firmware_data' for %s\n", dev->bus_id); + "Drivers changed 'acpi_handle' for %s\n", dev->bus_id); return -EINVAL; } get_device(dev); @@ -278,25 +278,26 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle) put_device(dev); return -EINVAL; } - dev->firmware_data = handle; + dev->archdata.acpi_handle = handle; return 0; } static int acpi_unbind_one(struct device *dev) { - if (!dev->firmware_data) + if (!dev->archdata.acpi_handle) return 0; - if (dev == acpi_get_physical_device(dev->firmware_data)) { + if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { /* acpi_get_physical_device increase refcnt by one */ put_device(dev); - acpi_detach_data(dev->firmware_data, acpi_glue_data_handler); - dev->firmware_data = NULL; + acpi_detach_data(dev->archdata.acpi_handle, + acpi_glue_data_handler); + dev->archdata.acpi_handle = NULL; /* acpi_bind_one increase refcnt by one */ put_device(dev); } else { printk(KERN_ERR PREFIX - "Oops, 'firmware_data' corrupt for %s\n", dev->bus_id); + "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id); } return 0; } @@ -328,7 +329,8 @@ static int acpi_platform_notify(struct device *dev) if (!ret) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - acpi_get_name(dev->firmware_data, ACPI_FULL_PATHNAME, &buffer); + acpi_get_name(dev->archdata.acpi_handle, + ACPI_FULL_PATHNAME, &buffer); DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer); kfree(buffer.pointer); } else diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index f338e40bd544..fdd10953b2b6 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -357,7 +357,7 @@ struct device *acpi_get_physical_device(acpi_handle); /* helper */ acpi_handle acpi_get_child(acpi_handle, acpi_integer); acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); -#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->firmware_data)) +#define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle)) #endif /* CONFIG_ACPI */ diff --git a/include/asm-i386/device.h b/include/asm-i386/device.h index d8f9872b0e2d..849604c70e6b 100644 --- a/include/asm-i386/device.h +++ b/include/asm-i386/device.h @@ -3,5 +3,13 @@ * * This file is released under the GPLv2 */ -#include +#ifndef _ASM_I386_DEVICE_H +#define _ASM_I386_DEVICE_H +struct dev_archdata { +#ifdef CONFIG_ACPI + void *acpi_handle; +#endif +}; + +#endif /* _ASM_I386_DEVICE_H */ diff --git a/include/asm-ia64/device.h b/include/asm-ia64/device.h index d8f9872b0e2d..3db6daf7f251 100644 --- a/include/asm-ia64/device.h +++ b/include/asm-ia64/device.h @@ -3,5 +3,13 @@ * * This file is released under the GPLv2 */ -#include +#ifndef _ASM_IA64_DEVICE_H +#define _ASM_IA64_DEVICE_H +struct dev_archdata { +#ifdef CONFIG_ACPI + void *acpi_handle; +#endif +}; + +#endif /* _ASM_IA64_DEVICE_H */ diff --git a/include/asm-x86_64/device.h b/include/asm-x86_64/device.h index d8f9872b0e2d..3afa03f33a36 100644 --- a/include/asm-x86_64/device.h +++ b/include/asm-x86_64/device.h @@ -3,5 +3,13 @@ * * This file is released under the GPLv2 */ -#include +#ifndef _ASM_X86_64_DEVICE_H +#define _ASM_X86_64_DEVICE_H +struct dev_archdata { +#ifdef CONFIG_ACPI + void *acpi_handle; +#endif +}; + +#endif /* _ASM_X86_64_DEVICE_H */ diff --git a/include/linux/device.h b/include/linux/device.h index 5b54d756cd54..2d9dc358c027 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -369,8 +369,6 @@ struct device { void *driver_data; /* data private to the driver */ void *platform_data; /* Platform specific data, device core doesn't touch it */ - void *firmware_data; /* Firmware specific data (e.g. ACPI, - BIOS data),reserved for device core*/ struct dev_pm_info power; u64 *dma_mask; /* dma mask (if dma'able device) */ -- cgit v1.2.3 From 289535334646796fe41f199718e4a731f7411a92 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 8 Nov 2006 19:46:14 -0800 Subject: Driver core: Call platform_notify_remove later Move the call to platform_notify_remove() to after the call to bus_remove_device(), where it belongs. It's bogus to notify the platform of removal while drivers are still attached to the device and possibly still operating since the platform might use this callback to tear down some resources used by the driver (ACPI bits, iommu table, ...) Signed-off-by: Benjamin Herrenschmidt Cc: "Brown, Len" Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index f544adc5a5e2..5d11bbdfbd2f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -682,6 +682,7 @@ void device_del(struct device * dev) device_remove_file(dev, &dev->uevent_attr); device_remove_groups(dev); device_remove_attrs(dev); + bus_remove_device(dev); /* Notify the platform of the removal, in case they * need to do anything... @@ -691,7 +692,6 @@ void device_del(struct device * dev) if (dev->bus) blocking_notifier_call_chain(&dev->bus->bus_notifier, BUS_NOTIFY_DEL_DEVICE, dev); - bus_remove_device(dev); device_pm_remove(dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); kobject_del(&dev->kobj); -- cgit v1.2.3 From 06a4bcae1ff2cd5f6f42bd74add85ec785a26343 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 8 Nov 2006 19:46:09 -0800 Subject: cpu topology: consider sysfs_create_group return value Take return value of sysfs_create_group() into account. That function got called in case of CPU_ONLINE notification. Since callbacks are not allowed to fail on CPU_ONLINE notification do the sysfs group creation on CPU_UP_PREPARE notification. Also remember if creation succeeded in a bitmask. So it's possible to know whether it's legal to call sysfs_remove_group or not. In addition some other minor stuff: - since CPU_UP_PREPARE might fail add CPU_UP_CANCELED handling as well. - use hotcpu_notifier instead of register_hotcpu_notifier. - #ifdef code that isn't needed in the !CONFIG_HOTPLUG_CPU case. Signed-off-by: Heiko Carstens Acked-by: Cornelia Huck Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/topology.c | 55 ++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 28dccb730af9..3d12b85b0962 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -94,54 +94,63 @@ static struct attribute_group topology_attr_group = { .name = "topology" }; +static cpumask_t topology_dev_map = CPU_MASK_NONE; + /* Add/Remove cpu_topology interface for CPU device */ -static int __cpuinit topology_add_dev(struct sys_device * sys_dev) +static int __cpuinit topology_add_dev(unsigned int cpu) { - return sysfs_create_group(&sys_dev->kobj, &topology_attr_group); + int rc; + struct sys_device *sys_dev = get_cpu_sysdev(cpu); + + rc = sysfs_create_group(&sys_dev->kobj, &topology_attr_group); + if (!rc) + cpu_set(cpu, topology_dev_map); + return rc; } -static int __cpuinit topology_remove_dev(struct sys_device * sys_dev) +#ifdef CONFIG_HOTPLUG_CPU +static void __cpuinit topology_remove_dev(unsigned int cpu) { + struct sys_device *sys_dev = get_cpu_sysdev(cpu); + + if (!cpu_isset(cpu, topology_dev_map)) + return; + cpu_clear(cpu, topology_dev_map); sysfs_remove_group(&sys_dev->kobj, &topology_attr_group); - return 0; } static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) + unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; - struct sys_device *sys_dev; + int rc = 0; - sys_dev = get_cpu_sysdev(cpu); switch (action) { - case CPU_ONLINE: - topology_add_dev(sys_dev); + case CPU_UP_PREPARE: + rc = topology_add_dev(cpu); break; + case CPU_UP_CANCELED: case CPU_DEAD: - topology_remove_dev(sys_dev); + topology_remove_dev(cpu); break; } - return NOTIFY_OK; + return rc ? NOTIFY_BAD : NOTIFY_OK; } - -static struct notifier_block __cpuinitdata topology_cpu_notifier = -{ - .notifier_call = topology_cpu_callback, -}; +#endif static int __cpuinit topology_sysfs_init(void) { - int i; + int cpu; + int rc; - for_each_online_cpu(i) { - topology_cpu_callback(&topology_cpu_notifier, CPU_ONLINE, - (void *)(long)i); + for_each_online_cpu(cpu) { + rc = topology_add_dev(cpu); + if (rc) + return rc; } - - register_hotcpu_notifier(&topology_cpu_notifier); + hotcpu_notifier(topology_cpu_callback, 0); return 0; } device_initcall(topology_sysfs_init); - -- cgit v1.2.3 From 5ab699810d46011ad2195c5916f3cbc684bfe3ee Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 16 Nov 2006 15:42:07 +0100 Subject: driver core: Introduce device_find_child(). Introduce device_find_child() to match device_for_each_child(). Signed-off-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 33 +++++++++++++++++++++++++++++++++ include/linux/device.h | 2 ++ 2 files changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 5d11bbdfbd2f..a29e68545462 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -750,12 +750,45 @@ int device_for_each_child(struct device * parent, void * data, return error; } +/** + * device_find_child - device iterator for locating a particular device. + * @parent: parent struct device + * @data: Data to pass to match function + * @match: Callback function to check device + * + * This is similar to the device_for_each_child() function above, but it + * returns a reference to a device that is 'found' for later use, as + * determined by the @match callback. + * + * The callback should return 0 if the device doesn't match and non-zero + * if it does. If the callback returns non-zero and a reference to the + * current device can be obtained, this function will return to the caller + * and not iterate over any more devices. + */ +struct device * device_find_child(struct device *parent, void *data, + int (*match)(struct device *, void *)) +{ + struct klist_iter i; + struct device *child; + + if (!parent) + return NULL; + + klist_iter_init(&parent->klist_children, &i); + while ((child = next_device(&i))) + if (match(child, data) && get_device(child)) + break; + klist_iter_exit(&i); + return child; +} + int __init devices_init(void) { return subsystem_register(&devices_subsys); } EXPORT_SYMBOL_GPL(device_for_each_child); +EXPORT_SYMBOL_GPL(device_find_child); EXPORT_SYMBOL_GPL(device_initialize); EXPORT_SYMBOL_GPL(device_add); diff --git a/include/linux/device.h b/include/linux/device.h index 2d9dc358c027..0a0370c74181 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -421,6 +421,8 @@ extern int __must_check device_add(struct device * dev); extern void device_del(struct device * dev); extern int device_for_each_child(struct device *, void *, int (*fn)(struct device *, void *)); +extern struct device *device_find_child(struct device *, void *data, + int (*match)(struct device *, void *)); extern int device_rename(struct device *dev, char *new_name); /* -- cgit v1.2.3 From af9e0765362151b27372c14d9d6dc417184182d3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 17 Nov 2006 02:19:44 +0100 Subject: Driver core: make drivers/base/core.c:setup_parent() static This patch makes the needlessly global setup_parent() static. Signed-off-by: Adrian Bunk Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index a29e68545462..75b45a10935a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -389,7 +389,7 @@ void device_initialize(struct device *dev) } #ifdef CONFIG_SYSFS_DEPRECATED -int setup_parent(struct device *dev, struct device *parent) +static int setup_parent(struct device *dev, struct device *parent) { /* Set the parent to the class, not the parent device */ /* this keeps sysfs from having a symlink to make old udevs happy */ @@ -418,7 +418,7 @@ static int virtual_device_parent(struct device *dev) return 0; } -int setup_parent(struct device *dev, struct device *parent) +static int setup_parent(struct device *dev, struct device *parent) { int error; -- cgit v1.2.3 From 8a82472f86bf693b8e91ed56c9ca4f62fbbdcfa3 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Mon, 20 Nov 2006 17:07:51 +0100 Subject: driver core: Introduce device_move(): move a device to a new parent. Provide a function device_move() to move a device to a new parent device. Add auxilliary functions kobject_move() and sysfs_move_dir(). kobject_move() generates a new uevent of type KOBJ_MOVE, containing the previous path (DEVPATH_OLD) in addition to the usual values. For this, a new interface kobject_uevent_env() is created that allows to add further environmental data to the uevent at the kobject layer. Signed-off-by: Cornelia Huck Acked-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ fs/sysfs/dir.c | 45 ++++++++++++++++++++++++ include/linux/device.h | 1 + include/linux/kobject.h | 8 +++++ include/linux/sysfs.h | 8 +++++ lib/kobject.c | 50 +++++++++++++++++++++++++++ lib/kobject_uevent.c | 28 ++++++++++++--- 7 files changed, 228 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 75b45a10935a..e4eaf46c4d93 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -955,3 +955,95 @@ int device_rename(struct device *dev, char *new_name) return error; } + + +static int device_move_class_links(struct device *dev, + struct device *old_parent, + struct device *new_parent) +{ +#ifdef CONFIG_SYSFS_DEPRECATED + int error; + char *class_name; + + class_name = make_class_name(dev->class->name, &dev->kobj); + if (!class_name) { + error = PTR_ERR(class_name); + class_name = NULL; + goto out; + } + if (old_parent) { + sysfs_remove_link(&dev->kobj, "device"); + sysfs_remove_link(&old_parent->kobj, class_name); + } + error = sysfs_create_link(&dev->kobj, &new_parent->kobj, "device"); + if (error) + goto out; + error = sysfs_create_link(&new_parent->kobj, &dev->kobj, class_name); + if (error) + sysfs_remove_link(&dev->kobj, "device"); +out: + kfree(class_name); + return error; +#else + return 0; +#endif +} + +/** + * device_move - moves a device to a new parent + * @dev: the pointer to the struct device to be moved + * @new_parent: the new parent of the device + */ +int device_move(struct device *dev, struct device *new_parent) +{ + int error; + struct device *old_parent; + + dev = get_device(dev); + if (!dev) + return -EINVAL; + + if (!device_is_registered(dev)) { + error = -EINVAL; + goto out; + } + new_parent = get_device(new_parent); + if (!new_parent) { + error = -EINVAL; + goto out; + } + pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id, + new_parent->bus_id); + error = kobject_move(&dev->kobj, &new_parent->kobj); + if (error) { + put_device(new_parent); + goto out; + } + old_parent = dev->parent; + dev->parent = new_parent; + if (old_parent) + klist_del(&dev->knode_parent); + klist_add_tail(&dev->knode_parent, &new_parent->klist_children); + if (!dev->class) + goto out_put; + error = device_move_class_links(dev, old_parent, new_parent); + if (error) { + /* We ignore errors on cleanup since we're hosed anyway... */ + device_move_class_links(dev, new_parent, old_parent); + if (!kobject_move(&dev->kobj, &old_parent->kobj)) { + klist_del(&dev->knode_parent); + if (old_parent) + klist_add_tail(&dev->knode_parent, + &old_parent->klist_children); + } + put_device(new_parent); + goto out; + } +out_put: + put_device(old_parent); +out: + put_device(dev); + return error; +} + +EXPORT_SYMBOL_GPL(device_move); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 3aa3434621ca..a5782e8c7f07 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -372,6 +372,51 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name) return error; } +int sysfs_move_dir(struct kobject *kobj, struct kobject *new_parent) +{ + struct dentry *old_parent_dentry, *new_parent_dentry, *new_dentry; + struct sysfs_dirent *new_parent_sd, *sd; + int error; + + if (!new_parent) + return -EINVAL; + + old_parent_dentry = kobj->parent ? + kobj->parent->dentry : sysfs_mount->mnt_sb->s_root; + new_parent_dentry = new_parent->dentry; + +again: + mutex_lock(&old_parent_dentry->d_inode->i_mutex); + if (!mutex_trylock(&new_parent_dentry->d_inode->i_mutex)) { + mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + goto again; + } + + new_parent_sd = new_parent_dentry->d_fsdata; + sd = kobj->dentry->d_fsdata; + + new_dentry = lookup_one_len(kobj->name, new_parent_dentry, + strlen(kobj->name)); + if (IS_ERR(new_dentry)) { + error = PTR_ERR(new_dentry); + goto out; + } else + error = 0; + d_add(new_dentry, NULL); + d_move(kobj->dentry, new_dentry); + dput(new_dentry); + + /* Remove from old parent's list and insert into new parent's list. */ + list_del_init(&sd->s_sibling); + list_add(&sd->s_sibling, &new_parent_sd->s_children); + +out: + mutex_unlock(&new_parent_dentry->d_inode->i_mutex); + mutex_unlock(&old_parent_dentry->d_inode->i_mutex); + + return error; +} + static int sysfs_dir_open(struct inode *inode, struct file *file) { struct dentry * dentry = file->f_dentry; diff --git a/include/linux/device.h b/include/linux/device.h index 0a0370c74181..583a341e016c 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -424,6 +424,7 @@ extern int device_for_each_child(struct device *, void *, extern struct device *device_find_child(struct device *, void *data, int (*match)(struct device *, void *)); extern int device_rename(struct device *dev, char *new_name); +extern int device_move(struct device *dev, struct device *new_parent); /* * Manual binding of a device to driver. See drivers/base/bus.c diff --git a/include/linux/kobject.h b/include/linux/kobject.h index bcd9cd173c2c..d1c8d28fa92e 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -47,6 +47,7 @@ enum kobject_action { KOBJ_UMOUNT = (__force kobject_action_t) 0x05, /* umount event for block devices (broken) */ KOBJ_OFFLINE = (__force kobject_action_t) 0x06, /* device offline */ KOBJ_ONLINE = (__force kobject_action_t) 0x07, /* device online */ + KOBJ_MOVE = (__force kobject_action_t) 0x08, /* device move */ }; struct kobject { @@ -76,6 +77,7 @@ extern int __must_check kobject_add(struct kobject *); extern void kobject_del(struct kobject *); extern int __must_check kobject_rename(struct kobject *, const char *new_name); +extern int __must_check kobject_move(struct kobject *, struct kobject *); extern int __must_check kobject_register(struct kobject *); extern void kobject_unregister(struct kobject *); @@ -264,6 +266,8 @@ extern int __must_check subsys_create_file(struct subsystem * , #if defined(CONFIG_HOTPLUG) void kobject_uevent(struct kobject *kobj, enum kobject_action action); +void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, + char *envp[]); int add_uevent_var(char **envp, int num_envp, int *cur_index, char *buffer, int buffer_size, int *cur_len, @@ -271,6 +275,10 @@ int add_uevent_var(char **envp, int num_envp, int *cur_index, __attribute__((format (printf, 7, 8))); #else static inline void kobject_uevent(struct kobject *kobj, enum kobject_action action) { } +static inline void kobject_uevent_env(struct kobject *kobj, + enum kobject_action action, + char *envp[]) +{ } static inline int add_uevent_var(char **envp, int num_envp, int *cur_index, char *buffer, int buffer_size, int *cur_len, diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 6d5c43d31dec..2129d1b6c874 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -96,6 +96,9 @@ sysfs_remove_dir(struct kobject *); extern int __must_check sysfs_rename_dir(struct kobject *, const char *new_name); +extern int __must_check +sysfs_move_dir(struct kobject *, struct kobject *); + extern int __must_check sysfs_create_file(struct kobject *, const struct attribute *); @@ -142,6 +145,11 @@ static inline int sysfs_rename_dir(struct kobject * k, const char *new_name) return 0; } +static inline int sysfs_move_dir(struct kobject * k, struct kobject * new_parent) +{ + return 0; +} + static inline int sysfs_create_file(struct kobject * k, const struct attribute * a) { return 0; diff --git a/lib/kobject.c b/lib/kobject.c index 7dd5c0e9d996..744a4b102c7f 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -310,6 +310,56 @@ int kobject_rename(struct kobject * kobj, const char *new_name) return error; } +/** + * kobject_move - move object to another parent + * @kobj: object in question. + * @new_parent: object's new parent + */ + +int kobject_move(struct kobject *kobj, struct kobject *new_parent) +{ + int error; + struct kobject *old_parent; + const char *devpath = NULL; + char *devpath_string = NULL; + char *envp[2]; + + kobj = kobject_get(kobj); + if (!kobj) + return -EINVAL; + new_parent = kobject_get(new_parent); + if (!new_parent) { + error = -EINVAL; + goto out; + } + /* old object path */ + devpath = kobject_get_path(kobj, GFP_KERNEL); + if (!devpath) { + error = -ENOMEM; + goto out; + } + devpath_string = kmalloc(strlen(devpath) + 15, GFP_KERNEL); + if (!devpath_string) { + error = -ENOMEM; + goto out; + } + sprintf(devpath_string, "DEVPATH_OLD=%s", devpath); + envp[0] = devpath_string; + envp[1] = NULL; + error = sysfs_move_dir(kobj, new_parent); + if (error) + goto out; + old_parent = kobj->parent; + kobj->parent = new_parent; + kobject_put(old_parent); + kobject_uevent_env(kobj, KOBJ_MOVE, envp); +out: + kobject_put(kobj); + kfree(devpath_string); + kfree(devpath); + return error; +} + /** * kobject_del - unlink kobject from hierarchy. * @kobj: object. diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index 7f20e7b857cb..a1922765ff31 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -50,18 +50,22 @@ static char *action_to_string(enum kobject_action action) return "offline"; case KOBJ_ONLINE: return "online"; + case KOBJ_MOVE: + return "move"; default: return NULL; } } /** - * kobject_uevent - notify userspace by ending an uevent + * kobject_uevent_env - send an uevent with environmental data * - * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) + * @action: action that is happening (usually KOBJ_MOVE) * @kobj: struct kobject that the action is happening to + * @envp_ext: pointer to environmental data */ -void kobject_uevent(struct kobject *kobj, enum kobject_action action) +void kobject_uevent_env(struct kobject *kobj, enum kobject_action action, + char *envp_ext[]) { char **envp; char *buffer; @@ -76,6 +80,7 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action) char *seq_buff; int i = 0; int retval; + int j; pr_debug("%s\n", __FUNCTION__); @@ -134,7 +139,8 @@ void kobject_uevent(struct kobject *kobj, enum kobject_action action) scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1; envp [i++] = scratch; scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1; - + for (j = 0; envp_ext && envp_ext[j]; j++) + envp[i++] = envp_ext[j]; /* just reserve the space, overwrite it after kset call has returned */ envp[i++] = seq_buff = scratch; scratch += strlen("SEQNUM=18446744073709551616") + 1; @@ -200,6 +206,20 @@ exit: kfree(envp); return; } + +EXPORT_SYMBOL_GPL(kobject_uevent_env); + +/** + * kobject_uevent - notify userspace by ending an uevent + * + * @action: action that is happening (usually KOBJ_ADD and KOBJ_REMOVE) + * @kobj: struct kobject that the action is happening to + */ +void kobject_uevent(struct kobject *kobj, enum kobject_action action) +{ + kobject_uevent_env(kobj, action, NULL); +} + EXPORT_SYMBOL_GPL(kobject_uevent); /** -- cgit v1.2.3 From acf02d23b96efa92e7cff05987122ceeb37dd075 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 22 Nov 2006 17:49:39 +0100 Subject: driver core: Use klist_remove() in device_move() As pointed out by Alan Stern, device_move needs to use klist_remove which waits until removal is complete. Signed-off-by: Cornelia Huck Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index e4eaf46c4d93..e4b530ef757d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1022,7 +1022,7 @@ int device_move(struct device *dev, struct device *new_parent) old_parent = dev->parent; dev->parent = new_parent; if (old_parent) - klist_del(&dev->knode_parent); + klist_remove(&dev->knode_parent); klist_add_tail(&dev->knode_parent, &new_parent->klist_children); if (!dev->class) goto out_put; @@ -1031,7 +1031,7 @@ int device_move(struct device *dev, struct device *new_parent) /* We ignore errors on cleanup since we're hosed anyway... */ device_move_class_links(dev, new_parent, old_parent); if (!kobject_move(&dev->kobj, &old_parent->kobj)) { - klist_del(&dev->knode_parent); + klist_remove(&dev->knode_parent); if (old_parent) klist_add_tail(&dev->knode_parent, &old_parent->klist_children); -- cgit v1.2.3 From c67334fbdfbba533af767610cf3fde8a49710e62 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 16 Nov 2006 23:28:47 -0800 Subject: Driver core: platform_driver_probe(), can save codespace This defines a new platform_driver_probe() method allowing the driver's probe() method, and its support code+data, to safely live in __init sections for typical system configurations. Many system-on-chip processors could benefit from this API, to the tune of recovering hundreds to thousands of bytes per driver. That's memory which is currently wasted holding code which can never be called after system startup, yet can not be removed. It can't be removed because of the linkage requirement that pointers to init section code (like, ideally, probe support) must not live in other sections (like driver method tables) after those pointers would be invalid. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 48 +++++++++++++++++++++++++++++++++++++++++ include/linux/platform_device.h | 6 ++++++ 2 files changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 940ce41f1887..d1df4a087924 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -388,6 +388,11 @@ static int platform_drv_probe(struct device *_dev) return drv->probe(dev); } +static int platform_drv_probe_fail(struct device *_dev) +{ + return -ENXIO; +} + static int platform_drv_remove(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); @@ -451,6 +456,49 @@ void platform_driver_unregister(struct platform_driver *drv) } EXPORT_SYMBOL_GPL(platform_driver_unregister); +/** + * platform_driver_probe - register driver for non-hotpluggable device + * @drv: platform driver structure + * @probe: the driver probe routine, probably from an __init section + * + * Use this instead of platform_driver_register() when you know the device + * is not hotpluggable and has already been registered, and you want to + * remove its run-once probe() infrastructure from memory after the driver + * has bound to the device. + * + * One typical use for this would be with drivers for controllers integrated + * into system-on-chip processors, where the controller devices have been + * configured as part of board setup. + * + * Returns zero if the driver registered and bound to a device, else returns + * a negative error code and with the driver not registered. + */ +int platform_driver_probe(struct platform_driver *drv, + int (*probe)(struct platform_device *)) +{ + int retval, code; + + /* temporary section violation during probe() */ + drv->probe = probe; + retval = code = platform_driver_register(drv); + + /* Fixup that section violation, being paranoid about code scanning + * the list of drivers in order to probe new devices. Check to see + * if the probe was successful, and make sure any forced probes of + * new devices fail. + */ + spin_lock(&platform_bus_type.klist_drivers.k_lock); + drv->probe = NULL; + if (code == 0 && list_empty(&drv->driver.klist_devices.k_list)) + retval = -ENODEV; + drv->driver.probe = platform_drv_probe_fail; + spin_unlock(&platform_bus_type.klist_drivers.k_lock); + + if (code != retval) + platform_driver_unregister(drv); + return retval; +} +EXPORT_SYMBOL_GPL(platform_driver_probe); /* modalias support enables more hands-off userspace setup: * (a) environment variable lets new-style hotplug events work once system is diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 29cd6dee13db..20f47b81d3fa 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -58,6 +58,12 @@ struct platform_driver { extern int platform_driver_register(struct platform_driver *); extern void platform_driver_unregister(struct platform_driver *); +/* non-hotpluggable platform devices may use this so that probe() and + * its support may live in __init sections, conserving runtime memory. + */ +extern int platform_driver_probe(struct platform_driver *driver, + int (*probe)(struct platform_device *)); + #define platform_get_drvdata(_dev) dev_get_drvdata(&(_dev)->dev) #define platform_set_drvdata(_dev,data) dev_set_drvdata(&(_dev)->dev, (data)) -- cgit v1.2.3 From c4b41c9f077392803cd548000f3a2312dcd4a122 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 3 Oct 2006 16:18:13 +0100 Subject: [PATCH] 2.6.18: sb1250-mac: Broadcom PHY support This patch adds support for interrupt-driven operation of the Broadcom Gigabit Ethernet PHYs. I have included device IDs for the parts used on Broadcom SiByte evaluation boards; more can be added as a need arises. They are apparently generally software-compatible with one another. Signed-off-by: Maciej W. Rozycki patch-mips-2.6.18-20060920-broadcom-phy-15 Signed-off-by: Jeff Garzik --- drivers/net/phy/Kconfig | 6 ++ drivers/net/phy/Makefile | 1 + drivers/net/phy/broadcom.c | 175 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 drivers/net/phy/broadcom.c (limited to 'drivers') diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index ecb61f876f27..f994f129f3d8 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -56,6 +56,12 @@ config SMSC_PHY ---help--- Currently supports the LAN83C185 PHY +config BROADCOM_PHY + tristate "Drivers for Broadcom PHYs" + depends on PHYLIB + ---help--- + Currently supports the BCM5411, BCM5421 and BCM5461 PHYs. + config FIXED_PHY tristate "Drivers for PHY emulation on fixed speed/link" depends on PHYLIB diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 320f8323123f..bcd1efbd2a18 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -10,4 +10,5 @@ obj-$(CONFIG_LXT_PHY) += lxt.o obj-$(CONFIG_QSEMI_PHY) += qsemi.o obj-$(CONFIG_SMSC_PHY) += smsc.o obj-$(CONFIG_VITESSE_PHY) += vitesse.o +obj-$(CONFIG_BROADCOM_PHY) += broadcom.o obj-$(CONFIG_FIXED_PHY) += fixed.o diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c new file mode 100644 index 000000000000..29666c85ed55 --- /dev/null +++ b/drivers/net/phy/broadcom.c @@ -0,0 +1,175 @@ +/* + * drivers/net/phy/broadcom.c + * + * Broadcom BCM5411, BCM5421 and BCM5461 Gigabit Ethernet + * transceivers. + * + * Copyright (c) 2006 Maciej W. Rozycki + * + * Inspired by code written by Amy Fong. + * + * 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 +#include + +#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */ +#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */ +#define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */ + +#define MII_BCM54XX_ESR 0x11 /* BCM54xx extended status register */ +#define MII_BCM54XX_ESR_IS 0x1000 /* Interrupt status */ + +#define MII_BCM54XX_ISR 0x1a /* BCM54xx interrupt status register */ +#define MII_BCM54XX_IMR 0x1b /* BCM54xx interrupt mask register */ +#define MII_BCM54XX_INT_CRCERR 0x0001 /* CRC error */ +#define MII_BCM54XX_INT_LINK 0x0002 /* Link status changed */ +#define MII_BCM54XX_INT_SPEED 0x0004 /* Link speed change */ +#define MII_BCM54XX_INT_DUPLEX 0x0008 /* Duplex mode changed */ +#define MII_BCM54XX_INT_LRS 0x0010 /* Local receiver status changed */ +#define MII_BCM54XX_INT_RRS 0x0020 /* Remote receiver status changed */ +#define MII_BCM54XX_INT_SSERR 0x0040 /* Scrambler synchronization error */ +#define MII_BCM54XX_INT_UHCD 0x0080 /* Unsupported HCD negotiated */ +#define MII_BCM54XX_INT_NHCD 0x0100 /* No HCD */ +#define MII_BCM54XX_INT_NHCDL 0x0200 /* No HCD link */ +#define MII_BCM54XX_INT_ANPR 0x0400 /* Auto-negotiation page received */ +#define MII_BCM54XX_INT_LC 0x0800 /* All counters below 128 */ +#define MII_BCM54XX_INT_HC 0x1000 /* Counter above 32768 */ +#define MII_BCM54XX_INT_MDIX 0x2000 /* MDIX status change */ +#define MII_BCM54XX_INT_PSERR 0x4000 /* Pair swap error */ + +MODULE_DESCRIPTION("Broadcom PHY driver"); +MODULE_AUTHOR("Maciej W. Rozycki"); +MODULE_LICENSE("GPL"); + +static int bcm54xx_config_init(struct phy_device *phydev) +{ + int reg, err; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + /* Mask interrupts globally. */ + reg |= MII_BCM54XX_ECR_IM; + err = phy_write(phydev, MII_BCM54XX_ECR, reg); + if (err < 0) + return err; + + /* Unmask events we are interested in. */ + reg = ~(MII_BCM54XX_INT_DUPLEX | + MII_BCM54XX_INT_SPEED | + MII_BCM54XX_INT_LINK); + err = phy_write(phydev, MII_BCM54XX_IMR, reg); + if (err < 0) + return err; + return 0; +} + +static int bcm54xx_ack_interrupt(struct phy_device *phydev) +{ + int reg; + + /* Clear pending interrupts. */ + reg = phy_read(phydev, MII_BCM54XX_ISR); + if (reg < 0) + return reg; + + return 0; +} + +static int bcm54xx_config_intr(struct phy_device *phydev) +{ + int reg, err; + + reg = phy_read(phydev, MII_BCM54XX_ECR); + if (reg < 0) + return reg; + + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + reg &= ~MII_BCM54XX_ECR_IM; + else + reg |= MII_BCM54XX_ECR_IM; + + err = phy_write(phydev, MII_BCM54XX_ECR, reg); + return err; +} + +static struct phy_driver bcm5411_driver = { + .phy_id = 0x00206070, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5411", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static struct phy_driver bcm5421_driver = { + .phy_id = 0x002060e0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5421", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static struct phy_driver bcm5461_driver = { + .phy_id = 0x002060c0, + .phy_id_mask = 0xfffffff0, + .name = "Broadcom BCM5461", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, + .config_init = bcm54xx_config_init, + .config_aneg = genphy_config_aneg, + .read_status = genphy_read_status, + .ack_interrupt = bcm54xx_ack_interrupt, + .config_intr = bcm54xx_config_intr, + .driver = { .owner = THIS_MODULE }, +}; + +static int __init broadcom_init(void) +{ + int ret; + + ret = phy_driver_register(&bcm5411_driver); + if (ret) + goto out_5411; + ret = phy_driver_register(&bcm5421_driver); + if (ret) + goto out_5421; + ret = phy_driver_register(&bcm5461_driver); + if (ret) + goto out_5461; + return ret; + +out_5461: + phy_driver_unregister(&bcm5421_driver); +out_5421: + phy_driver_unregister(&bcm5411_driver); +out_5411: + return ret; +} + +static void __exit broadcom_exit(void) +{ + phy_driver_unregister(&bcm5461_driver); + phy_driver_unregister(&bcm5421_driver); + phy_driver_unregister(&bcm5411_driver); +} + +module_init(broadcom_init); +module_exit(broadcom_exit); -- cgit v1.2.3 From 3c3070d713d798f7f9e7ee3614e49b47655d14d8 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Tue, 3 Oct 2006 16:18:35 +0100 Subject: [PATCH] 2.6.18: sb1250-mac: Phylib IRQ handling fixes This patch fixes a couple of problems discovered with interrupt handling in the phylib core, namely: 1. The driver uses timer and workqueue calls, but does not include nor . 2. The driver uses schedule_work() for handling interrupts, but does not make sure any pending work scheduled thus has been completed before driver's structures get freed from memory. This is especially important as interrupts may keep arriving if the line is shared with another PHY. The solution is to ignore phy_interrupt() calls if the reported device has already been halted and calling flush_scheduled_work() from phy_stop_interrupts() (but guarded with current_is_keventd() in case the function has been called through keventd from the MAC device's close call to avoid a deadlock on the netlink lock). Signed-off-by: Maciej W. Rozycki patch-mips-2.6.18-20060920-phy-irq-16 Signed-off-by: Jeff Garzik --- drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3af9fcf76c81..95f0419ba21e 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -7,6 +7,7 @@ * Author: Andy Fleming * * Copyright (c) 2004 Freescale Semiconductor, Inc. + * Copyright (c) 2006 Maciej W. Rozycki * * 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 @@ -32,6 +33,8 @@ #include #include #include +#include +#include #include #include @@ -484,6 +487,9 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat) { struct phy_device *phydev = phy_dat; + if (PHY_HALTED == phydev->state) + return IRQ_NONE; /* It can't be ours. */ + /* The MDIO bus is not allowed to be written in interrupt * context, so we need to disable the irq here. A work * queue will write the PHY to disable and clear the @@ -577,6 +583,13 @@ int phy_stop_interrupts(struct phy_device *phydev) if (err) phy_error(phydev); + /* + * Finish any pending work; we might have been scheduled + * to be called from keventd ourselves, though. + */ + if (!current_is_keventd()) + flush_scheduled_work(); + free_irq(phydev->irq, phydev); return err; @@ -603,7 +616,8 @@ static void phy_change(void *data) enable_irq(phydev->irq); /* Reenable interrupts */ - err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); + if (PHY_HALTED != phydev->state) + err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED); if (err) goto irq_enable_err; @@ -624,18 +638,24 @@ void phy_stop(struct phy_device *phydev) if (PHY_HALTED == phydev->state) goto out_unlock; - if (phydev->irq != PHY_POLL) { - /* Clear any pending interrupts */ - phy_clear_interrupt(phydev); + phydev->state = PHY_HALTED; + if (phydev->irq != PHY_POLL) { /* Disable PHY Interrupts */ phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED); - } - phydev->state = PHY_HALTED; + /* Clear any pending interrupts */ + phy_clear_interrupt(phydev); + } out_unlock: spin_unlock(&phydev->lock); + + /* + * Cannot call flush_scheduled_work() here as desired because + * of rtnl_lock(), but PHY_HALTED shall guarantee phy_change() + * will not reenable interrupts. + */ } -- cgit v1.2.3 From a189317fa0e9d425cd3a4c248b06f96d876cf7fd Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 10 Oct 2006 14:33:27 -0700 Subject: [PATCH] forcedeth: power management support Tobias Diedrich sayeth: Vanilla forcedeth doesn't seem to support suspend and an ifdown/up-cycle is needed to get it working again after suspend. Francois Romieu's "Awfully experimental" patch is working just fine for me (with message signalled interrupts disabled) and has survived quite a few suspend/resume cycles. So I'd very much like to see (at least partial, with msi disabled) suspend support for forcedeth in mainline. (Addresses http://bugzilla.kernel.org/show_bug.cgi?id=6398) Cc: Francois Romieu Cc; Jeff Garzik Cc: Manfred Spraul Cc: Ayaz Abdulla Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index c5ed635bce36..87af5e497c51 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4603,6 +4603,50 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) pci_set_drvdata(pci_dev, NULL); } +#ifdef CONFIG_PM +static int nv_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct net_device *dev = pci_get_drvdata(pdev); + struct fe_priv *np = netdev_priv(dev); + + if (!netif_running(dev)) + goto out; + + netif_device_detach(dev); + + // Gross. + nv_close(dev); + + pci_save_state(pdev); + pci_enable_wake(pdev, pci_choose_state(pdev, state), np->wolenabled); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); +out: + return 0; +} + +static int nv_resume(struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + int rc = 0; + + if (!netif_running(dev)) + goto out; + + netif_device_attach(dev); + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + pci_enable_wake(pdev, PCI_D0, 0); + + rc = nv_open(dev); +out: + return rc; +} +#else +#define nv_suspend NULL +#define nv_resume NULL +#endif /* CONFIG_PM */ + static struct pci_device_id pci_tbl[] = { { /* nForce Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_1), @@ -4704,9 +4748,10 @@ static struct pci_driver driver = { .id_table = pci_tbl, .probe = nv_probe, .remove = __devexit_p(nv_remove), + .suspend = nv_suspend, + .resume = nv_resume, }; - static int __init init_nic(void) { printk(KERN_INFO "forcedeth.c: Reverse Engineered nForce ethernet driver. Version %s.\n", FORCEDETH_VERSION); -- cgit v1.2.3 From 107ce6d21b746f33f85f4385b9802b3ae928f876 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 10 Oct 2006 14:33:28 -0700 Subject: [PATCH] Remove unnecessary check in drivers/net/depca.c This was spotted by coverity (cid #793). All callers dereference dev before calling this functions, and we dereference it earlier in the function, when initializing lp. Signed-off-by: Eric Sesterhenn Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/depca.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/depca.c b/drivers/net/depca.c index f87f6e3dc721..5113eef755b9 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1252,24 +1252,22 @@ static void set_multicast_list(struct net_device *dev) struct depca_private *lp = (struct depca_private *) dev->priv; u_long ioaddr = dev->base_addr; - if (dev) { - netif_stop_queue(dev); - while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - - STOP_DEPCA; /* Temporarily stop the depca. */ - depca_init_ring(dev); /* Initialize the descriptor rings */ + netif_stop_queue(dev); + while (lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ - if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ - lp->init_block.mode |= PROM; - } else { - SetMulticastFilter(dev); - lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ - } + STOP_DEPCA; /* Temporarily stop the depca. */ + depca_init_ring(dev); /* Initialize the descriptor rings */ - LoadCSRs(dev); /* Reload CSR3 */ - InitRestartDepca(dev); /* Resume normal operation. */ - netif_start_queue(dev); /* Unlock the TX ring */ + if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ + lp->init_block.mode |= PROM; + } else { + SetMulticastFilter(dev); + lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ } + + LoadCSRs(dev); /* Reload CSR3 */ + InitRestartDepca(dev); /* Resume normal operation. */ + netif_start_queue(dev); /* Unlock the TX ring */ } /* -- cgit v1.2.3 From 83717cf054214d144165c576cba6362d07fc6656 Mon Sep 17 00:00:00 2001 From: Henrik Kretzschmar Date: Tue, 10 Oct 2006 14:33:29 -0700 Subject: [PATCH] pci_module_init() convertion in olympic.c pci_module_init() convertion in olympic.c Signed-off-by: Henrik Kretzschmar Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/tokenring/olympic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c index cd142d0302bc..8f4ecc1109cb 100644 --- a/drivers/net/tokenring/olympic.c +++ b/drivers/net/tokenring/olympic.c @@ -1771,7 +1771,7 @@ static struct pci_driver olympic_driver = { static int __init olympic_pci_init(void) { - return pci_module_init (&olympic_driver) ; + return pci_register_driver(&olympic_driver) ; } static void __exit olympic_pci_cleanup(void) -- cgit v1.2.3 From 24b46a0f0a9a736f125141f271102f70c2612a9f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Oct 2006 10:16:23 -0700 Subject: [PATCH] sk98lin: ethtool register dump Add support for dumping the registers in the deprecated sk98lin driver. This is allows for easier comparison with settings in new skge driver. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sk98lin/skethtool.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c index e5cb5b548b88..36460694eb82 100644 --- a/drivers/net/sk98lin/skethtool.c +++ b/drivers/net/sk98lin/skethtool.c @@ -581,6 +581,30 @@ static int setRxCsum(struct net_device *dev, u32 data) return 0; } +static int getRegsLen(struct net_device *dev) +{ + return 0x4000; +} + +/* + * Returns copy of whole control register region + * Note: skip RAM address register because accessing it will + * cause bus hangs! + */ +static void getRegs(struct net_device *dev, struct ethtool_regs *regs, + void *p) +{ + DEV_NET *pNet = netdev_priv(dev); + const void __iomem *io = pNet->pAC->IoBase; + + regs->version = 1; + memset(p, 0, regs->len); + memcpy_fromio(p, io, B3_RAM_ADDR); + + memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, + regs->len - B3_RI_WTO_R1); +} + const struct ethtool_ops SkGeEthtoolOps = { .get_settings = getSettings, .set_settings = setSettings, @@ -599,4 +623,6 @@ const struct ethtool_ops SkGeEthtoolOps = { .set_tx_csum = setTxCsum, .get_rx_csum = getRxCsum, .set_rx_csum = setRxCsum, + .get_regs = getRegs, + .get_regs_len = getRegsLen, }; -- cgit v1.2.3 From 865f3b2b6ac578a061c823bec5baf00ad04cbd8c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Oct 2006 10:21:26 -0700 Subject: [PATCH] sk98lin: MII ioctl support Add MII ioctl support to the deprecated sk98lin driver. This allows comparison with skge driver's PHY settings. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sk98lin/skge.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index d4913c3de2a1..a5d41ebc9fb4 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -113,6 +113,7 @@ #include #include #include +#include #include "h/skdrv1st.h" #include "h/skdrv2nd.h" @@ -2843,6 +2844,56 @@ unsigned long Flags; /* for spin lock */ return(&pAC->stats); } /* SkGeStats */ +/* + * Basic MII register access + */ +static int SkGeMiiIoctl(struct net_device *dev, + struct mii_ioctl_data *data, int cmd) +{ + DEV_NET *pNet = netdev_priv(dev); + SK_AC *pAC = pNet->pAC; + SK_IOC IoC = pAC->IoBase; + int Port = pNet->PortNr; + SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; + unsigned long Flags; + int err = 0; + int reg = data->reg_num & 0x1f; + SK_U16 val = data->val_in; + + if (!netif_running(dev)) + return -ENODEV; /* Phy still in reset */ + + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + switch(cmd) { + case SIOCGMIIPHY: + data->phy_id = pPrt->PhyAddr; + + /* fallthru */ + case SIOCGMIIREG: + if (pAC->GIni.GIGenesis) + SkXmPhyRead(pAC, IoC, Port, reg, &val); + else + SkGmPhyRead(pAC, IoC, Port, reg, &val); + + data->val_out = val; + break; + + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + err = -EPERM; + + else if (pAC->GIni.GIGenesis) + SkXmPhyWrite(pAC, IoC, Port, reg, val); + else + SkGmPhyWrite(pAC, IoC, Port, reg, val); + break; + default: + err = -EOPNOTSUPP; + } + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + return err; +} + /***************************************************************************** * @@ -2876,6 +2927,9 @@ int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); pNet = netdev_priv(dev); pAC = pNet->pAC; + if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG) + return SkGeMiiIoctl(dev, if_mii(rq), cmd); + if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { return -EFAULT; } -- cgit v1.2.3 From 6c3561b0c1b64c8f0d1419f3909ab29f0eb98906 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 10 Oct 2006 00:19:36 +0100 Subject: [PATCH] beginning of 8390 fixes - generic and arm/etherh etherh and a handful of other odd drivers use different macros when building 8390.c. Since we generate a single 8390.o and then link with it, in any config with both oddball and normal 8390-based driver we will end up with breakage in at least one of them. Solution: take most of 8390.c into lib8390.c and have 8390.c, etherh.c and the rest of oddballs #include it. Helper macros are taken from 8390.h to whoever includes lib8390.c. That way odd drivers get separate instances of compiled 8390 stuff and stop stepping on each other's toes. 8390.h gets cleaned up - we don't have the cascade of ifdefs in there and are left with the stuff that can be used by any 8390-based driver. Current problems are exactly because of that cascade - we attempt to choose the set of helpers by looking at config and that, of course, doesn't work well when we have several sets needed by various drivers in our config. Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/net/8390.c | 1080 +-------------------------------------------- drivers/net/8390.h | 29 +- drivers/net/Makefile | 1 - drivers/net/arm/etherh.c | 27 +- drivers/net/lib8390.c | 1097 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1135 insertions(+), 1099 deletions(-) create mode 100644 drivers/net/lib8390.c (limited to 'drivers') diff --git a/drivers/net/8390.c b/drivers/net/8390.c index 3d1c599ac3cb..a82807641dcf 100644 --- a/drivers/net/8390.c +++ b/drivers/net/8390.c @@ -1,1104 +1,40 @@ -/* 8390.c: A general NS8390 ethernet driver core for linux. */ -/* - Written 1992-94 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - - This is the chip-specific code for many 8390-based ethernet adaptors. - This is not a complete driver, it must be combined with board-specific - code such as ne.c, wd.c, 3c503.c, etc. - - Seeing how at least eight drivers use this code, (not counting the - PCMCIA ones either) it is easy to break some card by what seems like - a simple innocent change. Please contact me or Donald if you think - you have found something that needs changing. -- PG - - - Changelog: - - Paul Gortmaker : remove set_bit lock, other cleanups. - Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to - ei_block_input() for eth_io_copy_and_sum(). - Paul Gortmaker : exchange static int ei_pingpong for a #define, - also add better Tx error handling. - Paul Gortmaker : rewrite Rx overrun handling as per NS specs. - Alexey Kuznetsov : use the 8390's six bit hash multicast filter. - Paul Gortmaker : tweak ANK's above multicast changes a bit. - Paul Gortmaker : update packet statistics for v2.1.x - Alan Cox : support arbitary stupid port mappings on the - 68K Macintosh. Support >16bit I/O spaces - Paul Gortmaker : add kmod support for auto-loading of the 8390 - module by all drivers that require it. - Alan Cox : Spinlocking work, added 'BUG_83C690' - Paul Gortmaker : Separate out Tx timeout code from Tx path. - Paul Gortmaker : Remove old unused single Tx buffer code. - Hayato Fujiwara : Add m32r support. - Paul Gortmaker : use skb_padto() instead of stack scratch area - - Sources: - The National Semiconductor LAN Databook, and the 3Com 3c503 databook. - - */ +/* 8390 core for usual drivers */ static const char version[] = "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NS8390_CORE -#include "8390.h" - -#define BUG_83C690 - -/* These are the operational function interfaces to board-specific - routines. - void reset_8390(struct net_device *dev) - Resets the board associated with DEV, including a hardware reset of - the 8390. This is only called when there is a transmit timeout, and - it is always followed by 8390_init(). - void block_output(struct net_device *dev, int count, const unsigned char *buf, - int start_page) - Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The - "page" value uses the 8390's 256-byte pages. - void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page) - Read the 4 byte, page aligned 8390 header. *If* there is a - subsequent read, it will be of the rest of the packet. - void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) - Read COUNT bytes from the packet buffer into the skb data area. Start - reading from RING_OFFSET, the address as the 8390 sees it. This will always - follow the read of the 8390 header. -*/ -#define ei_reset_8390 (ei_local->reset_8390) -#define ei_block_output (ei_local->block_output) -#define ei_block_input (ei_local->block_input) -#define ei_get_8390_hdr (ei_local->get_8390_hdr) - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef ei_debug -int ei_debug = 1; -#endif - -/* Index to functions. */ -static void ei_tx_intr(struct net_device *dev); -static void ei_tx_err(struct net_device *dev); -static void ei_tx_timeout(struct net_device *dev); -static void ei_receive(struct net_device *dev); -static void ei_rx_overrun(struct net_device *dev); - -/* Routines generic to NS8390-based boards. */ -static void NS8390_trigger_send(struct net_device *dev, unsigned int length, - int start_page); -static void set_multicast_list(struct net_device *dev); -static void do_set_multicast_list(struct net_device *dev); - -/* - * SMP and the 8390 setup. - * - * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is - * a page register that controls bank and packet buffer access. We guard - * this with ei_local->page_lock. Nobody should assume or set the page other - * than zero when the lock is not held. Lock holders must restore page 0 - * before unlocking. Even pure readers must take the lock to protect in - * page 0. - * - * To make life difficult the chip can also be very slow. We therefore can't - * just use spinlocks. For the longer lockups we disable the irq the device - * sits on and hold the lock. We must hold the lock because there is a dual - * processor case other than interrupts (get stats/set multicast list in - * parallel with each other and transmit). - * - * Note: in theory we can just disable the irq on the card _but_ there is - * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs" - * enter lock, take the queued irq. So we waddle instead of flying. - * - * Finally by special arrangement for the purpose of being generally - * annoying the transmit function is called bh atomic. That places - * restrictions on the user context callers as disable_irq won't save - * them. - */ - - +#include "lib8390.c" -/** - * ei_open - Open/initialize the board. - * @dev: network device to initialize - * - * This routine goes all-out, setting everything - * up anew at each open, even though many of these registers should only - * need to be set once at boot. - */ int ei_open(struct net_device *dev) { - unsigned long flags; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - - /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout - wrapper that does e.g. media check & then calls ei_tx_timeout. */ - if (dev->tx_timeout == NULL) - dev->tx_timeout = ei_tx_timeout; - if (dev->watchdog_timeo <= 0) - dev->watchdog_timeo = TX_TIMEOUT; - - /* - * Grab the page lock so we own the register set, then call - * the init function. - */ - - spin_lock_irqsave(&ei_local->page_lock, flags); - NS8390_init(dev, 1); - /* Set the flag before we drop the lock, That way the IRQ arrives - after its set and we get no silly warnings */ - netif_start_queue(dev); - spin_unlock_irqrestore(&ei_local->page_lock, flags); - ei_local->irqlock = 0; - return 0; + return __ei_open(dev); } -/** - * ei_close - shut down network device - * @dev: network device to close - * - * Opposite of ei_open(). Only used when "ifconfig down" is done. - */ int ei_close(struct net_device *dev) { - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - unsigned long flags; - - /* - * Hold the page lock during close - */ - - spin_lock_irqsave(&ei_local->page_lock, flags); - NS8390_init(dev, 0); - spin_unlock_irqrestore(&ei_local->page_lock, flags); - netif_stop_queue(dev); - return 0; -} - -/** - * ei_tx_timeout - handle transmit time out condition - * @dev: network device which has apparently fallen asleep - * - * Called by kernel when device never acknowledges a transmit has - * completed (or failed) - i.e. never posted a Tx related interrupt. - */ - -void ei_tx_timeout(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int txsr, isr, tickssofar = jiffies - dev->trans_start; - unsigned long flags; - -#if defined(CONFIG_M32R) && defined(CONFIG_SMP) - unsigned long icucr; - - local_irq_save(flags); - icucr = inl(M32R_ICU_CR1_PORTL); - icucr |= M32R_ICUCR_ISMOD11; - outl(icucr, M32R_ICU_CR1_PORTL); - local_irq_restore(flags); -#endif - ei_local->stat.tx_errors++; - - spin_lock_irqsave(&ei_local->page_lock, flags); - txsr = inb(e8390_base+EN0_TSR); - isr = inb(e8390_base+EN0_ISR); - spin_unlock_irqrestore(&ei_local->page_lock, flags); - - printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); - - if (!isr && !ei_local->stat.tx_packets) - { - /* The 8390 probably hasn't gotten on the cable yet. */ - ei_local->interface_num ^= 1; /* Try a different xcvr. */ - } - - /* Ugly but a reset can be slow, yet must be protected */ - - disable_irq_nosync_lockdep(dev->irq); - spin_lock(&ei_local->page_lock); - - /* Try to restart the card. Perhaps the user has fixed something. */ - ei_reset_8390(dev); - NS8390_init(dev, 1); - - spin_unlock(&ei_local->page_lock); - enable_irq_lockdep(dev->irq); - netif_wake_queue(dev); -} - -/** - * ei_start_xmit - begin packet transmission - * @skb: packet to be sent - * @dev: network device to which packet is sent - * - * Sends a packet to an 8390 network device. - */ - -static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int send_length = skb->len, output_page; - unsigned long flags; - char buf[ETH_ZLEN]; - char *data = skb->data; - - if (skb->len < ETH_ZLEN) { - memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */ - memcpy(buf, data, skb->len); - send_length = ETH_ZLEN; - data = buf; - } - - /* Mask interrupts from the ethercard. - SMP: We have to grab the lock here otherwise the IRQ handler - on another CPU can flip window and race the IRQ mask set. We end - up trashing the mcast filter not disabling irqs if we don't lock */ - - spin_lock_irqsave(&ei_local->page_lock, flags); - outb_p(0x00, e8390_base + EN0_IMR); - spin_unlock_irqrestore(&ei_local->page_lock, flags); - - - /* - * Slow phase with lock held. - */ - - disable_irq_nosync_lockdep_irqsave(dev->irq, &flags); - - spin_lock(&ei_local->page_lock); - - ei_local->irqlock = 1; - - /* - * We have two Tx slots available for use. Find the first free - * slot, and then perform some sanity checks. With two Tx bufs, - * you get very close to transmitting back-to-back packets. With - * only one Tx buf, the transmitter sits idle while you reload the - * card, leaving a substantial gap between each transmitted packet. - */ - - if (ei_local->tx1 == 0) - { - output_page = ei_local->tx_start_page; - ei_local->tx1 = send_length; - if (ei_debug && ei_local->tx2 > 0) - printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); - } - else if (ei_local->tx2 == 0) - { - output_page = ei_local->tx_start_page + TX_PAGES/2; - ei_local->tx2 = send_length; - if (ei_debug && ei_local->tx1 > 0) - printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", - dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); - } - else - { /* We should never get here. */ - if (ei_debug) - printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n", - dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx); - ei_local->irqlock = 0; - netif_stop_queue(dev); - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - spin_unlock(&ei_local->page_lock); - enable_irq_lockdep_irqrestore(dev->irq, &flags); - ei_local->stat.tx_errors++; - return 1; - } - - /* - * Okay, now upload the packet and trigger a send if the transmitter - * isn't already sending. If it is busy, the interrupt handler will - * trigger the send later, upon receiving a Tx done interrupt. - */ - - ei_block_output(dev, send_length, data, output_page); - - if (! ei_local->txing) - { - ei_local->txing = 1; - NS8390_trigger_send(dev, send_length, output_page); - dev->trans_start = jiffies; - if (output_page == ei_local->tx_start_page) - { - ei_local->tx1 = -1; - ei_local->lasttx = -1; - } - else - { - ei_local->tx2 = -1; - ei_local->lasttx = -2; - } - } - else ei_local->txqueue++; - - if (ei_local->tx1 && ei_local->tx2) - netif_stop_queue(dev); - else - netif_start_queue(dev); - - /* Turn 8390 interrupts back on. */ - ei_local->irqlock = 0; - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - - spin_unlock(&ei_local->page_lock); - enable_irq_lockdep_irqrestore(dev->irq, &flags); - - dev_kfree_skb (skb); - ei_local->stat.tx_bytes += send_length; - - return 0; + return __ei_close(dev); } -/** - * ei_interrupt - handle the interrupts from an 8390 - * @irq: interrupt number - * @dev_id: a pointer to the net_device - * - * Handle the ether interface interrupts. We pull packets from - * the 8390 via the card specific functions and fire them at the networking - * stack. We also handle transmit completions and wake the transmit path if - * necessary. We also update the counters and do other housekeeping as - * needed. - */ - irqreturn_t ei_interrupt(int irq, void *dev_id) { - struct net_device *dev = dev_id; - long e8390_base; - int interrupts, nr_serviced = 0; - struct ei_device *ei_local; - - e8390_base = dev->base_addr; - ei_local = netdev_priv(dev); - - /* - * Protect the irq test too. - */ - - spin_lock(&ei_local->page_lock); - - if (ei_local->irqlock) - { -#if 1 /* This might just be an interrupt for a PCI device sharing this line */ - /* The "irqlock" check is only for testing. */ - printk(ei_local->irqlock - ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n" - : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n", - dev->name, inb_p(e8390_base + EN0_ISR), - inb_p(e8390_base + EN0_IMR)); -#endif - spin_unlock(&ei_local->page_lock); - return IRQ_NONE; - } - - /* Change to page 0 and read the intr status reg. */ - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - if (ei_debug > 3) - printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name, - inb_p(e8390_base + EN0_ISR)); - - /* !!Assumption!! -- we stay in page 0. Don't break this. */ - while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 - && ++nr_serviced < MAX_SERVICE) - { - if (!netif_running(dev)) { - printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name); - /* rmk - acknowledge the interrupts */ - outb_p(interrupts, e8390_base + EN0_ISR); - interrupts = 0; - break; - } - if (interrupts & ENISR_OVER) - ei_rx_overrun(dev); - else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) - { - /* Got a good (?) packet. */ - ei_receive(dev); - } - /* Push the next to-transmit packet through. */ - if (interrupts & ENISR_TX) - ei_tx_intr(dev); - else if (interrupts & ENISR_TX_ERR) - ei_tx_err(dev); - - if (interrupts & ENISR_COUNTERS) - { - ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0); - ei_local->stat.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1); - ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2); - outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */ - } - - /* Ignore any RDC interrupts that make it back to here. */ - if (interrupts & ENISR_RDC) - { - outb_p(ENISR_RDC, e8390_base + EN0_ISR); - } - - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - } - - if (interrupts && ei_debug) - { - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); - if (nr_serviced >= MAX_SERVICE) - { - /* 0xFF is valid for a card removal */ - if(interrupts!=0xFF) - printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n", - dev->name, interrupts); - outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ - } else { - printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts); - outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ - } - } - spin_unlock(&ei_local->page_lock); - return IRQ_RETVAL(nr_serviced > 0); + return __ei_interrupt(irq, dev_id); } #ifdef CONFIG_NET_POLL_CONTROLLER void ei_poll(struct net_device *dev) { - disable_irq_lockdep(dev->irq); - ei_interrupt(dev->irq, dev); - enable_irq_lockdep(dev->irq); + __ei_poll(dev); } #endif -/** - * ei_tx_err - handle transmitter error - * @dev: network device which threw the exception - * - * A transmitter error has happened. Most likely excess collisions (which - * is a fairly normal condition). If the error is one where the Tx will - * have been aborted, we try and send another one right away, instead of - * letting the failed packet sit and collect dust in the Tx buffer. This - * is a much better solution as it avoids kernel based Tx timeouts, and - * an unnecessary card reset. - * - * Called with lock held. - */ - -static void ei_tx_err(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - unsigned char txsr = inb_p(e8390_base+EN0_TSR); - unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); - -#ifdef VERBOSE_ERROR_DUMP - printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); - if (txsr & ENTSR_ABT) - printk("excess-collisions "); - if (txsr & ENTSR_ND) - printk("non-deferral "); - if (txsr & ENTSR_CRS) - printk("lost-carrier "); - if (txsr & ENTSR_FU) - printk("FIFO-underrun "); - if (txsr & ENTSR_CDH) - printk("lost-heartbeat "); - printk("\n"); -#endif - - outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ - - if (tx_was_aborted) - ei_tx_intr(dev); - else - { - ei_local->stat.tx_errors++; - if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; - if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; - if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++; - } -} - -/** - * ei_tx_intr - transmit interrupt handler - * @dev: network device for which tx intr is handled - * - * We have finished a transmit: check for errors and then trigger the next - * packet to be sent. Called with lock held. - */ - -static void ei_tx_intr(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int status = inb(e8390_base + EN0_TSR); - - outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ - - /* - * There are two Tx buffers, see which one finished, and trigger - * the send of another one if it exists. - */ - ei_local->txqueue--; - - if (ei_local->tx1 < 0) - { - if (ei_local->lasttx != 1 && ei_local->lasttx != -1) - printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx1); - ei_local->tx1 = 0; - if (ei_local->tx2 > 0) - { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); - dev->trans_start = jiffies; - ei_local->tx2 = -1, - ei_local->lasttx = 2; - } - else ei_local->lasttx = 20, ei_local->txing = 0; - } - else if (ei_local->tx2 < 0) - { - if (ei_local->lasttx != 2 && ei_local->lasttx != -2) - printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", - ei_local->name, ei_local->lasttx, ei_local->tx2); - ei_local->tx2 = 0; - if (ei_local->tx1 > 0) - { - ei_local->txing = 1; - NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); - dev->trans_start = jiffies; - ei_local->tx1 = -1; - ei_local->lasttx = 1; - } - else - ei_local->lasttx = 10, ei_local->txing = 0; - } -// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", -// dev->name, ei_local->lasttx); - - /* Minimize Tx latency: update the statistics after we restart TXing. */ - if (status & ENTSR_COL) - ei_local->stat.collisions++; - if (status & ENTSR_PTX) - ei_local->stat.tx_packets++; - else - { - ei_local->stat.tx_errors++; - if (status & ENTSR_ABT) - { - ei_local->stat.tx_aborted_errors++; - ei_local->stat.collisions += 16; - } - if (status & ENTSR_CRS) - ei_local->stat.tx_carrier_errors++; - if (status & ENTSR_FU) - ei_local->stat.tx_fifo_errors++; - if (status & ENTSR_CDH) - ei_local->stat.tx_heartbeat_errors++; - if (status & ENTSR_OWC) - ei_local->stat.tx_window_errors++; - } - netif_wake_queue(dev); -} - -/** - * ei_receive - receive some packets - * @dev: network device with which receive will be run - * - * We have a good packet(s), get it/them out of the buffers. - * Called with lock held. - */ - -static void ei_receive(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - unsigned char rxing_page, this_frame, next_frame; - unsigned short current_offset; - int rx_pkt_count = 0; - struct e8390_pkt_hdr rx_frame; - int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; - - while (++rx_pkt_count < 10) - { - int pkt_len, pkt_stat; - - /* Get the rx page (incoming packet pointer). */ - outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD); - rxing_page = inb_p(e8390_base + EN1_CURPAG); - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); - - /* Remove one frame from the ring. Boundary is always a page behind. */ - this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1; - if (this_frame >= ei_local->stop_page) - this_frame = ei_local->rx_start_page; - - /* Someday we'll omit the previous, iff we never get this message. - (There is at least one clone claimed to have a problem.) - - Keep quiet if it looks like a card removal. One problem here - is that some clones crash in roughly the same way. - */ - if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) - printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", - dev->name, this_frame, ei_local->current_page); - - if (this_frame == rxing_page) /* Read all the frames? */ - break; /* Done for now */ - - current_offset = this_frame << 8; - ei_get_8390_hdr(dev, &rx_frame, this_frame); - - pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr); - pkt_stat = rx_frame.status; - - next_frame = this_frame + 1 + ((pkt_len+4)>>8); - - /* Check for bogosity warned by 3c503 book: the status byte is never - written. This happened a lot during testing! This code should be - cleaned up someday. */ - if (rx_frame.next != next_frame - && rx_frame.next != next_frame + 1 - && rx_frame.next != next_frame - num_rx_pages - && rx_frame.next != next_frame + 1 - num_rx_pages) { - ei_local->current_page = rxing_page; - outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY); - ei_local->stat.rx_errors++; - continue; - } - - if (pkt_len < 60 || pkt_len > 1518) - { - if (ei_debug) - printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", - dev->name, rx_frame.count, rx_frame.status, - rx_frame.next); - ei_local->stat.rx_errors++; - ei_local->stat.rx_length_errors++; - } - else if ((pkt_stat & 0x0F) == ENRSR_RXOK) - { - struct sk_buff *skb; - - skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) - { - if (ei_debug > 1) - printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", - dev->name, pkt_len); - ei_local->stat.rx_dropped++; - break; - } - else - { - skb_reserve(skb,2); /* IP headers on 16 byte boundaries */ - skb->dev = dev; - skb_put(skb, pkt_len); /* Make room */ - ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame)); - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->last_rx = jiffies; - ei_local->stat.rx_packets++; - ei_local->stat.rx_bytes += pkt_len; - if (pkt_stat & ENRSR_PHY) - ei_local->stat.multicast++; - } - } - else - { - if (ei_debug) - printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", - dev->name, rx_frame.status, rx_frame.next, - rx_frame.count); - ei_local->stat.rx_errors++; - /* NB: The NIC counts CRC, frame and missed errors. */ - if (pkt_stat & ENRSR_FO) - ei_local->stat.rx_fifo_errors++; - } - next_frame = rx_frame.next; - - /* This _should_ never happen: it's here for avoiding bad clones. */ - if (next_frame >= ei_local->stop_page) { - printk("%s: next frame inconsistency, %#2x\n", dev->name, - next_frame); - next_frame = ei_local->rx_start_page; - } - ei_local->current_page = next_frame; - outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); - } - - /* We used to also ack ENISR_OVER here, but that would sometimes mask - a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ - outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR); - return; -} - -/** - * ei_rx_overrun - handle receiver overrun - * @dev: network device which threw exception - * - * We have a receiver overrun: we have to kick the 8390 to get it started - * again. Problem is that you have to kick it exactly as NS prescribes in - * the updated datasheets, or "the NIC may act in an unpredictable manner." - * This includes causing "the NIC to defer indefinitely when it is stopped - * on a busy network." Ugh. - * Called with lock held. Don't call this with the interrupts off or your - * computer will hate you - it takes 10ms or so. - */ - -static void ei_rx_overrun(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - unsigned char was_txing, must_resend = 0; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - - /* - * Record whether a Tx was in progress and then issue the - * stop command. - */ - was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - - if (ei_debug > 1) - printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); - ei_local->stat.rx_over_errors++; - - /* - * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. - * Early datasheets said to poll the reset bit, but now they say that - * it "is not a reliable indicator and subsequently should be ignored." - * We wait at least 10ms. - */ - - mdelay(10); - - /* - * Reset RBCR[01] back to zero as per magic incantation. - */ - outb_p(0x00, e8390_base+EN0_RCNTLO); - outb_p(0x00, e8390_base+EN0_RCNTHI); - - /* - * See if any Tx was interrupted or not. According to NS, this - * step is vital, and skipping it will cause no end of havoc. - */ - - if (was_txing) - { - unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); - if (!tx_completed) - must_resend = 1; - } - - /* - * Have to enter loopback mode and then restart the NIC before - * you are allowed to slurp packets up off the ring. - */ - outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); - outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); - - /* - * Clear the Rx ring of all the debris, and ack the interrupt. - */ - ei_receive(dev); - outb_p(ENISR_OVER, e8390_base+EN0_ISR); - - /* - * Leave loopback mode, and resend any packet that got stopped. - */ - outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); - if (must_resend) - outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); -} - -/* - * Collect the stats. This is called unlocked and from several contexts. - */ - -static struct net_device_stats *get_stats(struct net_device *dev) -{ - long ioaddr = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - unsigned long flags; - - /* If the card is stopped, just return the present stats. */ - if (!netif_running(dev)) - return &ei_local->stat; - - spin_lock_irqsave(&ei_local->page_lock,flags); - /* Read the counter registers, assuming we are in page 0. */ - ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); - ei_local->stat.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1); - ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); - spin_unlock_irqrestore(&ei_local->page_lock, flags); - - return &ei_local->stat; -} - -/* - * Form the 64 bit 8390 multicast table from the linked list of addresses - * associated with this dev structure. - */ - -static inline void make_mc_bits(u8 *bits, struct net_device *dev) -{ - struct dev_mc_list *dmi; - - for (dmi=dev->mc_list; dmi; dmi=dmi->next) - { - u32 crc; - if (dmi->dmi_addrlen != ETH_ALEN) - { - printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); - continue; - } - crc = ether_crc(ETH_ALEN, dmi->dmi_addr); - /* - * The 8390 uses the 6 most significant bits of the - * CRC to index the multicast table. - */ - bits[crc>>29] |= (1<<((crc>>26)&7)); - } -} - -/** - * do_set_multicast_list - set/clear multicast filter - * @dev: net device for which multicast filter is adjusted - * - * Set or clear the multicast filter for this adaptor. May be called - * from a BH in 2.1.x. Must be called with lock held. - */ - -static void do_set_multicast_list(struct net_device *dev) -{ - long e8390_base = dev->base_addr; - int i; - struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); - - if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) - { - memset(ei_local->mcfilter, 0, 8); - if (dev->mc_list) - make_mc_bits(ei_local->mcfilter, dev); - } - else - memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */ - - /* - * DP8390 manuals don't specify any magic sequence for altering - * the multicast regs on an already running card. To be safe, we - * ensure multicast mode is off prior to loading up the new hash - * table. If this proves to be not enough, we can always resort - * to stopping the NIC, loading the table and then restarting. - * - * Bug Alert! The MC regs on the SMC 83C690 (SMC Elite and SMC - * Elite16) appear to be write-only. The NS 8390 data sheet lists - * them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and - * Ultra32 EISA) appears to have this bug fixed. - */ - - if (netif_running(dev)) - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); - outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); - for(i = 0; i < 8; i++) - { - outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); -#ifndef BUG_83C690 - if(inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i]) - printk(KERN_ERR "Multicast filter read/write mismap %d\n",i); -#endif - } - outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); - - if(dev->flags&IFF_PROMISC) - outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR); - else if(dev->flags&IFF_ALLMULTI || dev->mc_list) - outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR); - else - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); - } - -/* - * Called without lock held. This is invoked from user context and may - * be parallel to just about everything else. Its also fairly quick and - * not called too often. Must protect against both bh and irq users - */ - -static void set_multicast_list(struct net_device *dev) -{ - unsigned long flags; - struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); - - spin_lock_irqsave(&ei_local->page_lock, flags); - do_set_multicast_list(dev); - spin_unlock_irqrestore(&ei_local->page_lock, flags); -} - -/** - * ethdev_setup - init rest of 8390 device struct - * @dev: network device structure to init - * - * Initialize the rest of the 8390 device structure. Do NOT __init - * this, as it is used by 8390 based modular drivers too. - */ - -static void ethdev_setup(struct net_device *dev) -{ - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - if (ei_debug > 1) - printk(version); - - dev->hard_start_xmit = &ei_start_xmit; - dev->get_stats = get_stats; - dev->set_multicast_list = &set_multicast_list; - - ether_setup(dev); - - spin_lock_init(&ei_local->page_lock); -} - -/** - * alloc_ei_netdev - alloc_etherdev counterpart for 8390 - * @size: extra bytes to allocate - * - * Allocate 8390-specific net_device. - */ struct net_device *__alloc_ei_netdev(int size) { - return alloc_netdev(sizeof(struct ei_device) + size, "eth%d", - ethdev_setup); + return ____alloc_ei_netdev(size); } - - - -/* This page of functions should be 8390 generic */ -/* Follow National Semi's recommendations for initializing the "NIC". */ - -/** - * NS8390_init - initialize 8390 hardware - * @dev: network device to initialize - * @startp: boolean. non-zero value to initiate chip processing - * - * Must be called with lock held. - */ - void NS8390_init(struct net_device *dev, int startp) { - long e8390_base = dev->base_addr; - struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); - int i; - int endcfg = ei_local->word16 - ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0)) - : 0x48; - - if(sizeof(struct e8390_pkt_hdr)!=4) - panic("8390.c: header struct mispacked\n"); - /* Follow National Semi's recommendations for initing the DP83902. */ - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ - outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ - /* Clear the remote byte count registers. */ - outb_p(0x00, e8390_base + EN0_RCNTLO); - outb_p(0x00, e8390_base + EN0_RCNTHI); - /* Set to monitor and loopback mode -- this is vital!. */ - outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ - outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ - /* Set the transmit page and receive ring. */ - outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); - ei_local->tx1 = ei_local->tx2 = 0; - outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); - outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ - ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ - outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); - /* Clear the pending interrupts and mask. */ - outb_p(0xFF, e8390_base + EN0_ISR); - outb_p(0x00, e8390_base + EN0_IMR); - - /* Copy the station address into the DS8390 registers. */ - - outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ - for(i = 0; i < 6; i++) - { - outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); - if (ei_debug > 1 && inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) - printk(KERN_ERR "Hw. address read/write mismap %d\n",i); - } - - outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - - netif_start_queue(dev); - ei_local->tx1 = ei_local->tx2 = 0; - ei_local->txing = 0; - - if (startp) - { - outb_p(0xff, e8390_base + EN0_ISR); - outb_p(ENISR_ALL, e8390_base + EN0_IMR); - outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); - outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ - /* 3c503 TechMan says rxconfig only after the NIC is started. */ - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ - do_set_multicast_list(dev); /* (re)load the mcast table */ - } -} - -/* Trigger a transmit start, assuming the length is valid. - Always called with the page lock held */ - -static void NS8390_trigger_send(struct net_device *dev, unsigned int length, - int start_page) -{ - long e8390_base = dev->base_addr; - struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev); - - outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); - - if (inb_p(e8390_base + E8390_CMD) & E8390_TRANS) - { - printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", - dev->name); - return; - } - outb_p(length & 0xff, e8390_base + EN0_TCNTLO); - outb_p(length >> 8, e8390_base + EN0_TCNTHI); - outb_p(start_page, e8390_base + EN0_TPSR); - outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); + return __NS8390_init(dev, startp); } EXPORT_SYMBOL(ei_open); diff --git a/drivers/net/8390.h b/drivers/net/8390.h index f44f1220b3a5..fae4aa92c4b7 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -116,26 +116,23 @@ struct ei_device { #undef outb #undef outb_p -#define inb(port) in_8(port) -#define outb(val,port) out_8(port,val) -#define inb_p(port) in_8(port) -#define outb_p(val,port) out_8(port,val) +#define ei_inb(port) in_8(port) +#define ei_outb(val,port) out_8(port,val) +#define ei_inb_p(port) in_8(port) +#define ei_outb_p(val,port) out_8(port,val) -#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) +#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) -#undef inb -#undef inb_p -#undef outb -#undef outb_p +#endif -#define inb(_p) readb(_p) -#define outb(_v,_p) writeb(_v,_p) -#define inb_p(_p) inb(_p) -#define outb_p(_v,_p) outb(_v,_p) +#ifndef ei_inb +#define ei_inb(_p) inb(_p) +#define ei_outb(_v,_p) outb(_v,_p) +#define ei_inb_p(_p) inb_p(_p) +#define ei_outb_p(_v,_p) outb_p(_v,_p) +#endif -#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) -#define EI_SHIFT(x) (ei_local->reg_offset[x]) -#else +#ifndef EI_SHIFT #define EI_SHIFT(x) (x) #endif diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f270bc49e571..53ccc337099c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -90,7 +90,6 @@ obj-$(CONFIG_HP100) += hp100.o obj-$(CONFIG_SMC9194) += smc9194.o obj-$(CONFIG_FEC) += fec.o obj-$(CONFIG_68360_ENET) += 68360enet.o -obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 4ae98970b282..747a71f5dd0e 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -52,7 +52,12 @@ #include #include -#include "../8390.h" +#define EI_SHIFT(x) (ei_local->reg_offset[x]) + +#define ei_inb(_p) readb(_p) +#define ei_outb(_v,_p) writeb(_v,_p) +#define ei_inb_p(_p) readb(_p) +#define ei_outb_p(_v,_p) writeb(_v,_p) #define NET_DEBUG 0 #define DEBUG_INIT 2 @@ -60,6 +65,11 @@ #define DRV_NAME "etherh" #define DRV_VERSION "1.11" +static char version[] __initdata = + "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; + +#include "../lib8390.c" + static unsigned int net_debug = NET_DEBUG; struct etherh_priv { @@ -87,9 +97,6 @@ MODULE_AUTHOR("Russell King"); MODULE_DESCRIPTION("EtherH/EtherM driver"); MODULE_LICENSE("GPL"); -static char version[] __initdata = - "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; - #define ETHERH500_DATAPORT 0x800 /* MEMC */ #define ETHERH500_NS8390 0x000 /* MEMC */ #define ETHERH500_CTRLPORT 0x800 /* IOC */ @@ -360,7 +367,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf printk(KERN_ERR "%s: timeout waiting for TX RDC\n", dev->name); etherh_reset (dev); - NS8390_init (dev, 1); + __NS8390_init (dev, 1); break; } @@ -465,7 +472,7 @@ etherh_open(struct net_device *dev) return -EINVAL; } - if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev)) + if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev)) return -EAGAIN; /* @@ -491,7 +498,7 @@ etherh_open(struct net_device *dev) etherh_setif(dev); etherh_reset(dev); - ei_open(dev); + __ei_open(dev); return 0; } @@ -502,7 +509,7 @@ etherh_open(struct net_device *dev) static int etherh_close(struct net_device *dev) { - ei_close (dev); + __ei_close (dev); free_irq (dev->irq, dev); return 0; } @@ -650,7 +657,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) if (ret) goto out; - dev = __alloc_ei_netdev(sizeof(struct etherh_priv)); + dev = ____alloc_ei_netdev(sizeof(struct etherh_priv)); if (!dev) { ret = -ENOMEM; goto release; @@ -736,7 +743,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id) ei_local->interface_num = 0; etherh_reset(dev); - NS8390_init(dev, 0); + __NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c new file mode 100644 index 000000000000..e726c06b8dc6 --- /dev/null +++ b/drivers/net/lib8390.c @@ -0,0 +1,1097 @@ +/* 8390.c: A general NS8390 ethernet driver core for linux. */ +/* + Written 1992-94 by Donald Becker. + + Copyright 1993 United States Government as represented by the + Director, National Security Agency. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 + + + This is the chip-specific code for many 8390-based ethernet adaptors. + This is not a complete driver, it must be combined with board-specific + code such as ne.c, wd.c, 3c503.c, etc. + + Seeing how at least eight drivers use this code, (not counting the + PCMCIA ones either) it is easy to break some card by what seems like + a simple innocent change. Please contact me or Donald if you think + you have found something that needs changing. -- PG + + + Changelog: + + Paul Gortmaker : remove set_bit lock, other cleanups. + Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to + ei_block_input() for eth_io_copy_and_sum(). + Paul Gortmaker : exchange static int ei_pingpong for a #define, + also add better Tx error handling. + Paul Gortmaker : rewrite Rx overrun handling as per NS specs. + Alexey Kuznetsov : use the 8390's six bit hash multicast filter. + Paul Gortmaker : tweak ANK's above multicast changes a bit. + Paul Gortmaker : update packet statistics for v2.1.x + Alan Cox : support arbitary stupid port mappings on the + 68K Macintosh. Support >16bit I/O spaces + Paul Gortmaker : add kmod support for auto-loading of the 8390 + module by all drivers that require it. + Alan Cox : Spinlocking work, added 'BUG_83C690' + Paul Gortmaker : Separate out Tx timeout code from Tx path. + Paul Gortmaker : Remove old unused single Tx buffer code. + Hayato Fujiwara : Add m32r support. + Paul Gortmaker : use skb_padto() instead of stack scratch area + + Sources: + The National Semiconductor LAN Databook, and the 3Com 3c503 databook. + + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define NS8390_CORE +#include "8390.h" + +#define BUG_83C690 + +/* These are the operational function interfaces to board-specific + routines. + void reset_8390(struct net_device *dev) + Resets the board associated with DEV, including a hardware reset of + the 8390. This is only called when there is a transmit timeout, and + it is always followed by 8390_init(). + void block_output(struct net_device *dev, int count, const unsigned char *buf, + int start_page) + Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The + "page" value uses the 8390's 256-byte pages. + void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page) + Read the 4 byte, page aligned 8390 header. *If* there is a + subsequent read, it will be of the rest of the packet. + void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) + Read COUNT bytes from the packet buffer into the skb data area. Start + reading from RING_OFFSET, the address as the 8390 sees it. This will always + follow the read of the 8390 header. +*/ +#define ei_reset_8390 (ei_local->reset_8390) +#define ei_block_output (ei_local->block_output) +#define ei_block_input (ei_local->block_input) +#define ei_get_8390_hdr (ei_local->get_8390_hdr) + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifndef ei_debug +int ei_debug = 1; +#endif + +/* Index to functions. */ +static void ei_tx_intr(struct net_device *dev); +static void ei_tx_err(struct net_device *dev); +static void ei_tx_timeout(struct net_device *dev); +static void ei_receive(struct net_device *dev); +static void ei_rx_overrun(struct net_device *dev); + +/* Routines generic to NS8390-based boards. */ +static void NS8390_trigger_send(struct net_device *dev, unsigned int length, + int start_page); +static void set_multicast_list(struct net_device *dev); +static void do_set_multicast_list(struct net_device *dev); +static void __NS8390_init(struct net_device *dev, int startp); + +/* + * SMP and the 8390 setup. + * + * The 8390 isnt exactly designed to be multithreaded on RX/TX. There is + * a page register that controls bank and packet buffer access. We guard + * this with ei_local->page_lock. Nobody should assume or set the page other + * than zero when the lock is not held. Lock holders must restore page 0 + * before unlocking. Even pure readers must take the lock to protect in + * page 0. + * + * To make life difficult the chip can also be very slow. We therefore can't + * just use spinlocks. For the longer lockups we disable the irq the device + * sits on and hold the lock. We must hold the lock because there is a dual + * processor case other than interrupts (get stats/set multicast list in + * parallel with each other and transmit). + * + * Note: in theory we can just disable the irq on the card _but_ there is + * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs" + * enter lock, take the queued irq. So we waddle instead of flying. + * + * Finally by special arrangement for the purpose of being generally + * annoying the transmit function is called bh atomic. That places + * restrictions on the user context callers as disable_irq won't save + * them. + */ + + + +/** + * ei_open - Open/initialize the board. + * @dev: network device to initialize + * + * This routine goes all-out, setting everything + * up anew at each open, even though many of these registers should only + * need to be set once at boot. + */ +static int __ei_open(struct net_device *dev) +{ + unsigned long flags; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + + /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout + wrapper that does e.g. media check & then calls ei_tx_timeout. */ + if (dev->tx_timeout == NULL) + dev->tx_timeout = ei_tx_timeout; + if (dev->watchdog_timeo <= 0) + dev->watchdog_timeo = TX_TIMEOUT; + + /* + * Grab the page lock so we own the register set, then call + * the init function. + */ + + spin_lock_irqsave(&ei_local->page_lock, flags); + __NS8390_init(dev, 1); + /* Set the flag before we drop the lock, That way the IRQ arrives + after its set and we get no silly warnings */ + netif_start_queue(dev); + spin_unlock_irqrestore(&ei_local->page_lock, flags); + ei_local->irqlock = 0; + return 0; +} + +/** + * ei_close - shut down network device + * @dev: network device to close + * + * Opposite of ei_open(). Only used when "ifconfig down" is done. + */ +static int __ei_close(struct net_device *dev) +{ + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + unsigned long flags; + + /* + * Hold the page lock during close + */ + + spin_lock_irqsave(&ei_local->page_lock, flags); + __NS8390_init(dev, 0); + spin_unlock_irqrestore(&ei_local->page_lock, flags); + netif_stop_queue(dev); + return 0; +} + +/** + * ei_tx_timeout - handle transmit time out condition + * @dev: network device which has apparently fallen asleep + * + * Called by kernel when device never acknowledges a transmit has + * completed (or failed) - i.e. never posted a Tx related interrupt. + */ + +static void ei_tx_timeout(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + int txsr, isr, tickssofar = jiffies - dev->trans_start; + unsigned long flags; + +#if defined(CONFIG_M32R) && defined(CONFIG_SMP) + unsigned long icucr; + + local_irq_save(flags); + icucr = inl(M32R_ICU_CR1_PORTL); + icucr |= M32R_ICUCR_ISMOD11; + outl(icucr, M32R_ICU_CR1_PORTL); + local_irq_restore(flags); +#endif + ei_local->stat.tx_errors++; + + spin_lock_irqsave(&ei_local->page_lock, flags); + txsr = ei_inb(e8390_base+EN0_TSR); + isr = ei_inb(e8390_base+EN0_ISR); + spin_unlock_irqrestore(&ei_local->page_lock, flags); + + printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", + dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : + (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); + + if (!isr && !ei_local->stat.tx_packets) + { + /* The 8390 probably hasn't gotten on the cable yet. */ + ei_local->interface_num ^= 1; /* Try a different xcvr. */ + } + + /* Ugly but a reset can be slow, yet must be protected */ + + disable_irq_nosync_lockdep(dev->irq); + spin_lock(&ei_local->page_lock); + + /* Try to restart the card. Perhaps the user has fixed something. */ + ei_reset_8390(dev); + __NS8390_init(dev, 1); + + spin_unlock(&ei_local->page_lock); + enable_irq_lockdep(dev->irq); + netif_wake_queue(dev); +} + +/** + * ei_start_xmit - begin packet transmission + * @skb: packet to be sent + * @dev: network device to which packet is sent + * + * Sends a packet to an 8390 network device. + */ + +static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + int send_length = skb->len, output_page; + unsigned long flags; + char buf[ETH_ZLEN]; + char *data = skb->data; + + if (skb->len < ETH_ZLEN) { + memset(buf, 0, ETH_ZLEN); /* more efficient than doing just the needed bits */ + memcpy(buf, data, skb->len); + send_length = ETH_ZLEN; + data = buf; + } + + /* Mask interrupts from the ethercard. + SMP: We have to grab the lock here otherwise the IRQ handler + on another CPU can flip window and race the IRQ mask set. We end + up trashing the mcast filter not disabling irqs if we don't lock */ + + spin_lock_irqsave(&ei_local->page_lock, flags); + ei_outb_p(0x00, e8390_base + EN0_IMR); + spin_unlock_irqrestore(&ei_local->page_lock, flags); + + + /* + * Slow phase with lock held. + */ + + disable_irq_nosync_lockdep_irqsave(dev->irq, &flags); + + spin_lock(&ei_local->page_lock); + + ei_local->irqlock = 1; + + /* + * We have two Tx slots available for use. Find the first free + * slot, and then perform some sanity checks. With two Tx bufs, + * you get very close to transmitting back-to-back packets. With + * only one Tx buf, the transmitter sits idle while you reload the + * card, leaving a substantial gap between each transmitted packet. + */ + + if (ei_local->tx1 == 0) + { + output_page = ei_local->tx_start_page; + ei_local->tx1 = send_length; + if (ei_debug && ei_local->tx2 > 0) + printk(KERN_DEBUG "%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing); + } + else if (ei_local->tx2 == 0) + { + output_page = ei_local->tx_start_page + TX_PAGES/2; + ei_local->tx2 = send_length; + if (ei_debug && ei_local->tx1 > 0) + printk(KERN_DEBUG "%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing); + } + else + { /* We should never get here. */ + if (ei_debug) + printk(KERN_DEBUG "%s: No Tx buffers free! tx1=%d tx2=%d last=%d\n", + dev->name, ei_local->tx1, ei_local->tx2, ei_local->lasttx); + ei_local->irqlock = 0; + netif_stop_queue(dev); + ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR); + spin_unlock(&ei_local->page_lock); + enable_irq_lockdep_irqrestore(dev->irq, &flags); + ei_local->stat.tx_errors++; + return 1; + } + + /* + * Okay, now upload the packet and trigger a send if the transmitter + * isn't already sending. If it is busy, the interrupt handler will + * trigger the send later, upon receiving a Tx done interrupt. + */ + + ei_block_output(dev, send_length, data, output_page); + + if (! ei_local->txing) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, send_length, output_page); + dev->trans_start = jiffies; + if (output_page == ei_local->tx_start_page) + { + ei_local->tx1 = -1; + ei_local->lasttx = -1; + } + else + { + ei_local->tx2 = -1; + ei_local->lasttx = -2; + } + } + else ei_local->txqueue++; + + if (ei_local->tx1 && ei_local->tx2) + netif_stop_queue(dev); + else + netif_start_queue(dev); + + /* Turn 8390 interrupts back on. */ + ei_local->irqlock = 0; + ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR); + + spin_unlock(&ei_local->page_lock); + enable_irq_lockdep_irqrestore(dev->irq, &flags); + + dev_kfree_skb (skb); + ei_local->stat.tx_bytes += send_length; + + return 0; +} + +/** + * ei_interrupt - handle the interrupts from an 8390 + * @irq: interrupt number + * @dev_id: a pointer to the net_device + * + * Handle the ether interface interrupts. We pull packets from + * the 8390 via the card specific functions and fire them at the networking + * stack. We also handle transmit completions and wake the transmit path if + * necessary. We also update the counters and do other housekeeping as + * needed. + */ + +static irqreturn_t __ei_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + unsigned long e8390_base = dev->base_addr; + int interrupts, nr_serviced = 0; + struct ei_device *ei_local = netdev_priv(dev); + + /* + * Protect the irq test too. + */ + + spin_lock(&ei_local->page_lock); + + if (ei_local->irqlock) + { +#if 1 /* This might just be an interrupt for a PCI device sharing this line */ + /* The "irqlock" check is only for testing. */ + printk(ei_local->irqlock + ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n" + : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n", + dev->name, ei_inb_p(e8390_base + EN0_ISR), + ei_inb_p(e8390_base + EN0_IMR)); +#endif + spin_unlock(&ei_local->page_lock); + return IRQ_NONE; + } + + /* Change to page 0 and read the intr status reg. */ + ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); + if (ei_debug > 3) + printk(KERN_DEBUG "%s: interrupt(isr=%#2.2x).\n", dev->name, + ei_inb_p(e8390_base + EN0_ISR)); + + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = ei_inb_p(e8390_base + EN0_ISR)) != 0 + && ++nr_serviced < MAX_SERVICE) + { + if (!netif_running(dev)) { + printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name); + /* rmk - acknowledge the interrupts */ + ei_outb_p(interrupts, e8390_base + EN0_ISR); + interrupts = 0; + break; + } + if (interrupts & ENISR_OVER) + ei_rx_overrun(dev); + else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) + { + /* Got a good (?) packet. */ + ei_receive(dev); + } + /* Push the next to-transmit packet through. */ + if (interrupts & ENISR_TX) + ei_tx_intr(dev); + else if (interrupts & ENISR_TX_ERR) + ei_tx_err(dev); + + if (interrupts & ENISR_COUNTERS) + { + ei_local->stat.rx_frame_errors += ei_inb_p(e8390_base + EN0_COUNTER0); + ei_local->stat.rx_crc_errors += ei_inb_p(e8390_base + EN0_COUNTER1); + ei_local->stat.rx_missed_errors+= ei_inb_p(e8390_base + EN0_COUNTER2); + ei_outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */ + } + + /* Ignore any RDC interrupts that make it back to here. */ + if (interrupts & ENISR_RDC) + { + ei_outb_p(ENISR_RDC, e8390_base + EN0_ISR); + } + + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); + } + + if (interrupts && ei_debug) + { + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); + if (nr_serviced >= MAX_SERVICE) + { + /* 0xFF is valid for a card removal */ + if(interrupts!=0xFF) + printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n", + dev->name, interrupts); + ei_outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ + } else { + printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts); + ei_outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ + } + } + spin_unlock(&ei_local->page_lock); + return IRQ_RETVAL(nr_serviced > 0); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void __ei_poll(struct net_device *dev) +{ + disable_irq_lockdep(dev->irq); + __ei_interrupt(dev->irq, dev); + enable_irq_lockdep(dev->irq); +} +#endif + +/** + * ei_tx_err - handle transmitter error + * @dev: network device which threw the exception + * + * A transmitter error has happened. Most likely excess collisions (which + * is a fairly normal condition). If the error is one where the Tx will + * have been aborted, we try and send another one right away, instead of + * letting the failed packet sit and collect dust in the Tx buffer. This + * is a much better solution as it avoids kernel based Tx timeouts, and + * an unnecessary card reset. + * + * Called with lock held. + */ + +static void ei_tx_err(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + unsigned char txsr = ei_inb_p(e8390_base+EN0_TSR); + unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); + +#ifdef VERBOSE_ERROR_DUMP + printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); + if (txsr & ENTSR_ABT) + printk("excess-collisions "); + if (txsr & ENTSR_ND) + printk("non-deferral "); + if (txsr & ENTSR_CRS) + printk("lost-carrier "); + if (txsr & ENTSR_FU) + printk("FIFO-underrun "); + if (txsr & ENTSR_CDH) + printk("lost-heartbeat "); + printk("\n"); +#endif + + ei_outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ + + if (tx_was_aborted) + ei_tx_intr(dev); + else + { + ei_local->stat.tx_errors++; + if (txsr & ENTSR_CRS) ei_local->stat.tx_carrier_errors++; + if (txsr & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++; + if (txsr & ENTSR_OWC) ei_local->stat.tx_window_errors++; + } +} + +/** + * ei_tx_intr - transmit interrupt handler + * @dev: network device for which tx intr is handled + * + * We have finished a transmit: check for errors and then trigger the next + * packet to be sent. Called with lock held. + */ + +static void ei_tx_intr(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + int status = ei_inb(e8390_base + EN0_TSR); + + ei_outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ + + /* + * There are two Tx buffers, see which one finished, and trigger + * the send of another one if it exists. + */ + ei_local->txqueue--; + + if (ei_local->tx1 < 0) + { + if (ei_local->lasttx != 1 && ei_local->lasttx != -1) + printk(KERN_ERR "%s: bogus last_tx_buffer %d, tx1=%d.\n", + ei_local->name, ei_local->lasttx, ei_local->tx1); + ei_local->tx1 = 0; + if (ei_local->tx2 > 0) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); + dev->trans_start = jiffies; + ei_local->tx2 = -1, + ei_local->lasttx = 2; + } + else ei_local->lasttx = 20, ei_local->txing = 0; + } + else if (ei_local->tx2 < 0) + { + if (ei_local->lasttx != 2 && ei_local->lasttx != -2) + printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", + ei_local->name, ei_local->lasttx, ei_local->tx2); + ei_local->tx2 = 0; + if (ei_local->tx1 > 0) + { + ei_local->txing = 1; + NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); + dev->trans_start = jiffies; + ei_local->tx1 = -1; + ei_local->lasttx = 1; + } + else + ei_local->lasttx = 10, ei_local->txing = 0; + } +// else printk(KERN_WARNING "%s: unexpected TX-done interrupt, lasttx=%d.\n", +// dev->name, ei_local->lasttx); + + /* Minimize Tx latency: update the statistics after we restart TXing. */ + if (status & ENTSR_COL) + ei_local->stat.collisions++; + if (status & ENTSR_PTX) + ei_local->stat.tx_packets++; + else + { + ei_local->stat.tx_errors++; + if (status & ENTSR_ABT) + { + ei_local->stat.tx_aborted_errors++; + ei_local->stat.collisions += 16; + } + if (status & ENTSR_CRS) + ei_local->stat.tx_carrier_errors++; + if (status & ENTSR_FU) + ei_local->stat.tx_fifo_errors++; + if (status & ENTSR_CDH) + ei_local->stat.tx_heartbeat_errors++; + if (status & ENTSR_OWC) + ei_local->stat.tx_window_errors++; + } + netif_wake_queue(dev); +} + +/** + * ei_receive - receive some packets + * @dev: network device with which receive will be run + * + * We have a good packet(s), get it/them out of the buffers. + * Called with lock held. + */ + +static void ei_receive(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + unsigned char rxing_page, this_frame, next_frame; + unsigned short current_offset; + int rx_pkt_count = 0; + struct e8390_pkt_hdr rx_frame; + int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; + + while (++rx_pkt_count < 10) + { + int pkt_len, pkt_stat; + + /* Get the rx page (incoming packet pointer). */ + ei_outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD); + rxing_page = ei_inb_p(e8390_base + EN1_CURPAG); + ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); + + /* Remove one frame from the ring. Boundary is always a page behind. */ + this_frame = ei_inb_p(e8390_base + EN0_BOUNDARY) + 1; + if (this_frame >= ei_local->stop_page) + this_frame = ei_local->rx_start_page; + + /* Someday we'll omit the previous, iff we never get this message. + (There is at least one clone claimed to have a problem.) + + Keep quiet if it looks like a card removal. One problem here + is that some clones crash in roughly the same way. + */ + if (ei_debug > 0 && this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) + printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", + dev->name, this_frame, ei_local->current_page); + + if (this_frame == rxing_page) /* Read all the frames? */ + break; /* Done for now */ + + current_offset = this_frame << 8; + ei_get_8390_hdr(dev, &rx_frame, this_frame); + + pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr); + pkt_stat = rx_frame.status; + + next_frame = this_frame + 1 + ((pkt_len+4)>>8); + + /* Check for bogosity warned by 3c503 book: the status byte is never + written. This happened a lot during testing! This code should be + cleaned up someday. */ + if (rx_frame.next != next_frame + && rx_frame.next != next_frame + 1 + && rx_frame.next != next_frame - num_rx_pages + && rx_frame.next != next_frame + 1 - num_rx_pages) { + ei_local->current_page = rxing_page; + ei_outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY); + ei_local->stat.rx_errors++; + continue; + } + + if (pkt_len < 60 || pkt_len > 1518) + { + if (ei_debug) + printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", + dev->name, rx_frame.count, rx_frame.status, + rx_frame.next); + ei_local->stat.rx_errors++; + ei_local->stat.rx_length_errors++; + } + else if ((pkt_stat & 0x0F) == ENRSR_RXOK) + { + struct sk_buff *skb; + + skb = dev_alloc_skb(pkt_len+2); + if (skb == NULL) + { + if (ei_debug > 1) + printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", + dev->name, pkt_len); + ei_local->stat.rx_dropped++; + break; + } + else + { + skb_reserve(skb,2); /* IP headers on 16 byte boundaries */ + skb->dev = dev; + skb_put(skb, pkt_len); /* Make room */ + ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame)); + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + dev->last_rx = jiffies; + ei_local->stat.rx_packets++; + ei_local->stat.rx_bytes += pkt_len; + if (pkt_stat & ENRSR_PHY) + ei_local->stat.multicast++; + } + } + else + { + if (ei_debug) + printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", + dev->name, rx_frame.status, rx_frame.next, + rx_frame.count); + ei_local->stat.rx_errors++; + /* NB: The NIC counts CRC, frame and missed errors. */ + if (pkt_stat & ENRSR_FO) + ei_local->stat.rx_fifo_errors++; + } + next_frame = rx_frame.next; + + /* This _should_ never happen: it's here for avoiding bad clones. */ + if (next_frame >= ei_local->stop_page) { + printk("%s: next frame inconsistency, %#2x\n", dev->name, + next_frame); + next_frame = ei_local->rx_start_page; + } + ei_local->current_page = next_frame; + ei_outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); + } + + /* We used to also ack ENISR_OVER here, but that would sometimes mask + a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ + ei_outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR); + return; +} + +/** + * ei_rx_overrun - handle receiver overrun + * @dev: network device which threw exception + * + * We have a receiver overrun: we have to kick the 8390 to get it started + * again. Problem is that you have to kick it exactly as NS prescribes in + * the updated datasheets, or "the NIC may act in an unpredictable manner." + * This includes causing "the NIC to defer indefinitely when it is stopped + * on a busy network." Ugh. + * Called with lock held. Don't call this with the interrupts off or your + * computer will hate you - it takes 10ms or so. + */ + +static void ei_rx_overrun(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + unsigned char was_txing, must_resend = 0; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + + /* + * Record whether a Tx was in progress and then issue the + * stop command. + */ + was_txing = ei_inb_p(e8390_base+E8390_CMD) & E8390_TRANS; + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); + + if (ei_debug > 1) + printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); + ei_local->stat.rx_over_errors++; + + /* + * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. + * Early datasheets said to poll the reset bit, but now they say that + * it "is not a reliable indicator and subsequently should be ignored." + * We wait at least 10ms. + */ + + mdelay(10); + + /* + * Reset RBCR[01] back to zero as per magic incantation. + */ + ei_outb_p(0x00, e8390_base+EN0_RCNTLO); + ei_outb_p(0x00, e8390_base+EN0_RCNTHI); + + /* + * See if any Tx was interrupted or not. According to NS, this + * step is vital, and skipping it will cause no end of havoc. + */ + + if (was_txing) + { + unsigned char tx_completed = ei_inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); + if (!tx_completed) + must_resend = 1; + } + + /* + * Have to enter loopback mode and then restart the NIC before + * you are allowed to slurp packets up off the ring. + */ + ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); + ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); + + /* + * Clear the Rx ring of all the debris, and ack the interrupt. + */ + ei_receive(dev); + ei_outb_p(ENISR_OVER, e8390_base+EN0_ISR); + + /* + * Leave loopback mode, and resend any packet that got stopped. + */ + ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); + if (must_resend) + ei_outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); +} + +/* + * Collect the stats. This is called unlocked and from several contexts. + */ + +static struct net_device_stats *get_stats(struct net_device *dev) +{ + unsigned long ioaddr = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + unsigned long flags; + + /* If the card is stopped, just return the present stats. */ + if (!netif_running(dev)) + return &ei_local->stat; + + spin_lock_irqsave(&ei_local->page_lock,flags); + /* Read the counter registers, assuming we are in page 0. */ + ei_local->stat.rx_frame_errors += ei_inb_p(ioaddr + EN0_COUNTER0); + ei_local->stat.rx_crc_errors += ei_inb_p(ioaddr + EN0_COUNTER1); + ei_local->stat.rx_missed_errors+= ei_inb_p(ioaddr + EN0_COUNTER2); + spin_unlock_irqrestore(&ei_local->page_lock, flags); + + return &ei_local->stat; +} + +/* + * Form the 64 bit 8390 multicast table from the linked list of addresses + * associated with this dev structure. + */ + +static inline void make_mc_bits(u8 *bits, struct net_device *dev) +{ + struct dev_mc_list *dmi; + + for (dmi=dev->mc_list; dmi; dmi=dmi->next) + { + u32 crc; + if (dmi->dmi_addrlen != ETH_ALEN) + { + printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name); + continue; + } + crc = ether_crc(ETH_ALEN, dmi->dmi_addr); + /* + * The 8390 uses the 6 most significant bits of the + * CRC to index the multicast table. + */ + bits[crc>>29] |= (1<<((crc>>26)&7)); + } +} + +/** + * do_set_multicast_list - set/clear multicast filter + * @dev: net device for which multicast filter is adjusted + * + * Set or clear the multicast filter for this adaptor. May be called + * from a BH in 2.1.x. Must be called with lock held. + */ + +static void do_set_multicast_list(struct net_device *dev) +{ + unsigned long e8390_base = dev->base_addr; + int i; + struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + + if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) + { + memset(ei_local->mcfilter, 0, 8); + if (dev->mc_list) + make_mc_bits(ei_local->mcfilter, dev); + } + else + memset(ei_local->mcfilter, 0xFF, 8); /* mcast set to accept-all */ + + /* + * DP8390 manuals don't specify any magic sequence for altering + * the multicast regs on an already running card. To be safe, we + * ensure multicast mode is off prior to loading up the new hash + * table. If this proves to be not enough, we can always resort + * to stopping the NIC, loading the table and then restarting. + * + * Bug Alert! The MC regs on the SMC 83C690 (SMC Elite and SMC + * Elite16) appear to be write-only. The NS 8390 data sheet lists + * them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and + * Ultra32 EISA) appears to have this bug fixed. + */ + + if (netif_running(dev)) + ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); + ei_outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); + for(i = 0; i < 8; i++) + { + ei_outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); +#ifndef BUG_83C690 + if(ei_inb_p(e8390_base + EN1_MULT_SHIFT(i))!=ei_local->mcfilter[i]) + printk(KERN_ERR "Multicast filter read/write mismap %d\n",i); +#endif + } + ei_outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); + + if(dev->flags&IFF_PROMISC) + ei_outb_p(E8390_RXCONFIG | 0x18, e8390_base + EN0_RXCR); + else if(dev->flags&IFF_ALLMULTI || dev->mc_list) + ei_outb_p(E8390_RXCONFIG | 0x08, e8390_base + EN0_RXCR); + else + ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); + } + +/* + * Called without lock held. This is invoked from user context and may + * be parallel to just about everything else. Its also fairly quick and + * not called too often. Must protect against both bh and irq users + */ + +static void set_multicast_list(struct net_device *dev) +{ + unsigned long flags; + struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev); + + spin_lock_irqsave(&ei_local->page_lock, flags); + do_set_multicast_list(dev); + spin_unlock_irqrestore(&ei_local->page_lock, flags); +} + +/** + * ethdev_setup - init rest of 8390 device struct + * @dev: network device structure to init + * + * Initialize the rest of the 8390 device structure. Do NOT __init + * this, as it is used by 8390 based modular drivers too. + */ + +static void ethdev_setup(struct net_device *dev) +{ + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + if (ei_debug > 1) + printk(version); + + dev->hard_start_xmit = &ei_start_xmit; + dev->get_stats = get_stats; + dev->set_multicast_list = &set_multicast_list; + + ether_setup(dev); + + spin_lock_init(&ei_local->page_lock); +} + +/** + * alloc_ei_netdev - alloc_etherdev counterpart for 8390 + * @size: extra bytes to allocate + * + * Allocate 8390-specific net_device. + */ +static struct net_device *____alloc_ei_netdev(int size) +{ + return alloc_netdev(sizeof(struct ei_device) + size, "eth%d", + ethdev_setup); +} + + + + +/* This page of functions should be 8390 generic */ +/* Follow National Semi's recommendations for initializing the "NIC". */ + +/** + * NS8390_init - initialize 8390 hardware + * @dev: network device to initialize + * @startp: boolean. non-zero value to initiate chip processing + * + * Must be called with lock held. + */ + +static void __NS8390_init(struct net_device *dev, int startp) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev); + int i; + int endcfg = ei_local->word16 + ? (0x48 | ENDCFG_WTS | (ei_local->bigendian ? ENDCFG_BOS : 0)) + : 0x48; + + if(sizeof(struct e8390_pkt_hdr)!=4) + panic("8390.c: header struct mispacked\n"); + /* Follow National Semi's recommendations for initing the DP83902. */ + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ + ei_outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + ei_outb_p(0x00, e8390_base + EN0_RCNTLO); + ei_outb_p(0x00, e8390_base + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + ei_outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ + ei_outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + ei_outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); + ei_local->tx1 = ei_local->tx2 = 0; + ei_outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); + ei_outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ + ei_outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + ei_outb_p(0xFF, e8390_base + EN0_ISR); + ei_outb_p(0x00, e8390_base + EN0_IMR); + + /* Copy the station address into the DS8390 registers. */ + + ei_outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ + for(i = 0; i < 6; i++) + { + ei_outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); + if (ei_debug > 1 && ei_inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) + printk(KERN_ERR "Hw. address read/write mismap %d\n",i); + } + + ei_outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); + + netif_start_queue(dev); + ei_local->tx1 = ei_local->tx2 = 0; + ei_local->txing = 0; + + if (startp) + { + ei_outb_p(0xff, e8390_base + EN0_ISR); + ei_outb_p(ENISR_ALL, e8390_base + EN0_IMR); + ei_outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); + ei_outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ + /* 3c503 TechMan says rxconfig only after the NIC is started. */ + ei_outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ + do_set_multicast_list(dev); /* (re)load the mcast table */ + } +} + +/* Trigger a transmit start, assuming the length is valid. + Always called with the page lock held */ + +static void NS8390_trigger_send(struct net_device *dev, unsigned int length, + int start_page) +{ + unsigned long e8390_base = dev->base_addr; + struct ei_device *ei_local __attribute((unused)) = (struct ei_device *) netdev_priv(dev); + + ei_outb_p(E8390_NODMA+E8390_PAGE0, e8390_base+E8390_CMD); + + if (ei_inb_p(e8390_base + E8390_CMD) & E8390_TRANS) + { + printk(KERN_WARNING "%s: trigger_send() called with the transmitter busy.\n", + dev->name); + return; + } + ei_outb_p(length & 0xff, e8390_base + EN0_TCNTLO); + ei_outb_p(length >> 8, e8390_base + EN0_TCNTHI); + ei_outb_p(start_page, e8390_base + EN0_TPSR); + ei_outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); +} -- cgit v1.2.3 From 8c6270f957f0eaa343e4a609159c4b85038468d6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 10 Oct 2006 00:19:36 +0100 Subject: [PATCH] 8390 fixes - m68k oddballs more 8390 conversions - mac8390, zorro8390 and hydra got the same treatment as arm etherh; one more case in 8390.h ifdef cascade is gone. Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/net/8390.h | 16 +--------------- drivers/net/Makefile | 6 +++--- drivers/net/hydra.c | 23 ++++++++++++++++------- drivers/net/mac8390.c | 26 ++++++++++++++++---------- drivers/net/zorro8390.c | 24 ++++++++++++++++-------- 5 files changed, 52 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/net/8390.h b/drivers/net/8390.h index fae4aa92c4b7..b8991fc7923f 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -107,21 +107,7 @@ struct ei_device { * - removed AMIGA_PCMCIA from this list, handled as ISA io now */ -#if defined(CONFIG_MAC) || \ - defined(CONFIG_ZORRO8390) || defined(CONFIG_ZORRO8390_MODULE) || \ - defined(CONFIG_HYDRA) || defined(CONFIG_HYDRA_MODULE) -#define EI_SHIFT(x) (ei_local->reg_offset[x]) -#undef inb -#undef inb_p -#undef outb -#undef outb_p - -#define ei_inb(port) in_8(port) -#define ei_outb(val,port) out_8(port,val) -#define ei_inb_p(port) in_8(port) -#define ei_outb_p(val,port) out_8(port,val) - -#elif defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) +#if defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) #define EI_SHIFT(x) (ei_local->reg_offset[x]) #endif diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 53ccc337099c..42bf31ea80c6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -82,7 +82,7 @@ obj-$(CONFIG_HAMACHI) += hamachi.o obj-$(CONFIG_NET) += Space.o loopback.o obj-$(CONFIG_SEEQ8005) += seeq8005.o obj-$(CONFIG_NET_SB1000) += sb1000.o -obj-$(CONFIG_MAC8390) += mac8390.o 8390.o +obj-$(CONFIG_MAC8390) += mac8390.o obj-$(CONFIG_APNE) += apne.o 8390.o obj-$(CONFIG_PCMCIA_PCNET) += 8390.o obj-$(CONFIG_SHAPER) += shaper.o @@ -164,7 +164,7 @@ obj-$(CONFIG_BVME6000_NET) += 82596.o obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_ETH16I) += eth16i.o -obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o +obj-$(CONFIG_ZORRO8390) += zorro8390.o obj-$(CONFIG_HPLANCE) += hplance.o 7990.o obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o obj-$(CONFIG_EQUALIZER) += eql.o @@ -177,7 +177,7 @@ obj-$(CONFIG_ATARILANCE) += atarilance.o obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o obj-$(CONFIG_A2065) += a2065.o -obj-$(CONFIG_HYDRA) += hydra.o 8390.o +obj-$(CONFIG_HYDRA) += hydra.o obj-$(CONFIG_ARIADNE) += ariadne.o obj-$(CONFIG_CS89x0) += cs89x0.o obj-$(CONFIG_MACSONIC) += macsonic.o diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 91326ea3e12b..f970bfbb9db2 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c @@ -31,7 +31,16 @@ #include #include -#include "8390.h" +#define EI_SHIFT(x) (ei_local->reg_offset[x]) +#define ei_inb(port) in_8(port) +#define ei_outb(val,port) out_8(port,val) +#define ei_inb_p(port) in_8(port) +#define ei_outb_p(val,port) out_8(port,val) + +static const char version[] = + "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + +#include "lib8390.c" #define NE_EN0_DCFG (0x0e*2) @@ -100,7 +109,7 @@ static int __devinit hydra_init(struct zorro_dev *z) 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, }; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); @@ -117,7 +126,7 @@ static int __devinit hydra_init(struct zorro_dev *z) dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, IRQF_SHARED, "Hydra Ethernet", + if (request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, "Hydra Ethernet", dev)) { free_netdev(dev); return -EAGAIN; @@ -139,10 +148,10 @@ static int __devinit hydra_init(struct zorro_dev *z) dev->open = &hydra_open; dev->stop = &hydra_close; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; + dev->poll_controller = __ei_poll; #endif - NS8390_init(dev, 0); + __NS8390_init(dev, 0); err = register_netdev(dev); if (err) { @@ -164,7 +173,7 @@ static int __devinit hydra_init(struct zorro_dev *z) static int hydra_open(struct net_device *dev) { - ei_open(dev); + __ei_open(dev); return 0; } @@ -172,7 +181,7 @@ static int hydra_close(struct net_device *dev) { if (ei_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); + __ei_close(dev); return 0; } diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index ade6ff852e1a..a12bb64e3694 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -39,7 +39,16 @@ #include #include -#include "8390.h" +static char version[] = + "mac8390.c: v0.4 2001-05-15 David Huggins-Daines and others\n"; + +#define EI_SHIFT(x) (ei_local->reg_offset[x]) +#define ei_inb(port) in_8(port) +#define ei_outb(val,port) out_8(port,val) +#define ei_inb_p(port) in_8(port) +#define ei_outb_p(val,port) out_8(port,val) + +#include "lib8390.c" #define WD_START_PG 0x00 /* First page of TX buffer */ #define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */ @@ -116,9 +125,6 @@ static int useresources[] = { 1, /* dayna-lc */ }; -static char version[] __initdata = - "mac8390.c: v0.4 2001-05-15 David Huggins-Daines and others\n"; - extern enum mac8390_type mac8390_ident(struct nubus_dev * dev); extern int mac8390_memsize(unsigned long membase); extern int mac8390_memtest(struct net_device * dev); @@ -237,7 +243,7 @@ struct net_device * __init mac8390_probe(int unit) if (!MACH_IS_MAC) return ERR_PTR(-ENODEV); - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return ERR_PTR(-ENOMEM); @@ -438,7 +444,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd dev->open = &mac8390_open; dev->stop = &mac8390_close; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; + dev->poll_controller = __ei_poll; #endif /* GAR, ei_status is actually a macro even though it looks global */ @@ -510,7 +516,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd return -ENODEV; } - NS8390_init(dev, 0); + __NS8390_init(dev, 0); /* Good, done, now spit out some messages */ printk(KERN_INFO "%s: %s in slot %X (type %s)\n", @@ -532,8 +538,8 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd static int mac8390_open(struct net_device *dev) { - ei_open(dev); - if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) { + __ei_open(dev); + if (request_irq(dev->irq, __ei_interrupt, 0, "8390 Ethernet", dev)) { printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } @@ -543,7 +549,7 @@ static int mac8390_open(struct net_device *dev) static int mac8390_close(struct net_device *dev) { free_irq(dev->irq, dev); - ei_close(dev); + __ei_close(dev); return 0; } diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index df04e050c647..d85e2ea0b6af 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c @@ -34,8 +34,16 @@ #include #include -#include "8390.h" +#define EI_SHIFT(x) (ei_local->reg_offset[x]) +#define ei_inb(port) in_8(port) +#define ei_outb(val,port) out_8(port,val) +#define ei_inb_p(port) in_8(port) +#define ei_outb_p(val,port) out_8(port,val) +static const char version[] = + "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + +#include "lib8390.c" #define DRV_NAME "zorro8390" @@ -114,7 +122,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z, break; board = z->resource.start; ioaddr = board+cards[i].offset; - dev = alloc_ei_netdev(); + dev = ____alloc_ei_netdev(0); if (!dev) return -ENOMEM; SET_MODULE_OWNER(dev); @@ -201,7 +209,7 @@ static int __devinit zorro8390_init(struct net_device *dev, dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, IRQF_SHARED, DRV_NAME, dev); + i = request_irq(IRQ_AMIGA_PORTS, __ei_interrupt, IRQF_SHARED, DRV_NAME, dev); if (i) return i; for(i = 0; i < ETHER_ADDR_LEN; i++) { @@ -226,10 +234,10 @@ static int __devinit zorro8390_init(struct net_device *dev, dev->open = &zorro8390_open; dev->stop = &zorro8390_close; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; + dev->poll_controller = __ei_poll; #endif - NS8390_init(dev, 0); + __NS8390_init(dev, 0); err = register_netdev(dev); if (err) { free_irq(IRQ_AMIGA_PORTS, dev); @@ -246,7 +254,7 @@ static int __devinit zorro8390_init(struct net_device *dev, static int zorro8390_open(struct net_device *dev) { - ei_open(dev); + __ei_open(dev); return 0; } @@ -254,7 +262,7 @@ static int zorro8390_close(struct net_device *dev) { if (ei_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); + __ei_close(dev); return 0; } @@ -405,7 +413,7 @@ static void zorro8390_block_output(struct net_device *dev, int count, printk(KERN_ERR "%s: timeout waiting for Tx RDC.\n", dev->name); zorro8390_reset_8390(dev); - NS8390_init(dev,1); + __NS8390_init(dev,1); break; } -- cgit v1.2.3 From b936889c8f95b601d3ef6caac6ac653a8adb4fec Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 10 Oct 2006 00:19:36 +0100 Subject: [PATCH] 8390 cleanup - etherh iomem annotations Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/net/arm/etherh.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c index 747a71f5dd0e..f3faa4fe58e7 100644 --- a/drivers/net/arm/etherh.c +++ b/drivers/net/arm/etherh.c @@ -54,10 +54,10 @@ #define EI_SHIFT(x) (ei_local->reg_offset[x]) -#define ei_inb(_p) readb(_p) -#define ei_outb(_v,_p) writeb(_v,_p) -#define ei_inb_p(_p) readb(_p) -#define ei_outb_p(_v,_p) writeb(_v,_p) +#define ei_inb(_p) readb((void __iomem *)_p) +#define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p) +#define ei_inb_p(_p) readb((void __iomem *)_p) +#define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p) #define NET_DEBUG 0 #define DEBUG_INIT 2 @@ -184,7 +184,7 @@ etherh_setif(struct net_device *dev) switch (etherh_priv(dev)->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - addr = (void *)dev->base_addr + EN0_RCNTHI; + addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; switch (dev->if_port) { case IF_PORT_10BASE2: @@ -225,7 +225,7 @@ etherh_getifstat(struct net_device *dev) switch (etherh_priv(dev)->id) { case PROD_I3_ETHERLAN600: case PROD_I3_ETHERLAN600A: - addr = (void *)dev->base_addr + EN0_RCNTHI; + addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; switch (dev->if_port) { case IF_PORT_10BASE2: stat = 1; @@ -288,7 +288,7 @@ static void etherh_reset(struct net_device *dev) { struct ei_device *ei_local = netdev_priv(dev); - void __iomem *addr = (void *)dev->base_addr; + void __iomem *addr = (void __iomem *)dev->base_addr; writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr); @@ -334,7 +334,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf ei_local->dmaing = 1; - addr = (void *)dev->base_addr; + addr = (void __iomem *)dev->base_addr; dma_base = etherh_priv(dev)->dma_base; count = (count + 1) & ~1; @@ -394,7 +394,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ei_local->dmaing = 1; - addr = (void *)dev->base_addr; + addr = (void __iomem *)dev->base_addr; dma_base = etherh_priv(dev)->dma_base; buf = skb->data; @@ -434,7 +434,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p ei_local->dmaing = 1; - addr = (void *)dev->base_addr; + addr = (void __iomem *)dev->base_addr; dma_base = etherh_priv(dev)->dma_base; writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); -- cgit v1.2.3 From 3470cb1d4fb27572273079e7095734ac4f9caa43 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 10 Oct 2006 00:19:36 +0100 Subject: [PATCH] 8390 fixes - the final chunk (h8300) The rest of 8390 conversions; ifdef cascade in 8390.h is gone now. Signed-off-by: Al Viro Signed-off-by: Jeff Garzik --- drivers/net/8390.h | 4 ---- drivers/net/Makefile | 2 +- drivers/net/ne-h8300.c | 23 +++++++++++++++-------- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/8390.h b/drivers/net/8390.h index b8991fc7923f..414de5bd228f 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -107,10 +107,6 @@ struct ei_device { * - removed AMIGA_PCMCIA from this list, handled as ISA io now */ -#if defined(CONFIG_NE_H8300) || defined(CONFIG_NE_H8300_MODULE) -#define EI_SHIFT(x) (ei_local->reg_offset[x]) -#endif - #ifndef ei_inb #define ei_inb(_p) inb(_p) #define ei_outb(_v,_p) outb(_v,_p) diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 42bf31ea80c6..7d3618424288 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -106,7 +106,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o obj-$(CONFIG_NET_SB1250_MAC) += sb1250-mac.o obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o -obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o +obj-$(CONFIG_NE_H8300) += ne-h8300.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c index eb893d7e8834..38fd525f0f13 100644 --- a/drivers/net/ne-h8300.c +++ b/drivers/net/ne-h8300.c @@ -33,6 +33,8 @@ static const char version1[] = #include #include +#define EI_SHIFT(x) (ei_local->reg_offset[x]) + #include "8390.h" #define DRV_NAME "ne-h8300" @@ -52,6 +54,11 @@ static const char version1[] = /* ---- No user-serviceable parts below ---- */ +static const char version[] = + "8390.c:v1.10cvs 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; + +#include "lib8390.c" + #define NE_BASE (dev->base_addr) #define NE_CMD 0x00 #define NE_DATAPORT (ei_status.word16?0x20:0x10) /* NatSemi-defined port window offset. */ @@ -162,7 +169,7 @@ static void cleanup_card(struct net_device *dev) #ifndef MODULE struct net_device * __init ne_probe(int unit) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); int err; if (!dev) @@ -283,7 +290,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); + ret = request_irq(dev->irq, __ei_interrupt, 0, name, dev); if (ret) { printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); goto err_out; @@ -318,9 +325,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr) dev->open = &ne_open; dev->stop = &ne_close; #ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = ei_poll; + dev->poll_controller = __ei_poll; #endif - NS8390_init(dev, 0); + __NS8390_init(dev, 0); ret = register_netdev(dev); if (ret) @@ -335,7 +342,7 @@ err_out: static int ne_open(struct net_device *dev) { - ei_open(dev); + __ei_open(dev); return 0; } @@ -343,7 +350,7 @@ static int ne_close(struct net_device *dev) { if (ei_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - ei_close(dev); + __ei_close(dev); return 0; } @@ -584,7 +591,7 @@ retry: if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne_reset_8390(dev); - NS8390_init(dev,1); + __NS8390_init(dev,1); break; } @@ -620,7 +627,7 @@ int init_module(void) int err; for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { - struct net_device *dev = alloc_ei_netdev(); + struct net_device *dev = ____alloc_ei_netdev(0); if (!dev) break; if (io[this_dev]) { -- cgit v1.2.3 From f04e2be7d9b73a1da7be99a08b3695074e14970c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Mon, 25 Sep 2006 15:33:20 -0500 Subject: [PATCH] bcm43xx: output proper link quality with scans The bcm43xx-softmac driver fails to set two quantities needed for iwlist to compute wireless quality when scanning. As a result, userland programs using the quality to determine the best connection fail. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 3 +++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 2 ++ drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 3 --- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index d6a8bf09878e..5f43d7f42af1 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -365,6 +365,9 @@ #define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7 #define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4 +/* FIXME: the next line is a guess as to what the maximum RSSI value might be */ +#define RX_RSSI_MAX 60 + /* Max size of a security key */ #define BCM43xx_SEC_KEYSIZE 16 /* Security algorithms. */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index a1b783813d8e..2ffc0d5b54ee 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3688,6 +3688,8 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) phy_type); return -ENODEV; }; + bcm->ieee->perfect_rssi = RX_RSSI_MAX; + bcm->ieee->worst_rssi = 0; if (!phy_rev_ok) { printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", phy_rev); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index d27016f8c736..12043f8be1bf 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -47,9 +47,6 @@ #define BCM43xx_WX_VERSION 18 #define MAX_WX_STRING 80 -/* FIXME: the next line is a guess as to what the maximum RSSI value might be */ -#define RX_RSSI_MAX 60 - static int bcm43xx_wx_get_name(struct net_device *net_dev, struct iw_request_info *info, -- cgit v1.2.3 From f2423723d70298e04179f934ff17346c3e06f408 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 26 Sep 2006 04:04:38 +0100 Subject: [PATCH] zd1211rw: Add 3 more device IDs iNexQ UR055g: Tested by Todor T Zviskov zd1211 chip 1435:0711 v4330 high 00-10-a7 AL2230_RF pa0 g-- ZyXEL AG-225, FCC ID SI5WUB410: Tested by Nathan zd1211 chip 0586:3409 v4810 full 00-13-49 AL7230B_RF pa0 g--- Yakumo QuickWLAN USB: Tested by EdB zd1211 chip 0b3b:1630 v4330 high 00-01-36 RF2959_RF pa0 --- Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index a15b09549245..435e16e137b3 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -47,6 +47,9 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3 From c9308b06c049a107edfbd4e5271771564eb6024d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 27 Sep 2006 03:50:31 +0100 Subject: [PATCH] ieee80211: Move IV/ICV stripping into ieee80211_rx This patch adds a host_strip_iv_icv flag to ieee80211 which indicates that ieee80211_rx should strip the IV/ICV/other security features from the payload. This saves on some memmove() calls in the driver and seems like something that belongs in the stack as it can be used by bcm43xx, ipw2200, and zd1211rw I will submit the ipw2200 patch separately as it needs testing. This patch also adds some sensible variable reuse (idx vs keyidx) in ieee80211_rx Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1 + drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 19 ---------- include/net/ieee80211.h | 4 +++ net/ieee80211/ieee80211_rx.c | 56 +++++++++++++++++++++++++---- 4 files changed, 55 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c index 12043f8be1bf..a659442b9c15 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c @@ -690,6 +690,7 @@ static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, bcm->ieee->host_encrypt = !!on; bcm->ieee->host_decrypt = !!on; bcm->ieee->host_build_iv = !on; + bcm->ieee->host_strip_iv_icv = !on; spin_unlock_irqrestore(&bcm->irq_lock, flags); mutex_unlock(&bcm->mutex); diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index 0159e4e93201..a957bc861382 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -543,25 +543,6 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, break; } - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - if ((frame_ctl & IEEE80211_FCTL_PROTECTED) && !bcm->ieee->host_decrypt) { - frame_ctl &= ~IEEE80211_FCTL_PROTECTED; - wlhdr->frame_ctl = cpu_to_le16(frame_ctl); - /* trim IV and ICV */ - /* FIXME: this must be done only for WEP encrypted packets */ - if (skb->len < 32) { - dprintkl(KERN_ERR PFX "RX packet dropped (PROTECTED flag " - "set and length < 32)\n"); - return -EINVAL; - } else { - memmove(skb->data + 4, skb->data, 24); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - stats.len -= 8; - } - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - } - switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); diff --git a/include/net/ieee80211.h b/include/net/ieee80211.h index b174ebb277a9..cb255432e4e4 100644 --- a/include/net/ieee80211.h +++ b/include/net/ieee80211.h @@ -1037,6 +1037,10 @@ struct ieee80211_device { /* host performs multicast decryption */ int host_mc_decrypt; + /* host should strip IV and ICV from protected frames */ + /* meaningful only when hardware decryption is being used */ + int host_strip_iv_icv; + int host_open_frag; int host_build_iv; int ieee802_1x; /* is IEEE 802.1X used */ diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c index 2759312a4204..d9265195656d 100644 --- a/net/ieee80211/ieee80211_rx.c +++ b/net/ieee80211/ieee80211_rx.c @@ -415,17 +415,16 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, ieee->host_mc_decrypt : ieee->host_decrypt; if (can_be_decrypted) { - int idx = 0; if (skb->len >= hdrlen + 3) { /* Top two-bits of byte 3 are the key index */ - idx = skb->data[hdrlen + 3] >> 6; + keyidx = skb->data[hdrlen + 3] >> 6; } - /* ieee->crypt[] is WEP_KEY (4) in length. Given that idx - * is only allowed 2-bits of storage, no value of idx can - * be provided via above code that would result in idx + /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx + * is only allowed 2-bits of storage, no value of keyidx can + * be provided via above code that would result in keyidx * being out of range */ - crypt = ieee->crypt[idx]; + crypt = ieee->crypt[keyidx]; #ifdef NOT_YET sta = NULL; @@ -655,6 +654,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb, goto rx_dropped; } + /* If the frame was decrypted in hardware, we may need to strip off + * any security data (IV, ICV, etc) that was left behind */ + if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && + ieee->host_strip_iv_icv) { + int trimlen = 0; + + /* Top two-bits of byte 3 are the key index */ + if (skb->len >= hdrlen + 3) + keyidx = skb->data[hdrlen + 3] >> 6; + + /* To strip off any security data which appears before the + * payload, we simply increase hdrlen (as the header gets + * chopped off immediately below). For the security data which + * appears after the payload, we use skb_trim. */ + + switch (ieee->sec.encode_alg[keyidx]) { + case SEC_ALG_WEP: + /* 4 byte IV */ + hdrlen += 4; + /* 4 byte ICV */ + trimlen = 4; + break; + case SEC_ALG_TKIP: + /* 4 byte IV, 4 byte ExtIV */ + hdrlen += 8; + /* 8 byte MIC, 4 byte ICV */ + trimlen = 12; + break; + case SEC_ALG_CCMP: + /* 8 byte CCMP header */ + hdrlen += 8; + /* 8 byte MIC */ + trimlen = 8; + break; + } + + if (skb->len < trimlen) + goto rx_dropped; + + __skb_trim(skb, skb->len - trimlen); + + if (skb->len < hdrlen) + goto rx_dropped; + } + /* skb: hdr + (possible reassembled) full plaintext payload */ payload = skb->data + hdrlen; -- cgit v1.2.3 From 00a5ebf8621e8098305ca5e7b319937eed430184 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 8 Oct 2006 00:14:28 -0400 Subject: [PATCH] atmel: save on array initialization NET: atmel - do not initialize array over and over again Signed-off-by: Dmitry Torokhov Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 0c07b8b7250d..3a6397ffda50 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -784,11 +784,11 @@ static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, static int start_tx(struct sk_buff *skb, struct net_device *dev) { + static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; struct atmel_private *priv = netdev_priv(dev); struct ieee80211_hdr_4addr header; unsigned long flags; u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - u8 SNAP_RFC1024[6] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; if (priv->card && priv->present_callback && !(*priv->present_callback)(priv->card)) { -- cgit v1.2.3 From b4341135794fdad85f995a378da424e4f4128e4d Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 8 Oct 2006 00:14:29 -0400 Subject: [PATCH] atmel: use ARRAY_SIZE() NET: atmel - switch to using ARRAY_SIZE() Signed-off-by: Dmitry Torokhov Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 3a6397ffda50..c253e9aad104 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1193,7 +1193,7 @@ static irqreturn_t service_interrupt(int irq, void *dev_id) atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */ - for (i = 0; i < sizeof(irq_order)/sizeof(u8); i++) + for (i = 0; i < ARRAY_SIZE(irq_order); i++) if (isr & irq_order[i]) break; @@ -1345,10 +1345,10 @@ int atmel_open(struct net_device *dev) atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain); } else { priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS); - for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) + for (i = 0; i < ARRAY_SIZE(channel_table); i++) if (priv->reg_domain == channel_table[i].reg_domain) break; - if (i == sizeof(channel_table)/sizeof(channel_table[0])) { + if (i == ARRAY_SIZE(channel_table)) { priv->reg_domain = REG_DOMAIN_MKK1; printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name); } @@ -1393,7 +1393,7 @@ static int atmel_validate_channel(struct atmel_private *priv, int channel) else return suitable default channel */ int i; - for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) + for (i = 0; i < ARRAY_SIZE(channel_table); i++) if (priv->reg_domain == channel_table[i].reg_domain) { if (channel >= channel_table[i].min && channel <= channel_table[i].max) @@ -1437,7 +1437,7 @@ static int atmel_proc_output (char *buf, struct atmel_private *priv) } r = ""; - for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) + for (i = 0; i < ARRAY_SIZE(channel_table); i++) if (priv->reg_domain == channel_table[i].reg_domain) r = channel_table[i].name; @@ -2373,7 +2373,7 @@ static int atmel_get_range(struct net_device *dev, range->min_nwid = 0x0000; range->max_nwid = 0x0000; range->num_channels = 0; - for (j = 0; j < sizeof(channel_table)/sizeof(channel_table[0]); j++) + for (j = 0; j < ARRAY_SIZE(channel_table); j++) if (priv->reg_domain == channel_table[j].reg_domain) { range->num_channels = channel_table[j].max - channel_table[j].min + 1; break; @@ -2579,9 +2579,9 @@ static const struct iw_priv_args atmel_private_args[] = { static const struct iw_handler_def atmel_handler_def = { - .num_standard = sizeof(atmel_handler)/sizeof(iw_handler), - .num_private = sizeof(atmel_private_handler)/sizeof(iw_handler), - .num_private_args = sizeof(atmel_private_args)/sizeof(struct iw_priv_args), + .num_standard = ARRAY_SIZE(atmel_handler), + .num_private = ARRAY_SIZE(atmel_private_handler), + .num_private_args = ARRAY_SIZE(atmel_private_args), .standard = (iw_handler *) atmel_handler, .private = (iw_handler *) atmel_private_handler, .private_args = (struct iw_priv_args *) atmel_private_args, @@ -2645,7 +2645,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) domain[REGDOMAINSZ] = 0; rc = -EINVAL; - for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) { + for (i = 0; i < ARRAY_SIZE(channel_table); i++) { /* strcasecmp doesn't exist in the library */ char *a = channel_table[i].name; char *b = domain; -- cgit v1.2.3 From 5c877fe58c5df19646204b144b978b99c2ef074f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 8 Oct 2006 00:14:30 -0400 Subject: [PATCH] atmel: whitespace cleanup NET: atmel: whitespace cleanup Signed-off-by: Dmitry Torokhov Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 6 ++-- drivers/net/wireless/atmel_cs.c | 74 ++++++++++++++++++++-------------------- drivers/net/wireless/atmel_pci.c | 10 +++--- 3 files changed, 45 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index c253e9aad104..74c800f6caf8 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -595,7 +595,7 @@ static void atmel_join_bss(struct atmel_private *priv, int bss_index); static void atmel_smooth_qual(struct atmel_private *priv); static void atmel_writeAR(struct net_device *dev, u16 data); static int probe_atmel_card(struct net_device *dev); -static int reset_atmel_card(struct net_device *dev ); +static int reset_atmel_card(struct net_device *dev); static void atmel_enter_state(struct atmel_private *priv, int new_state); int atmel_open (struct net_device *dev); @@ -1736,7 +1736,7 @@ static int atmel_set_encode(struct net_device *dev, /* Disable the key */ priv->wep_key_len[index] = 0; /* Check if the key is not marked as invalid */ - if(!(dwrq->flags & IW_ENCODE_NOKEY)) { + if (!(dwrq->flags & IW_ENCODE_NOKEY)) { /* Cleanup */ memset(priv->wep_keys[index], 0, 13); /* Copy the key in the driver */ @@ -1907,7 +1907,7 @@ static int atmel_get_encodeext(struct net_device *dev, encoding->flags = idx + 1; memset(ext, 0, sizeof(*ext)); - + if (!priv->wep_is_on) { ext->alg = IW_ENCODE_ALG_NONE; ext->key_len = 0; diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 785664090bb4..5c410989c4d7 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -5,12 +5,12 @@ Copyright 2000-2001 ATMEL Corporation. Copyright 2003 Simon Kelley. - This code was developed from version 2.1.1 of the Atmel drivers, - released by Atmel corp. under the GPL in December 2002. It also - includes code from the Linux aironet drivers (C) Benjamin Reed, - and the Linux PCMCIA package, (C) David Hinds. + This code was developed from version 2.1.1 of the Atmel drivers, + released by Atmel corp. under the GPL in December 2002. It also + includes code from the Linux aironet drivers (C) Benjamin Reed, + and the Linux PCMCIA package, (C) David Hinds. - For all queries about this code, please contact the current author, + For all queries about this code, please contact the current author, Simon Kelley and not Atmel Corporation. This program is free software; you can redistribute it and/or modify @@ -87,7 +87,7 @@ MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); event is received. The config() and release() entry points are used to configure or release a socket, in response to card insertion and ejection events. They are invoked from the atmel_cs - event handler. + event handler. */ static int atmel_config(struct pcmcia_device *link); @@ -133,22 +133,22 @@ static void atmel_detach(struct pcmcia_device *p_dev); device IO routines can use a flag like this to throttle IO to a card that is not ready to accept it. */ - + typedef struct local_info_t { dev_node_t node; struct net_device *eth_dev; } local_info_t; /*====================================================================== - + atmel_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. - + The dev_link structure is initialized, but we don't actually configure the card at this point -- we wait until we receive a card insertion event. - + ======================================================================*/ static int atmel_probe(struct pcmcia_device *p_dev) @@ -184,12 +184,12 @@ static int atmel_probe(struct pcmcia_device *p_dev) } /* atmel_attach */ /*====================================================================== - + This deletes a driver "instance". The device is de-registered with Card Services. If it has been released, all local data structures are freed. Otherwise, the structures will be freed when the device is released. - + ======================================================================*/ static void atmel_detach(struct pcmcia_device *link) @@ -202,11 +202,11 @@ static void atmel_detach(struct pcmcia_device *link) } /*====================================================================== - + atmel_config() is scheduled to run after a CARD_INSERTION event is received, to configure the PCMCIA socket, and to make the device available to the system. - + ======================================================================*/ #define CS_CHECK(fn, ret) \ @@ -237,12 +237,12 @@ static int atmel_config(struct pcmcia_device *link) did = handle_to_dev(link).driver_data; DEBUG(0, "atmel_config(0x%p)\n", link); - + tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = sizeof(buf); tuple.TupleOffset = 0; - + /* This reads the card's CONFIG tuple to find its configuration registers. @@ -258,7 +258,7 @@ static int atmel_config(struct pcmcia_device *link) In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including voltage, IO window, memory window, and interrupt settings. - + We make no assumptions about the card to be configured: we use just the information available in the CIS. In an ideal world, this would work for any PCMCIA card, but it requires a complete @@ -274,17 +274,17 @@ static int atmel_config(struct pcmcia_device *link) if (pcmcia_get_tuple_data(link, &tuple) != 0 || pcmcia_parse_tuple(link, &tuple, &parse) != 0) goto next_entry; - + if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; if (cfg->index == 0) goto next_entry; link->conf.ConfigIndex = cfg->index; - + /* Does this card need audio output? */ if (cfg->flags & CISTPL_CFTABLE_AUDIO) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; } - + /* Use power settings for Vcc and Vpp if present */ /* Note that the CIS values need to be rescaled */ if (cfg->vpp1.present & (1<conf.Vpp = dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - + /* Do we need to allocate an interrupt? */ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) link->conf.Attributes |= CONF_ENABLE_IRQ; - + /* IO window settings */ link->io.NumPorts1 = link->io.NumPorts2 = 0; if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { @@ -315,18 +315,18 @@ static int atmel_config(struct pcmcia_device *link) link->io.NumPorts2 = io->win[1].len; } } - + /* This reserves IO space but doesn't actually enable it */ if (pcmcia_request_io(link, &link->io) != 0) goto next_entry; /* If we got this far, we're cool! */ break; - + next_entry: CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); } - + /* Allocate an interrupt line. Note that this does not assign a handler to the interrupt, unless the 'Handler' member of the @@ -334,31 +334,31 @@ static int atmel_config(struct pcmcia_device *link) */ if (link->conf.Attributes & CONF_ENABLE_IRQ) CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - + /* This actually configures the PCMCIA socket -- setting up the I/O windows and the interrupt mapping, and putting the card and host interface into "Memory and IO" mode. */ CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - + if (link->irq.AssignedIRQ == 0) { - printk(KERN_ALERT + printk(KERN_ALERT "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config."); goto cs_failed; } - - ((local_info_t*)link->priv)->eth_dev = + + ((local_info_t*)link->priv)->eth_dev = init_atmel_card(link->irq.AssignedIRQ, link->io.BasePort1, did ? did->driver_info : ATMEL_FW_TYPE_NONE, &handle_to_dev(link), - card_present, + card_present, link); - if (!((local_info_t*)link->priv)->eth_dev) + if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed; - - + + /* At this point, the dev_node_t structure(s) need to be initialized and arranged in a linked list at link->dev_node. @@ -376,11 +376,11 @@ static int atmel_config(struct pcmcia_device *link) } /*====================================================================== - + After a card is removed, atmel_release() will unregister the device, and release the PCMCIA configuration. If the device is still open, this will be postponed until it is closed. - + ======================================================================*/ static void atmel_release(struct pcmcia_device *link) @@ -517,7 +517,7 @@ static void atmel_cs_cleanup(void) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. + POSSIBILITY OF SUCH DAMAGE. */ module_init(atmel_cs_init); diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c index 3bfa791c323d..92f87fbe750f 100644 --- a/drivers/net/wireless/atmel_pci.c +++ b/drivers/net/wireless/atmel_pci.c @@ -53,18 +53,18 @@ static int __devinit atmel_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pent) { struct net_device *dev; - + if (pci_enable_device(pdev)) return -ENODEV; - + pci_set_master(pdev); - - dev = init_atmel_card(pdev->irq, pdev->resource[1].start, + + dev = init_atmel_card(pdev->irq, pdev->resource[1].start, ATMEL_FW_TYPE_506, &pdev->dev, NULL, NULL); if (!dev) return -ENODEV; - + pci_set_drvdata(pdev, dev); return 0; } -- cgit v1.2.3 From d18e0c4a5434f02586b5fdcbcc72f1fe61ab49e6 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 8 Oct 2006 00:38:14 -0400 Subject: [PATCH] prism54: fix potential race in reset scheduling NET: prism54 - fix potential race in reset scheduling There appears to be a race in reset scheduling logic - thread responsible for reseting the interface should clear "reset pending" flag before restarting the queue, otherwise timeout handler might not schedule another reset even if it is needed. This race is mostly theoretical as far as I can see but a race nonetheless. Signed-off-by: Dmitry Torokhov Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_eth.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index a8261d8454dd..bfbafe99b94a 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -253,6 +253,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) * header and without the FCS. But there a is a bit that * indicates if the packet is corrupted :-) */ struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data; + if (hdr->flags & 0x01) /* This one is bad. Drop it ! */ return -1; @@ -464,10 +465,8 @@ islpci_eth_receive(islpci_private *priv) break; } /* update the fragment address */ - control_block->rx_data_low[index].address = cpu_to_le32((u32) - priv-> - pci_map_rx_address - [index]); + control_block->rx_data_low[index].address = + cpu_to_le32((u32)priv->pci_map_rx_address[index]); wmb(); /* increment the driver read pointer */ @@ -484,10 +483,12 @@ islpci_eth_receive(islpci_private *priv) void islpci_do_reset_and_wake(void *data) { - islpci_private *priv = (islpci_private *) data; + islpci_private *priv = data; + islpci_reset(priv, 1); - netif_wake_queue(priv->ndev); priv->reset_task_pending = 0; + smp_wmb(); + netif_wake_queue(priv->ndev); } void @@ -499,12 +500,14 @@ islpci_eth_tx_timeout(struct net_device *ndev) /* increment the transmit error counter */ statistics->tx_errors++; - printk(KERN_WARNING "%s: tx_timeout", ndev->name); if (!priv->reset_task_pending) { - priv->reset_task_pending = 1; - printk(", scheduling a reset"); + printk(KERN_WARNING + "%s: tx_timeout, scheduling reset", ndev->name); netif_stop_queue(ndev); + priv->reset_task_pending = 1; schedule_work(&priv->reset_task); + } else { + printk(KERN_WARNING + "%s: tx_timeout, waiting for reset", ndev->name); } - printk("\n"); } -- cgit v1.2.3 From 93b2dd12049d1adb0d76fb918fcd4c1030445433 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sun, 8 Oct 2006 00:38:15 -0400 Subject: [PATCH] prism54: whitespace cleanup NET: prism54 - whitespace cleanup Signed-off-by: Dmitry Torokhov Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_38xx.c | 17 ++++---- drivers/net/wireless/prism54/isl_38xx.h | 7 ++- drivers/net/wireless/prism54/isl_ioctl.c | 61 +++++++++++++-------------- drivers/net/wireless/prism54/isl_ioctl.h | 1 - drivers/net/wireless/prism54/isl_oid.h | 32 +++++++------- drivers/net/wireless/prism54/islpci_dev.c | 13 +++--- drivers/net/wireless/prism54/islpci_dev.h | 11 +++-- drivers/net/wireless/prism54/islpci_eth.c | 7 ++- drivers/net/wireless/prism54/islpci_eth.h | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 23 +++++----- drivers/net/wireless/prism54/islpci_mgt.c | 3 +- drivers/net/wireless/prism54/islpci_mgt.h | 5 +-- drivers/net/wireless/prism54/oid_mgt.c | 6 +-- drivers/net/wireless/prism54/prismcompat.h | 4 +- 14 files changed, 89 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index 23deee69974b..02fc67bccbd0 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003-2004 Luis R. Rodriguez _ * @@ -38,7 +37,7 @@ * isl38xx_disable_interrupts - disable all interrupts * @device: pci memory base address * - * Instructs the device to disable all interrupt reporting by asserting + * Instructs the device to disable all interrupt reporting by asserting * the IRQ line. New events may still show up in the interrupt identification * register located at offset %ISL38XX_INT_IDENT_REG. */ @@ -204,17 +203,19 @@ isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address) /* enable the interrupt for detecting initialization */ /* Note: Do not enable other interrupts here. We want the - * device to have come up first 100% before allowing any other + * device to have come up first 100% before allowing any other * interrupts. */ isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */ } void -isl38xx_enable_common_interrupts(void __iomem *device_base) { +isl38xx_enable_common_interrupts(void __iomem *device_base) +{ u32 reg; - reg = ( ISL38XX_INT_IDENT_UPDATE | - ISL38XX_INT_IDENT_SLEEP | ISL38XX_INT_IDENT_WAKEUP); + + reg = ISL38XX_INT_IDENT_UPDATE | ISL38XX_INT_IDENT_SLEEP | + ISL38XX_INT_IDENT_WAKEUP; isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); udelay(ISL38XX_WRITEIO_DELAY); } @@ -234,23 +235,21 @@ isl38xx_in_queue(isl38xx_control_block *cb, int queue) /* send queues */ case ISL38XX_CB_TX_MGMTQ: BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); + case ISL38XX_CB_TX_DATA_LQ: case ISL38XX_CB_TX_DATA_HQ: BUG_ON(delta > ISL38XX_CB_TX_QSIZE); return delta; - break; /* receive queues */ case ISL38XX_CB_RX_MGMTQ: BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); return ISL38XX_CB_MGMT_QSIZE - delta; - break; case ISL38XX_CB_RX_DATA_LQ: case ISL38XX_CB_RX_DATA_HQ: BUG_ON(delta > ISL38XX_CB_RX_QSIZE); return ISL38XX_CB_RX_QSIZE - delta; - break; } BUG(); return 0; diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index 8af20980af8d..3fadcb6f5297 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * * This program is free software; you can redistribute it and/or modify @@ -67,10 +66,10 @@ * @base: (host) memory base address of the device * @val: 32bit value (host order) to write * @offset: byte offset into @base to write value to - * + * * This helper takes care of writing a 32bit datum to the - * specified offset into the device's pci memory space, and making sure - * the pci memory buffers get flushed by performing one harmless read + * specified offset into the device's pci memory space, and making sure + * the pci memory buffers get flushed by performing one harmless read * from the %ISL38XX_PCI_POSTING_FLUSH offset. */ static inline void diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 286325ca3293..4a20e45de3ca 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * (C) 2003,2004 Aurelien Alleaume * (C) 2003 Herbert Valerio Riedel @@ -55,12 +54,12 @@ static const unsigned char scan_rate_list[] = { 2, 4, 11, 22, * prism54_mib_mode_helper - MIB change mode helper function * @mib: the &struct islpci_mib object to modify * @iw_mode: new mode (%IW_MODE_*) - * + * * This is a helper function, hence it does not lock. Make sure - * caller deals with locking *if* necessary. This function sets the - * mode-dependent mib values and does the mapping of the Linux - * Wireless API modes to Device firmware modes. It also checks for - * correct valid Linux wireless modes. + * caller deals with locking *if* necessary. This function sets the + * mode-dependent mib values and does the mapping of the Linux + * Wireless API modes to Device firmware modes. It also checks for + * correct valid Linux wireless modes. */ static int prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode) @@ -118,7 +117,7 @@ prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode) * * this function initializes the struct given as @mib with defaults, * of which many are retrieved from the global module parameter - * variables. + * variables. */ void @@ -134,7 +133,7 @@ prism54_mib_init(islpci_private *priv) authen = CARD_DEFAULT_AUTHEN; wep = CARD_DEFAULT_WEP; filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */ - dot1x = CARD_DEFAULT_DOT1X; + dot1x = CARD_DEFAULT_DOT1X; mlme = CARD_DEFAULT_MLME_MODE; conformance = CARD_DEFAULT_CONFORMANCE; power = 127; @@ -228,7 +227,7 @@ prism54_get_wireless_stats(struct net_device *ndev) } else priv->iwstatistics.qual.updated = 0; - /* Update our wireless stats, but do not schedule to often + /* Update our wireless stats, but do not schedule to often * (max 1 HZ) */ if ((priv->stats_timestamp == 0) || time_after(jiffies, priv->stats_timestamp + 1 * HZ)) { @@ -705,7 +704,7 @@ prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, * Starting with WE-17, the buffer can be as big as needed. * But the device won't repport anything if you change the value * of IWMAX_BSS=24. */ - + rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); bsslist = r.ptr; @@ -785,7 +784,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, return rvalue; } -/* Provides no functionality, just completes the ioctl. In essence this is a +/* Provides no functionality, just completes the ioctl. In essence this is a * just a cosmetic ioctl. */ static int @@ -1104,7 +1103,7 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, &key); } /* - * If a valid key is set, encryption should be enabled + * If a valid key is set, encryption should be enabled * (user may turn it off later). * This is also how "iwconfig ethX key on" works */ @@ -1126,7 +1125,7 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, } /* now read the flags */ if (dwrq->flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, + /* Encoding disabled, * authen = DOT11_AUTH_OS; * invoke = 0; * exunencrypt = 0; */ @@ -1214,7 +1213,7 @@ prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info, vwrq->value = (s32) r.u / 4; vwrq->fixed = 1; /* radio is not turned of - * btw: how is possible to turn off only the radio + * btw: how is possible to turn off only the radio */ vwrq->disabled = 0; @@ -2354,17 +2353,17 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, handle_request(priv, mlme, oid); send_formatted_event(priv, "Authenticate request (ex)", mlme, 1); - if (priv->iw_mode != IW_MODE_MASTER + if (priv->iw_mode != IW_MODE_MASTER && mlmeex->state != DOT11_STATE_AUTHING) break; confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC); - if (!confirm) + if (!confirm) break; memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + printk(KERN_DEBUG "Authenticate from: address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", mlmeex->address[0], mlmeex->address[1], mlmeex->address[2], @@ -2398,10 +2397,10 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, handle_request(priv, mlme, oid); send_formatted_event(priv, "Associate request (ex)", mlme, 1); - if (priv->iw_mode != IW_MODE_MASTER + if (priv->iw_mode != IW_MODE_MASTER && mlmeex->state != DOT11_STATE_ASSOCING) break; - + confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); if (!confirm) @@ -2417,7 +2416,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, if (!wpa_ie_len) { printk(KERN_DEBUG "No WPA IE found from " - "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", mlmeex->address[0], mlmeex->address[1], mlmeex->address[2], @@ -2435,14 +2434,14 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, mgt_set_varlen(priv, oid, confirm, wpa_ie_len); kfree(confirm); - + break; case DOT11_OID_REASSOCIATEEX: handle_request(priv, mlme, oid); send_formatted_event(priv, "Reassociate request (ex)", mlme, 1); - if (priv->iw_mode != IW_MODE_MASTER + if (priv->iw_mode != IW_MODE_MASTER && mlmeex->state != DOT11_STATE_ASSOCING) break; @@ -2461,7 +2460,7 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, if (!wpa_ie_len) { printk(KERN_DEBUG "No WPA IE found from " - "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", + "address:\t%02x:%02x:%02x:%02x:%02x:%02x\n", mlmeex->address[0], mlmeex->address[1], mlmeex->address[2], @@ -2473,13 +2472,13 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, break; } - confirm->size = wpa_ie_len; + confirm->size = wpa_ie_len; memcpy(&confirm->data, wpa_ie, wpa_ie_len); mgt_set_varlen(priv, oid, confirm, wpa_ie_len); kfree(confirm); - + break; default: @@ -2545,10 +2544,10 @@ enum { #define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ ((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) -/* Maximum length for algorithm names (-1 for nul termination) +/* Maximum length for algorithm names (-1 for nul termination) * used in ioctl() */ #define HOSTAP_CRYPT_ALG_NAME_LEN 16 - + struct prism2_hostapd_param { u32 cmd; u8 sta_addr[ETH_ALEN]; @@ -2621,7 +2620,7 @@ prism2_ioctl_set_encryption(struct net_device *dev, &key); } /* - * If a valid key is set, encryption should be enabled + * If a valid key is set, encryption should be enabled * (user may turn it off later). * This is also how "iwconfig ethX key on" works */ @@ -2643,7 +2642,7 @@ prism2_ioctl_set_encryption(struct net_device *dev, } /* now read the flags */ if (param->u.crypt.flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, + /* Encoding disabled, * authen = DOT11_AUTH_OS; * invoke = 0; * exunencrypt = 0; */ @@ -2710,7 +2709,7 @@ prism2_ioctl_set_generic_element(struct net_device *ndev, ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); - if (ret == 0) + if (ret == 0) printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", ndev->name); } @@ -2870,7 +2869,7 @@ prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, mlme = DOT11_MLME_AUTO; printk("%s: Disabling WPA\n", ndev->name); break; - case 2: + case 2: case 1: /* WPA */ printk("%s: Enabling WPA\n", ndev->name); break; diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h index 65f33acd0a42..e8183d30c52e 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ b/drivers/net/wireless/prism54/isl_ioctl.h @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * (C) 2003 Aurelien Alleaume * (C) 2003 Luis R. Rodriguez diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index 419edf7ccf1a..ab5322768a4a 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -1,6 +1,4 @@ /* - * - * * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2004 Luis R. Rodriguez * Copyright (C) 2004 Aurelien Alleaume @@ -23,7 +21,7 @@ #if !defined(_ISL_OID_H) #define _ISL_OID_H -/* +/* * MIB related constant and structure definitions for communicating * with the device firmware */ @@ -99,7 +97,7 @@ struct obj_attachment { char data[0]; } __attribute__((packed)); -/* +/* * in case everything's ok, the inlined function below will be * optimized away by the compiler... */ @@ -154,13 +152,13 @@ enum dot11_priv_t { /* Prism "Nitro" / Frameburst / "Packet Frame Grouping" * Value is in microseconds. Represents the # microseconds - * the firmware will take to group frames before sending out then out + * the firmware will take to group frames before sending out then out * together with a CSMA contention. Without this all frames are - * sent with a CSMA contention. - * Bibliography: + * sent with a CSMA contention. + * Bibliography: * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html */ -enum dot11_maxframeburst_t { +enum dot11_maxframeburst_t { /* Values for DOT11_OID_MAXFRAMEBURST */ DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */ DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */ @@ -176,9 +174,9 @@ enum dot11_maxframeburst_t { /* Support for 802.11 long and short frame preambles. * Long preamble uses 128-bit sync field, 8-bit CRC * Short preamble uses 56-bit sync field, 16-bit CRC - * + * * 802.11a -- not sure, both optionally ? - * 802.11b supports long and optionally short + * 802.11b supports long and optionally short * 802.11g supports both */ enum dot11_preamblesettings_t { DOT11_PREAMBLESETTING_LONG = 0, @@ -194,7 +192,7 @@ enum dot11_preamblesettings_t { * Long uses 802.11a slot timing (9 usec ?) * Short uses 802.11b slot timing (20 use ?) */ enum dot11_slotsettings_t { - DOT11_SLOTSETTINGS_LONG = 0, + DOT11_SLOTSETTINGS_LONG = 0, /* Allows *only* long 802.11b slot timing */ DOT11_SLOTSETTINGS_SHORT = 1, /* Allows *only* long 802.11a slot timing */ @@ -203,7 +201,7 @@ enum dot11_slotsettings_t { }; /* All you need to know, ERP is "Extended Rate PHY". - * An Extended Rate PHY (ERP) STA or AP shall support three different + * An Extended Rate PHY (ERP) STA or AP shall support three different * preamble and header formats: * Long preamble (refer to above) * Short preamble (refer to above) @@ -221,7 +219,7 @@ enum do11_nonerpstatus_t { /* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-* * The key here is DOT11 NON ERP NEVER protects against * NON ERP STA's. You *don't* want this unless - * you know what you are doing. It means you will only + * you know what you are doing. It means you will only * get Extended Rate capabilities */ enum dot11_nonerpprotection_t { DOT11_NONERP_NEVER = 0, @@ -229,13 +227,13 @@ enum dot11_nonerpprotection_t { DOT11_NONERP_DYNAMIC = 2 }; -/* Preset OID configuration for 802.11 modes - * Note: DOT11_OID_CW[MIN|MAX] hold the values of the +/* Preset OID configuration for 802.11 modes + * Note: DOT11_OID_CW[MIN|MAX] hold the values of the * DCS MIN|MAX backoff used */ enum dot11_profile_t { /* And set/allowed values */ /* Allowed values for DOT11_OID_PROFILES */ DOT11_PROFILE_B_ONLY = 0, - /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps + /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC * DOT11_OID_CWMIN: 31 * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC @@ -275,7 +273,7 @@ enum oid_inl_conformance_t { OID_INL_CONFORMANCE_NONE = 0, /* Perform active scanning */ OID_INL_CONFORMANCE_STRICT = 1, /* Strictly adhere to 802.11d */ OID_INL_CONFORMANCE_FLEXIBLE = 2, /* Use passed 802.11d info to - * determine channel AND/OR just make assumption that active + * determine channel AND/OR just make assumption that active * channels are valid channels */ }; diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index ec1c00f19eb3..1e0603ca436c 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2003 Luis R. Rodriguez @@ -413,7 +412,7 @@ prism54_bring_down(islpci_private *priv) islpci_set_state(priv, PRV_STATE_PREBOOT); /* disable all device interrupts in case they weren't */ - isl38xx_disable_interrupts(priv->device_base); + isl38xx_disable_interrupts(priv->device_base); /* For safety reasons, we may want to ensure that no DMA transfer is * currently in progress by emptying the TX and RX queues. */ @@ -480,7 +479,7 @@ islpci_reset_if(islpci_private *priv) DEFINE_WAIT(wait); prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); - + /* now the last step is to reset the interface */ isl38xx_interface_reset(priv->device_base, priv->device_host_address); islpci_set_state(priv, PRV_STATE_PREINIT); @@ -488,7 +487,7 @@ islpci_reset_if(islpci_private *priv) for(count = 0; count < 2 && result; count++) { /* The software reset acknowledge needs about 220 msec here. * Be conservative and wait for up to one second. */ - + remaining = schedule_timeout_uninterruptible(HZ); if(remaining > 0) { @@ -496,7 +495,7 @@ islpci_reset_if(islpci_private *priv) break; } - /* If we're here it's because our IRQ hasn't yet gone through. + /* If we're here it's because our IRQ hasn't yet gone through. * Retry a bit more... */ printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n", @@ -514,7 +513,7 @@ islpci_reset_if(islpci_private *priv) /* Now that the device is 100% up, let's allow * for the other interrupts -- - * NOTE: this is not *yet* true since we've only allowed the + * NOTE: this is not *yet* true since we've only allowed the * INIT interrupt on the IRQ line. We can perhaps poll * the IRQ line until we know for sure the reset went through */ isl38xx_enable_common_interrupts(priv->device_base); @@ -716,7 +715,7 @@ islpci_alloc_memory(islpci_private *priv) prism54_acl_init(&priv->acl); prism54_wpa_bss_ie_init(priv); - if (mgt_init(priv)) + if (mgt_init(priv)) goto out_free; return 0; diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 2f7e525d0cf6..a9aa1662eaa4 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -1,6 +1,5 @@ /* - * - * Copyright (C) 2002 Intersil Americas Inc. + * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel * Copyright (C) 2003 Luis R. Rodriguez * Copyright (C) 2003 Aurelien Alleaume @@ -72,12 +71,12 @@ struct islpci_bss_wpa_ie { u8 bssid[ETH_ALEN]; u8 wpa_ie[MAX_WPA_IE_LEN]; size_t wpa_ie_len; - + }; typedef struct { spinlock_t slock; /* generic spinlock; */ - + u32 priv_oid; /* our mib cache */ @@ -85,7 +84,7 @@ typedef struct { struct rw_semaphore mib_sem; void **mib; char nickname[IW_ESSID_MAX_SIZE+1]; - + /* Take care of the wireless stats */ struct work_struct stats_work; struct semaphore stats_sem; @@ -120,7 +119,7 @@ typedef struct { struct net_device *ndev; /* device queue interface members */ - struct isl38xx_cb *control_block; /* device control block + struct isl38xx_cb *control_block; /* device control block (== driver_mem_address!) */ /* Each queue has three indexes: diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index bfbafe99b94a..676d83813dc8 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2004 Aurelien Alleaume * This program is free software; you can redistribute it and/or modify @@ -48,7 +47,7 @@ islpci_eth_cleanup_transmit(islpci_private *priv, /* read the index of the first fragment to be freed */ index = priv->free_data_tx % ISL38XX_CB_TX_QSIZE; - /* check for holes in the arrays caused by multi fragment frames + /* check for holes in the arrays caused by multi fragment frames * searching for the last fragment of a frame */ if (priv->pci_map_tx_address[index] != (dma_addr_t) NULL) { /* entry is the last fragment of a frame @@ -285,7 +284,7 @@ islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) (struct avs_80211_1_header *) skb_push(*skb, sizeof (struct avs_80211_1_header)); - + avs->version = cpu_to_be32(P80211CAPTURE_VERSION); avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); avs->mactime = cpu_to_be64(le64_to_cpu(clock)); @@ -391,7 +390,7 @@ islpci_eth_receive(islpci_private *priv) struct rx_annex_header *annex = (struct rx_annex_header *) skb->data; wstats.level = annex->rfmon.rssi; - /* The noise value can be a bit outdated if nobody's + /* The noise value can be a bit outdated if nobody's * reading wireless stats... */ wstats.noise = priv->local_iwstatistics.qual.noise; wstats.qual = wstats.level - wstats.noise; diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h index bc9d7a60b8d6..26789454067c 100644 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ b/drivers/net/wireless/prism54/islpci_eth.h @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * * This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index f692dccf0d07..f6354b1cbc28 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Herbert Valerio Riedel * @@ -40,8 +39,8 @@ static int init_pcitm = 0; module_param(init_pcitm, int, 0); /* In this order: vendor, device, subvendor, subdevice, class, class_mask, - * driver_data - * If you have an update for this please contact prism54-devel@prism54.org + * driver_data + * If you have an update for this please contact prism54-devel@prism54.org * The latest list can be found at http://prism54.org/supported_cards.php */ static const struct pci_device_id prism54_id_tbl[] = { /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ @@ -132,15 +131,15 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT) * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT) - * The RETRY_TIMEOUT is used to set the number of retries that the core, as a - * Master, will perform before abandoning a cycle. The default value for - * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new - * devices. A write of zero to the RETRY_TIMEOUT register disables this - * function to allow use with any non-compliant legacy devices that may - * execute more retries. + * The RETRY_TIMEOUT is used to set the number of retries that the core, as a + * Master, will perform before abandoning a cycle. The default value for + * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new + * devices. A write of zero to the RETRY_TIMEOUT register disables this + * function to allow use with any non-compliant legacy devices that may + * execute more retries. * - * Writing zero to both these two registers will disable both timeouts and - * *can* solve problems caused by devices that are slow to respond. + * Writing zero to both these two registers will disable both timeouts and + * *can* solve problems caused by devices that are slow to respond. * Make this configurable - MSW */ if ( init_pcitm >= 0 ) { @@ -241,7 +240,7 @@ prism54_remove(struct pci_dev *pdev) isl38xx_disable_interrupts(priv->device_base); islpci_set_state(priv, PRV_STATE_OFF); /* This bellow causes a lockup at rmmod time. It might be - * because some interrupts still linger after rmmod time, + * because some interrupts still linger after rmmod time, * see bug #17 */ /* pci_set_power_state(pdev, 3);*/ /* try to power-off */ } diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c index 2e061a80b294..036a875054c9 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ b/drivers/net/wireless/prism54/islpci_mgt.c @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright 2004 Jens Maurer * @@ -502,7 +501,7 @@ islpci_mgt_transaction(struct net_device *ndev, printk(KERN_WARNING "%s: timeout waiting for mgmt response\n", ndev->name); - /* TODO: we should reset the device here */ + /* TODO: we should reset the device here */ out: finish_wait(&priv->mgmt_wqueue, &wait); up(&priv->mgmt_sem); diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h index 2982be3363ef..fc53b587b722 100644 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ b/drivers/net/wireless/prism54/islpci_mgt.h @@ -1,5 +1,4 @@ /* - * * Copyright (C) 2002 Intersil Americas Inc. * Copyright (C) 2003 Luis R. Rodriguez * @@ -36,8 +35,8 @@ extern int pc_debug; /* General driver definitions */ -#define PCIDEVICE_LATENCY_TIMER_MIN 0x40 -#define PCIDEVICE_LATENCY_TIMER_VAL 0x50 +#define PCIDEVICE_LATENCY_TIMER_MIN 0x40 +#define PCIDEVICE_LATENCY_TIMER_VAL 0x50 /* Debugging verbose definitions */ #define SHOW_NOTHING 0x00 /* overrules everything */ diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c index ebb238785839..fbc52b6a3024 100644 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ b/drivers/net/wireless/prism54/oid_mgt.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003,2004 Aurelien Alleaume * * This program is free software; you can redistribute it and/or modify @@ -503,7 +503,7 @@ mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len } if (ret || response_op == PIMFOR_OP_ERROR) ret = -EIO; - } else + } else ret = -EIO; /* re-set given data to what it was */ @@ -727,7 +727,7 @@ mgt_commit(islpci_private *priv) * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL * FREQUENCY,EXTENDEDRATES. * - * The way to do this is to set ESSID. Note though that they may get + * The way to do this is to set ESSID. Note though that they may get * unlatch before though by setting another OID. */ #if 0 void diff --git a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h index d71eca55a302..aa1d1747784f 100644 --- a/drivers/net/wireless/prism54/prismcompat.h +++ b/drivers/net/wireless/prism54/prismcompat.h @@ -1,4 +1,4 @@ -/* +/* * (C) 2004 Margit Schubert-While * * This program is free software; you can redistribute it and/or modify @@ -16,7 +16,7 @@ * */ -/* +/* * Compatibility header file to aid support of different kernel versions */ -- cgit v1.2.3 From 3b31dc327f07a2df06da931ffb0bb1627711bd86 Mon Sep 17 00:00:00 2001 From: Holden Karau Date: Tue, 10 Oct 2006 14:45:33 -0700 Subject: [PATCH] atmel: output signal strength information Output signal strength information as part of iwlist scan - before it did not output any signal strength related information. Signed-off-by: Holden Karau Cc: Jean Tourrilhes Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 74c800f6caf8..10bcb48e80d0 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -2343,6 +2343,14 @@ static int atmel_get_scan(struct net_device *dev, iwe.u.freq.e = 0; current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_FREQ_LEN); + /* Add quality statistics */ + iwe.cmd = IWEVQUAL; + iwe.u.qual.level = priv->BSSinfo[i].RSSI; + iwe.u.qual.qual = iwe.u.qual.level; + /* iwe.u.qual.noise = SOMETHING */ + current_ev = iwe_stream_add_event(current_ev, extra + IW_SCAN_MAX_DATA , &iwe, IW_EV_QUAL_LEN); + + iwe.cmd = SIOCGIWENCODE; if (priv->BSSinfo[i].UsingWEP) iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; -- cgit v1.2.3 From 995cdaa45b1faf8f4472e4b4c6027dc685ae1b54 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Tue, 10 Oct 2006 14:45:47 -0700 Subject: [PATCH] prism54: use BUILD_BUG_ON Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_oid.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h index ab5322768a4a..b7534c2869c8 100644 --- a/drivers/net/wireless/prism54/isl_oid.h +++ b/drivers/net/wireless/prism54/isl_oid.h @@ -104,14 +104,14 @@ struct obj_attachment { static inline void __bug_on_wrong_struct_sizes(void) { - BUG_ON(sizeof (struct obj_ssid) != 34); - BUG_ON(sizeof (struct obj_key) != 34); - BUG_ON(sizeof (struct obj_mlme) != 12); - BUG_ON(sizeof (struct obj_mlmeex) != 14); - BUG_ON(sizeof (struct obj_buffer) != 8); - BUG_ON(sizeof (struct obj_bss) != 60); - BUG_ON(sizeof (struct obj_bsslist) != 4); - BUG_ON(sizeof (struct obj_frequencies) != 2); + BUILD_BUG_ON(sizeof (struct obj_ssid) != 34); + BUILD_BUG_ON(sizeof (struct obj_key) != 34); + BUILD_BUG_ON(sizeof (struct obj_mlme) != 12); + BUILD_BUG_ON(sizeof (struct obj_mlmeex) != 14); + BUILD_BUG_ON(sizeof (struct obj_buffer) != 8); + BUILD_BUG_ON(sizeof (struct obj_bss) != 60); + BUILD_BUG_ON(sizeof (struct obj_bsslist) != 4); + BUILD_BUG_ON(sizeof (struct obj_frequencies) != 2); } enum dot11_state_t { -- cgit v1.2.3 From f3d1fca3eb05cf6ff3879a385a15d24fbf556c57 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Sun, 15 Oct 2006 23:18:11 -0500 Subject: [PATCH] bcm43xx: add PCI-E code The current bcm43xx driver does not contain code to handle PCI-E interfaces such as the BCM4311 and BCM4312. This patch, originally written by Stefano Brivio adds the necessary code to enable these interfaces. Signed-off-by: Stefano Brivio Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx.h | 29 ++++++ drivers/net/wireless/bcm43xx/bcm43xx_main.c | 143 ++++++++++++++++++++------- drivers/net/wireless/bcm43xx/bcm43xx_power.c | 28 ++++-- 3 files changed, 156 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h index 5f43d7f42af1..94dfb92fab5c 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ b/drivers/net/wireless/bcm43xx/bcm43xx.h @@ -159,6 +159,7 @@ /* Chipcommon registers. */ #define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 +#define BCM43xx_CHIPCOMMON_CTL 0x28 #define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 #define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 #define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 @@ -172,6 +173,33 @@ /* SBTOPCI2 values. */ #define BCM43xx_SBTOPCI2_PREFETCH 0x4 #define BCM43xx_SBTOPCI2_BURST 0x8 +#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20 + +/* PCI-E core registers. */ +#define BCM43xx_PCIECORE_REG_ADDR 0x0130 +#define BCM43xx_PCIECORE_REG_DATA 0x0134 +#define BCM43xx_PCIECORE_MDIO_CTL 0x0128 +#define BCM43xx_PCIECORE_MDIO_DATA 0x012C + +/* PCI-E registers. */ +#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004 +#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100 + +/* PCI-E MDIO bits. */ +#define BCM43xx_PCIE_MDIO_ST 0x40000000 +#define BCM43xx_PCIE_MDIO_WT 0x10000000 +#define BCM43xx_PCIE_MDIO_DEV 22 +#define BCM43xx_PCIE_MDIO_REG 18 +#define BCM43xx_PCIE_MDIO_TA 0x00020000 +#define BCM43xx_PCIE_MDIO_TC 0x0100 + +/* MDIO devices. */ +#define BCM43xx_MDIO_SERDES_RX 0x1F + +/* SERDES RX registers. */ +#define BCM43xx_SERDES_RXTIMER 0x2 +#define BCM43xx_SERDES_CDR 0x6 +#define BCM43xx_SERDES_CDR_BW 0x7 /* Chipcommon capabilities. */ #define BCM43xx_CAPABILITIES_PCTL 0x00040000 @@ -221,6 +249,7 @@ #define BCM43xx_COREID_USB20_HOST 0x819 #define BCM43xx_COREID_USB20_DEV 0x81a #define BCM43xx_COREID_SDIO_HOST 0x81b +#define BCM43xx_COREID_PCIE 0x820 /* Core Information Registers */ #define BCM43xx_CIR_BASE 0xf00 diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 2ffc0d5b54ee..c6bd86889f1b 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -130,6 +130,10 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4307 802.11b */ { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4311 802.11(a)/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + /* Broadcom 4312 802.11a/b/g */ + { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4318 802.11b/g */ { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Broadcom 4319 802.11a/b/g */ @@ -2600,8 +2604,9 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) /* fetch sb_id_hi from core information registers */ sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - core_id = (sb_id_hi & 0xFFF0) >> 4; - core_rev = (sb_id_hi & 0xF); + core_id = (sb_id_hi & 0x8FF0) >> 4; + core_rev = (sb_id_hi & 0x7000) >> 8; + core_rev |= (sb_id_hi & 0xF); core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; /* if present, chipcommon is always core 0; read the chipid from it */ @@ -2711,6 +2716,7 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core = NULL; switch (core_id) { case BCM43xx_COREID_PCI: + case BCM43xx_COREID_PCIE: core = &bcm->core_pci; if (core->available) { printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); @@ -2749,12 +2755,12 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) case 6: case 7: case 9: + case 10: break; default: - printk(KERN_ERR PFX "Error: Unsupported 80211 core revision %u\n", + printk(KERN_WARNING PFX + "Unsupported 80211 core revision %u\n", core_rev); - err = -ENODEV; - goto out; } bcm->nr_80211_available++; core->priv = ext_80211; @@ -2868,16 +2874,11 @@ static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, u32 sbimconfiglow; u8 limit; - if (bcm->chip_rev < 5) { + if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) - sbimconfiglow |= 0x32; - else if (bcm->bustype == BCM43xx_BUSTYPE_SB) - sbimconfiglow |= 0x53; - else - assert(0); + sbimconfiglow |= 0x32; bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); } @@ -3004,22 +3005,64 @@ static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) { - int err; - struct bcm43xx_coreinfo *old_core; + int err = 0; - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; + bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + if (bcm->core_chipcommon.available) { + err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); + if (err) + goto out; + + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + /* this function is always called when a PCI core is mapped */ + err = bcm43xx_switch_core(bcm, &bcm->core_pci); + if (err) + goto out; + } else + bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); + + bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - bcm43xx_switch_core(bcm, old_core); - assert(err == 0); out: return err; } +static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address) +{ + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); + return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA); +} + +static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address, + u32 data) +{ + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); + bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data); +} + +static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg, + u16 data) +{ + int i; + + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082); + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST | + BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) | + (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA | + data); + udelay(10); + + for (i = 0; i < 10; i++) { + if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) & + BCM43xx_PCIE_MDIO_TC) + break; + msleep(1); + } + bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0); +} + /* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. * To enable core 0, pass a core_mask of 1<<0 */ @@ -3039,7 +3082,8 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, if (err) goto out; - if (bcm->core_pci.rev < 6) { + if (bcm->current_core->rev < 6 || + bcm->current_core->id == BCM43xx_COREID_PCI) { value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); value |= (1 << backplane_flag_nr); bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); @@ -3057,21 +3101,46 @@ static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, } } - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - - if (bcm->core_pci.rev < 5) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); - err = bcm43xx_pcicore_commit_settings(bcm); - assert(err == 0); + if (bcm->current_core->id == BCM43xx_COREID_PCI) { + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + + if (bcm->current_core->rev < 5) { + value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); + value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; + value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) + & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; + bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); + err = bcm43xx_pcicore_commit_settings(bcm); + assert(err == 0); + } else if (bcm->current_core->rev >= 11) { + value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); + value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI; + bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); + } + } else { + if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) { + value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND); + value |= 0x8; + bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND, + value); + } + if (bcm->current_core->rev == 0) { + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_RXTIMER, 0x8128); + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_CDR, 0x0100); + bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, + BCM43xx_SERDES_CDR_BW, 0x1466); + } else if (bcm->current_core->rev == 1) { + value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL); + value |= 0x40; + bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL, + value); + } } - out_switch_back: err = bcm43xx_switch_core(bcm, old_core); out: @@ -3676,7 +3745,7 @@ static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; break; case BCM43xx_PHYTYPE_G: - if (phy_rev > 7) + if (phy_rev > 8) phy_rev_ok = 0; bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c index 6569da3a7a39..7e774f410953 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_power.c @@ -153,8 +153,6 @@ int bcm43xx_pctl_init(struct bcm43xx_private *bcm) int err, maxfreq; struct bcm43xx_coreinfo *old_core; - if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) - return 0; old_core = bcm->current_core; err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); if (err == -ENODEV) @@ -162,11 +160,27 @@ int bcm43xx_pctl_init(struct bcm43xx_private *bcm) if (err) goto out; - maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, - (maxfreq * 150 + 999999) / 1000000); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, - (maxfreq * 15 + 999999) / 1000000); + if (bcm->chip_id == 0x4321) { + if (bcm->chip_rev == 0) + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4); + if (bcm->chip_rev == 1) + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4); + } + + if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) { + if (bcm->current_core->rev >= 10) { + /* Set Idle Power clock rate to 1Mhz */ + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL, + (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL) + & 0x0000FFFF) | 0x40000); + } else { + maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, + (maxfreq * 150 + 999999) / 1000000); + bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, + (maxfreq * 15 + 999999) / 1000000); + } + } err = bcm43xx_switch_core(bcm, old_core); assert(err == 0); -- cgit v1.2.3 From 3d396eb17e9f8c5f59314078b45b88647591378d Mon Sep 17 00:00:00 2001 From: "Amit S. Kale" Date: Sat, 21 Oct 2006 15:33:03 -0400 Subject: Add NetXen 1G/10G ethernet driver. Signed-off-by: Amit S. Kale Signed-off-by: Jeff Garzik --- MAINTAINERS | 7 + drivers/net/Kconfig | 5 + drivers/net/Makefile | 1 + drivers/net/netxen/Makefile | 35 + drivers/net/netxen/netxen_nic.h | 910 ++++++++++++++++++++++++ drivers/net/netxen/netxen_nic_ethtool.c | 715 +++++++++++++++++++ drivers/net/netxen/netxen_nic_hdr.h | 618 ++++++++++++++++ drivers/net/netxen/netxen_nic_hw.c | 936 ++++++++++++++++++++++++ drivers/net/netxen/netxen_nic_hw.h | 480 +++++++++++++ drivers/net/netxen/netxen_nic_init.c | 1143 ++++++++++++++++++++++++++++++ drivers/net/netxen/netxen_nic_ioctl.h | 75 ++ drivers/net/netxen/netxen_nic_isr.c | 221 ++++++ drivers/net/netxen/netxen_nic_main.c | 1116 +++++++++++++++++++++++++++++ drivers/net/netxen/netxen_nic_niu.c | 800 +++++++++++++++++++++ drivers/net/netxen/netxen_nic_phan_reg.h | 195 +++++ 15 files changed, 7257 insertions(+) create mode 100644 drivers/net/netxen/Makefile create mode 100644 drivers/net/netxen/netxen_nic.h create mode 100644 drivers/net/netxen/netxen_nic_ethtool.c create mode 100644 drivers/net/netxen/netxen_nic_hdr.h create mode 100644 drivers/net/netxen/netxen_nic_hw.c create mode 100644 drivers/net/netxen/netxen_nic_hw.h create mode 100644 drivers/net/netxen/netxen_nic_init.c create mode 100644 drivers/net/netxen/netxen_nic_ioctl.h create mode 100644 drivers/net/netxen/netxen_nic_isr.c create mode 100644 drivers/net/netxen/netxen_nic_main.c create mode 100644 drivers/net/netxen/netxen_nic_niu.c create mode 100644 drivers/net/netxen/netxen_nic_phan_reg.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 846e77a78710..0e174320726f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2132,6 +2132,13 @@ L: netdev@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git S: Maintained +NETXEN (1/10) GbE SUPPORT +P: Amit S. Kale +M: amitkale@netxen.com +L: netdev@vger.kernel.org +W: http://www.netxen.com +S: Supported + IPVS P: Wensong Zhang M: wensong@linux-vs.org diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d3abf80ea3e2..112d4cd5c66c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2447,6 +2447,11 @@ config MYRI10GE . The module will be called myri10ge. +config NETXEN_NIC + tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" + help + This enables the support for NetXen's Gigabit Ethernet card. + endmenu source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7d3618424288..7889e4ca1844 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -213,3 +213,4 @@ obj-$(CONFIG_NETCONSOLE) += netconsole.o obj-$(CONFIG_FS_ENET) += fs_enet/ +obj-$(CONFIG_NETXEN_NIC) += netxen/ diff --git a/drivers/net/netxen/Makefile b/drivers/net/netxen/Makefile new file mode 100644 index 000000000000..a07cdc6f7384 --- /dev/null +++ b/drivers/net/netxen/Makefile @@ -0,0 +1,35 @@ +# Copyright (C) 2003 - 2006 NetXen, Inc. +# All rights reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# 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. +# +# The full GNU General Public License is included in this distribution +# in the file called LICENSE. +# +# Contact Information: +# info@netxen.com +# NetXen, +# 3965 Freedom Circle, Fourth floor, +# Santa Clara, CA 95054 +# +# Makefile for the NetXen NIC Driver +# + + +obj-$(CONFIG_NETXEN_NIC) := netxen_nic.o + +netxen_nic-y := netxen_nic_hw.o netxen_nic_main.o netxen_nic_init.o \ + netxen_nic_isr.o netxen_nic_ethtool.o netxen_nic_niu.o diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h new file mode 100644 index 000000000000..c7d76c14f7be --- /dev/null +++ b/drivers/net/netxen/netxen_nic.h @@ -0,0 +1,910 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + */ + +#ifndef _NETXEN_NIC_H_ +#define _NETXEN_NIC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "netxen_nic_hw.h" + +#define NETXEN_NIC_BUILD_NO "232" +#define _NETXEN_NIC_LINUX_MAJOR 2 +#define _NETXEN_NIC_LINUX_MINOR 3 +#define _NETXEN_NIC_LINUX_SUBVERSION 57 +#define NETXEN_NIC_LINUX_VERSIONID "2.3.57" +#define NETXEN_NIC_FW_VERSIONID "2.3.57" + +#define RCV_DESC_RINGSIZE \ + (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) +#define STATUS_DESC_RINGSIZE \ + (sizeof(struct status_desc)* adapter->max_rx_desc_count) +#define TX_RINGSIZE \ + (sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count) +#define RCV_BUFFSIZE \ + (sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count) +#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a))) + +#define NETXEN_NETDEV_STATUS 0x1 + +#define ADDR_IN_WINDOW1(off) \ + ((off > NETXEN_CRB_PCIX_HOST2) && (off < NETXEN_CRB_MAX)) ? 1 : 0 + +/* + * normalize a 64MB crb address to 32MB PCI window + * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1 + */ +#define NETXEN_CRB_NORMALIZE(adapter, reg) \ + ((adapter)->ahw.pci_base + (reg) \ + - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST) + +#define MAX_RX_BUFFER_LENGTH 2000 +#define MAX_RX_JUMBO_BUFFER_LENGTH 9046 +#define RX_DMA_MAP_LEN (MAX_RX_BUFFER_LENGTH - NET_IP_ALIGN) +#define RX_JUMBO_DMA_MAP_LEN \ + (MAX_RX_JUMBO_BUFFER_LENGTH - NET_IP_ALIGN) +#define NETXEN_ROM_ROUNDUP 0x80000000ULL + +/* + * Maximum number of ring contexts + */ +#define MAX_RING_CTX 1 + +/* Opcodes to be used with the commands */ +enum { + TX_ETHER_PKT = 0x01, +/* The following opcodes are for IP checksum */ + TX_TCP_PKT, + TX_UDP_PKT, + TX_IP_PKT, + TX_TCP_LSO, + TX_IPSEC, + TX_IPSEC_CMD +}; + +/* The following opcodes are for internal consumption. */ +#define NETXEN_CONTROL_OP 0x10 +#define PEGNET_REQUEST 0x11 + +#define MAX_NUM_CARDS 4 + +#define MAX_BUFFERS_PER_CMD 32 + +/* + * Following are the states of the Phantom. Phantom will set them and + * Host will read to check if the fields are correct. + */ +#define PHAN_INITIALIZE_START 0xff00 +#define PHAN_INITIALIZE_FAILED 0xffff +#define PHAN_INITIALIZE_COMPLETE 0xff01 + +/* Host writes the following to notify that it has done the init-handshake */ +#define PHAN_INITIALIZE_ACK 0xf00f + +#define NUM_RCV_DESC_RINGS 2 /* No of Rcv Descriptor contexts */ + +/* descriptor types */ +#define RCV_DESC_NORMAL 0x01 +#define RCV_DESC_JUMBO 0x02 +#define RCV_DESC_NORMAL_CTXID 0 +#define RCV_DESC_JUMBO_CTXID 1 + +#define RCV_DESC_TYPE(ID) \ + ((ID == RCV_DESC_JUMBO_CTXID) ? RCV_DESC_JUMBO : RCV_DESC_NORMAL) + +#define MAX_CMD_DESCRIPTORS 1024 +#define MAX_RCV_DESCRIPTORS 32768 +#define MAX_JUMBO_RCV_DESCRIPTORS 1024 +#define MAX_RCVSTATUS_DESCRIPTORS MAX_RCV_DESCRIPTORS +#define MAX_JUMBO_RCV_DESC MAX_JUMBO_RCV_DESCRIPTORS +#define MAX_RCV_DESC MAX_RCV_DESCRIPTORS +#define MAX_RCVSTATUS_DESC MAX_RCV_DESCRIPTORS +#define NUM_RCV_DESC (MAX_RCV_DESC + MAX_JUMBO_RCV_DESCRIPTORS) +#define MAX_EPG_DESCRIPTORS (MAX_CMD_DESCRIPTORS * 8) + +#define MIN_TX_COUNT 4096 +#define MIN_RX_COUNT 4096 + +#define MAX_FRAME_SIZE 0x10000 /* 64K MAX size for LSO */ + +#define PHAN_PEG_RCV_INITIALIZED 0xff01 +#define PHAN_PEG_RCV_START_INITIALIZE 0xff00 + +#define get_next_index(index, length) \ + (((index) + 1) & ((length) - 1)) + +#define get_index_range(index,length,count) \ + (((index) + (count)) & ((length) - 1)) + +/* + * Following data structures describe the descriptors that will be used. + * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when + * we are doing LSO (above the 1500 size packet) only. + */ + +/* + * The size of reference handle been changed to 16 bits to pass the MSS fields + * for the LSO packet + */ + +#define FLAGS_CHECKSUM_ENABLED 0x01 +#define FLAGS_LSO_ENABLED 0x02 +#define FLAGS_IPSEC_SA_ADD 0x04 +#define FLAGS_IPSEC_SA_DELETE 0x08 +#define FLAGS_VLAN_TAGGED 0x10 + +#define CMD_DESC_TOTAL_LENGTH(cmd_desc) \ + ((cmd_desc)->length_tcp_hdr & 0x00FFFFFF) +#define CMD_DESC_TCP_HDR_OFFSET(cmd_desc) \ + (((cmd_desc)->length_tcp_hdr >> 24) & 0x0FF) +#define CMD_DESC_PORT(cmd_desc) ((cmd_desc)->port_ctxid & 0x0F) +#define CMD_DESC_CTX_ID(cmd_desc) (((cmd_desc)->port_ctxid >> 4) & 0x0F) + +#define CMD_DESC_TOTAL_LENGTH_WRT(cmd_desc, var) \ + ((cmd_desc)->length_tcp_hdr |= ((var) & 0x00FFFFFF)) +#define CMD_DESC_TCP_HDR_OFFSET_WRT(cmd_desc, var) \ + ((cmd_desc)->length_tcp_hdr |= (((var) << 24) & 0xFF000000)) +#define CMD_DESC_PORT_WRT(cmd_desc, var) \ + ((cmd_desc)->port_ctxid |= ((var) & 0x0F)) + +struct cmd_desc_type0 { + u64 netxen_next; /* for fragments handled by Phantom */ + union { + struct { + u32 addr_low_part2; + u32 addr_high_part2; + }; + u64 addr_buffer2; + }; + + /* Bit pattern: 0-23 total length, 24-32 tcp header offset */ + u32 length_tcp_hdr; + u8 ip_hdr_offset; /* For LSO only */ + u8 num_of_buffers; /* total number of segments */ + u8 flags; /* as defined above */ + u8 opcode; + + u16 reference_handle; /* changed to u16 to add mss */ + u16 mss; /* passed by NDIS_PACKET for LSO */ + /* Bit pattern 0-3 port, 0-3 ctx id */ + u8 port_ctxid; + u8 total_hdr_length; /* LSO only : MAC+IP+TCP Hdr size */ + u16 conn_id; /* IPSec offoad only */ + + union { + struct { + u32 addr_low_part3; + u32 addr_high_part3; + }; + u64 addr_buffer3; + }; + + union { + struct { + u32 addr_low_part1; + u32 addr_high_part1; + }; + u64 addr_buffer1; + }; + + u16 buffer1_length; + u16 buffer2_length; + u16 buffer3_length; + u16 buffer4_length; + + union { + struct { + u32 addr_low_part4; + u32 addr_high_part4; + }; + u64 addr_buffer4; + }; + +} __attribute__ ((aligned(64))); + +/* Note: sizeof(rcv_desc) should always be a mutliple of 2 */ +struct rcv_desc { + u16 reference_handle; + u16 reserved; + u32 buffer_length; /* allocated buffer length (usually 2K) */ + u64 addr_buffer; +}; + +/* opcode field in status_desc */ +#define RCV_NIC_PKT (0xA) +#define STATUS_NIC_PKT ((RCV_NIC_PKT) << 12) + +/* for status field in status_desc */ +#define STATUS_NEED_CKSUM (1) +#define STATUS_CKSUM_OK (2) + +/* owner bits of status_desc */ +#define STATUS_OWNER_HOST (0x1) +#define STATUS_OWNER_PHANTOM (0x2) + +#define NETXEN_PROT_IP (1) +#define NETXEN_PROT_UNKNOWN (0) + +/* Note: sizeof(status_desc) should always be a mutliple of 2 */ +#define STATUS_DESC_PORT(status_desc) \ + ((status_desc)->port_status_type_op & 0x0F) +#define STATUS_DESC_STATUS(status_desc) \ + (((status_desc)->port_status_type_op >> 4) & 0x0F) +#define STATUS_DESC_TYPE(status_desc) \ + (((status_desc)->port_status_type_op >> 8) & 0x0F) +#define STATUS_DESC_OPCODE(status_desc) \ + (((status_desc)->port_status_type_op >> 12) & 0x0F) + +struct status_desc { + /* Bit pattern: 0-3 port, 4-7 status, 8-11 type, 12-15 opcode */ + u16 port_status_type_op; + u16 total_length; /* NIC mode */ + u16 reference_handle; /* handle for the associated packet */ + /* Bit pattern: 0-1 owner, 2-5 protocol */ + u16 owner; /* Owner of the descriptor */ +} __attribute__ ((aligned(8))); + +enum { + NETXEN_RCV_PEG_0 = 0, + NETXEN_RCV_PEG_1 +}; +/* The version of the main data structure */ +#define NETXEN_BDINFO_VERSION 1 + +/* Magic number to let user know flash is programmed */ +#define NETXEN_BDINFO_MAGIC 0x12345678 + +/* Max number of Gig ports on a Phantom board */ +#define NETXEN_MAX_PORTS 4 + +typedef enum { + NETXEN_BRDTYPE_P1_BD = 0x0000, + NETXEN_BRDTYPE_P1_SB = 0x0001, + NETXEN_BRDTYPE_P1_SMAX = 0x0002, + NETXEN_BRDTYPE_P1_SOCK = 0x0003, + + NETXEN_BRDTYPE_P2_SOCK_31 = 0x0008, + NETXEN_BRDTYPE_P2_SOCK_35 = 0x0009, + NETXEN_BRDTYPE_P2_SB35_4G = 0x000a, + NETXEN_BRDTYPE_P2_SB31_10G = 0x000b, + NETXEN_BRDTYPE_P2_SB31_2G = 0x000c, + + NETXEN_BRDTYPE_P2_SB31_10G_IMEZ = 0x000d, + NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e, + NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f +} netxen_brdtype_t; + +typedef enum { + NETXEN_BRDMFG_INVENTEC = 1 +} netxen_brdmfg; + +typedef enum { + MEM_ORG_128Mbx4 = 0x0, /* DDR1 only */ + MEM_ORG_128Mbx8 = 0x1, /* DDR1 only */ + MEM_ORG_128Mbx16 = 0x2, /* DDR1 only */ + MEM_ORG_256Mbx4 = 0x3, + MEM_ORG_256Mbx8 = 0x4, + MEM_ORG_256Mbx16 = 0x5, + MEM_ORG_512Mbx4 = 0x6, + MEM_ORG_512Mbx8 = 0x7, + MEM_ORG_512Mbx16 = 0x8, + MEM_ORG_1Gbx4 = 0x9, + MEM_ORG_1Gbx8 = 0xa, + MEM_ORG_1Gbx16 = 0xb, + MEM_ORG_2Gbx4 = 0xc, + MEM_ORG_2Gbx8 = 0xd, + MEM_ORG_2Gbx16 = 0xe, + MEM_ORG_128Mbx32 = 0x10002, /* GDDR only */ + MEM_ORG_256Mbx32 = 0x10005 /* GDDR only */ +} netxen_mn_mem_org_t; + +typedef enum { + MEM_ORG_512Kx36 = 0x0, + MEM_ORG_1Mx36 = 0x1, + MEM_ORG_2Mx36 = 0x2 +} netxen_sn_mem_org_t; + +typedef enum { + MEM_DEPTH_4MB = 0x1, + MEM_DEPTH_8MB = 0x2, + MEM_DEPTH_16MB = 0x3, + MEM_DEPTH_32MB = 0x4, + MEM_DEPTH_64MB = 0x5, + MEM_DEPTH_128MB = 0x6, + MEM_DEPTH_256MB = 0x7, + MEM_DEPTH_512MB = 0x8, + MEM_DEPTH_1GB = 0x9, + MEM_DEPTH_2GB = 0xa, + MEM_DEPTH_4GB = 0xb, + MEM_DEPTH_8GB = 0xc, + MEM_DEPTH_16GB = 0xd, + MEM_DEPTH_32GB = 0xe +} netxen_mem_depth_t; + +struct netxen_board_info { + u32 header_version; + + u32 board_mfg; + u32 board_type; + u32 board_num; + u32 chip_id; + u32 chip_minor; + u32 chip_major; + u32 chip_pkg; + u32 chip_lot; + + u32 port_mask; /* available niu ports */ + u32 peg_mask; /* available pegs */ + u32 icache_ok; /* can we run with icache? */ + u32 dcache_ok; /* can we run with dcache? */ + u32 casper_ok; + + u32 mac_addr_lo_0; + u32 mac_addr_lo_1; + u32 mac_addr_lo_2; + u32 mac_addr_lo_3; + + /* MN-related config */ + u32 mn_sync_mode; /* enable/ sync shift cclk/ sync shift mclk */ + u32 mn_sync_shift_cclk; + u32 mn_sync_shift_mclk; + u32 mn_wb_en; + u32 mn_crystal_freq; /* in MHz */ + u32 mn_speed; /* in MHz */ + u32 mn_org; + u32 mn_depth; + u32 mn_ranks_0; /* ranks per slot */ + u32 mn_ranks_1; /* ranks per slot */ + u32 mn_rd_latency_0; + u32 mn_rd_latency_1; + u32 mn_rd_latency_2; + u32 mn_rd_latency_3; + u32 mn_rd_latency_4; + u32 mn_rd_latency_5; + u32 mn_rd_latency_6; + u32 mn_rd_latency_7; + u32 mn_rd_latency_8; + u32 mn_dll_val[18]; + u32 mn_mode_reg; /* MIU DDR Mode Register */ + u32 mn_ext_mode_reg; /* MIU DDR Extended Mode Register */ + u32 mn_timing_0; /* MIU Memory Control Timing Rgister */ + u32 mn_timing_1; /* MIU Extended Memory Ctrl Timing Register */ + u32 mn_timing_2; /* MIU Extended Memory Ctrl Timing2 Register */ + + /* SN-related config */ + u32 sn_sync_mode; /* enable/ sync shift cclk / sync shift mclk */ + u32 sn_pt_mode; /* pass through mode */ + u32 sn_ecc_en; + u32 sn_wb_en; + u32 sn_crystal_freq; + u32 sn_speed; + u32 sn_org; + u32 sn_depth; + u32 sn_dll_tap; + u32 sn_rd_latency; + + u32 mac_addr_hi_0; + u32 mac_addr_hi_1; + u32 mac_addr_hi_2; + u32 mac_addr_hi_3; + + u32 magic; /* indicates flash has been initialized */ + + u32 mn_rdimm; + u32 mn_dll_override; + +}; + +#define FLASH_NUM_PORTS (4) + +struct netxen_flash_mac_addr { + u32 flash_addr[32]; +}; + +struct netxen_user_old_info { + u8 flash_md5[16]; + u8 crbinit_md5[16]; + u8 brdcfg_md5[16]; + /* bootloader */ + u32 bootld_version; + u32 bootld_size; + u8 bootld_md5[16]; + /* image */ + u32 image_version; + u32 image_size; + u8 image_md5[16]; + /* primary image status */ + u32 primary_status; + u32 secondary_present; + + /* MAC address , 4 ports */ + struct netxen_flash_mac_addr mac_addr[FLASH_NUM_PORTS]; +}; +#define FLASH_NUM_MAC_PER_PORT 32 +struct netxen_user_info { + u8 flash_md5[16 * 64]; + /* bootloader */ + u32 bootld_version; + u32 bootld_size; + /* image */ + u32 image_version; + u32 image_size; + /* primary image status */ + u32 primary_status; + u32 secondary_present; + + /* MAC address , 4 ports, 32 address per port */ + u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT]; + u32 sub_sys_id; + u8 serial_num[32]; + + /* Any user defined data */ +}; + +/* + * Flash Layout - new format. + */ +struct netxen_new_user_info { + u8 flash_md5[16 * 64]; + /* bootloader */ + u32 bootld_version; + u32 bootld_size; + /* image */ + u32 image_version; + u32 image_size; + /* primary image status */ + u32 primary_status; + u32 secondary_present; + + /* MAC address , 4 ports, 32 address per port */ + u64 mac_addr[FLASH_NUM_PORTS * FLASH_NUM_MAC_PER_PORT]; + u32 sub_sys_id; + u8 serial_num[32]; + + /* Any user defined data */ +}; + +#define SECONDARY_IMAGE_PRESENT 0xb3b4b5b6 +#define SECONDARY_IMAGE_ABSENT 0xffffffff +#define PRIMARY_IMAGE_GOOD 0x5a5a5a5a +#define PRIMARY_IMAGE_BAD 0xffffffff + +/* Flash memory map */ +typedef enum { + CRBINIT_START = 0, /* Crbinit section */ + BRDCFG_START = 0x4000, /* board config */ + INITCODE_START = 0x6000, /* pegtune code */ + BOOTLD_START = 0x10000, /* bootld */ + IMAGE_START = 0x43000, /* compressed image */ + SECONDARY_START = 0x200000, /* backup images */ + PXE_START = 0x3E0000, /* user defined region */ + USER_START = 0x3E8000, /* User defined region for new boards */ + FIXED_START = 0x3F0000 /* backup of crbinit */ +} netxen_flash_map_t; + +#define USER_START_OLD PXE_START /* for backward compatibility */ + +#define FLASH_START (CRBINIT_START) +#define INIT_SECTOR (0) +#define PRIMARY_START (BOOTLD_START) +#define FLASH_CRBINIT_SIZE (0x4000) +#define FLASH_BRDCFG_SIZE (sizeof(struct netxen_board_info)) +#define FLASH_USER_SIZE (sizeof(netxen_user_info)/sizeof(u32)) +#define FLASH_SECONDARY_SIZE (USER_START-SECONDARY_START) +#define NUM_PRIMARY_SECTORS (0x20) +#define NUM_CONFIG_SECTORS (1) +#define PFX "netxen: " + +/* Note: Make sure to not call this before adapter->port is valid */ +#if !defined(NETXEN_DEBUG) +#define DPRINTK(klevel, fmt, args...) do { \ + } while (0) +#else +#define DPRINTK(klevel, fmt, args...) do { \ + printk(KERN_##klevel PFX "%s: %s: " fmt, __FUNCTION__,\ + (adapter != NULL && adapter->port != NULL && \ + adapter->port[0] != NULL && \ + adapter->port[0]->netdev != NULL) ? \ + adapter->port[0]->netdev->name : NULL, \ + ## args); } while(0) +#endif + +/* Number of status descriptors to handle per interrupt */ +#define MAX_STATUS_HANDLE (128) + +/* + * netxen_skb_frag{} is to contain mapping info for each SG list. This + * has to be freed when DMA is complete. This is part of netxen_tx_buffer{}. + */ +struct netxen_skb_frag { + u64 dma; + u32 length; +}; + +/* Following defines are for the state of the buffers */ +#define NETXEN_BUFFER_FREE 0 +#define NETXEN_BUFFER_BUSY 1 + +/* + * There will be one netxen_buffer per skb packet. These will be + * used to save the dma info for pci_unmap_page() + */ +struct netxen_cmd_buffer { + struct sk_buff *skb; + struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1]; + u32 total_length; + u32 mss; + u16 port; + u8 cmd; + u8 frag_count; + unsigned long time_stamp; + u32 state; + u32 no_of_descriptors; +}; + +/* In rx_buffer, we do not need multiple fragments as is a single buffer */ +struct netxen_rx_buffer { + struct sk_buff *skb; + u64 dma; + u16 ref_handle; + u16 state; +}; + +/* Board types */ +#define NETXEN_NIC_GBE 0x01 +#define NETXEN_NIC_XGBE 0x02 + +/* + * One hardware_context{} per adapter + * contains interrupt info as well shared hardware info. + */ +struct netxen_hardware_context { + struct pci_dev *pdev; + void __iomem *pci_base; /* base of mapped phantom memory */ + u8 revision_id; + u16 board_type; + u16 max_ports; + struct netxen_board_info boardcfg; + u32 xg_linkup; + /* Address of cmd ring in Phantom */ + struct cmd_desc_type0 *cmd_desc_head; + dma_addr_t cmd_desc_phys_addr; + struct netxen_adapter *adapter; +}; + +#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ +#define ETHERNET_FCS_SIZE 4 + +struct netxen_adapter_stats { + u64 ints; + u64 hostints; + u64 otherints; + u64 process_rcv; + u64 process_xmit; + u64 noxmitdone; + u64 xmitcsummed; + u64 post_called; + u64 posted; + u64 lastposted; + u64 goodskbposts; +}; + +/* + * Rcv Descriptor Context. One such per Rcv Descriptor. There may + * be one Rcv Descriptor for normal packets, one for jumbo and may be others. + */ +struct netxen_rcv_desc_ctx { + u32 flags; + u32 producer; + u32 rcv_pending; /* Num of bufs posted in phantom */ + u32 rcv_free; /* Num of bufs in free list */ + dma_addr_t phys_addr; + struct rcv_desc *desc_head; /* address of rx ring in Phantom */ + u32 max_rx_desc_count; + u32 dma_size; + u32 skb_size; + struct netxen_rx_buffer *rx_buf_arr; /* rx buffers for receive */ + int begin_alloc; +}; + +/* + * Receive context. There is one such structure per instance of the + * receive processing. Any state information that is relevant to + * the receive, and is must be in this structure. The global data may be + * present elsewhere. + */ +struct netxen_recv_context { + struct netxen_rcv_desc_ctx rcv_desc[NUM_RCV_DESC_RINGS]; + u32 status_rx_producer; + u32 status_rx_consumer; + dma_addr_t rcv_status_desc_phys_addr; + struct status_desc *rcv_status_desc_head; +}; + +#define NETXEN_NIC_MSI_ENABLED 0x02 + +struct netxen_drvops; + +struct netxen_adapter { + struct netxen_hardware_context ahw; + int port_count; /* Number of configured ports */ + int active_ports; /* Number of open ports */ + struct netxen_port *port[NETXEN_MAX_PORTS]; /* ptr to each port */ + spinlock_t tx_lock; + spinlock_t lock; + struct work_struct watchdog_task; + struct work_struct tx_timeout_task; + struct timer_list watchdog_timer; + + u32 curr_window; + + u32 cmd_producer; + u32 cmd_consumer; + + u32 last_cmd_consumer; + u32 max_tx_desc_count; + u32 max_rx_desc_count; + u32 max_jumbo_rx_desc_count; + /* Num of instances active on cmd buffer ring */ + u32 proc_cmd_buf_counter; + + u32 num_threads, total_threads; /*Use to keep track of xmit threads */ + + u32 flags; + u32 irq; + int driver_mismatch; + + struct netxen_adapter_stats stats; + + struct netxen_cmd_buffer *cmd_buf_arr; /* Command buffers for xmit */ + + /* + * Receive instances. These can be either one per port, + * or one per peg, etc. + */ + struct netxen_recv_context recv_ctx[MAX_RCV_CTX]; + + int is_up; + int work_done; + struct netxen_drvops *ops; +}; /* netxen_adapter structure */ + +/* Max number of xmit producer threads that can run simultaneously */ +#define MAX_XMIT_PRODUCERS 16 + +struct netxen_port_stats { + u64 rcvdbadskb; + u64 xmitcalled; + u64 xmitedframes; + u64 xmitfinished; + u64 badskblen; + u64 nocmddescriptor; + u64 polled; + u64 uphappy; + u64 updropped; + u64 uplcong; + u64 uphcong; + u64 upmcong; + u64 updunno; + u64 skbfreed; + u64 txdropped; + u64 txnullskb; + u64 csummed; + u64 no_rcv; + u64 rxbytes; + u64 txbytes; +}; + +struct netxen_port { + struct netxen_adapter *adapter; + + u16 portnum; /* GBE port number */ + u16 link_speed; + u16 link_duplex; + u16 link_autoneg; + + int flags; + + struct net_device *netdev; + struct pci_dev *pdev; + struct net_device_stats net_stats; + struct netxen_port_stats stats; +}; + +struct netxen_drvops { + int (*enable_phy_interrupts) (struct netxen_adapter *, int); + int (*disable_phy_interrupts) (struct netxen_adapter *, int); + void (*handle_phy_intr) (struct netxen_adapter *); + int (*macaddr_set) (struct netxen_port *, netxen_ethernet_macaddr_t); + int (*set_mtu) (struct netxen_port *, int); + int (*set_promisc) (struct netxen_adapter *, int, + netxen_niu_prom_mode_t); + int (*unset_promisc) (struct netxen_adapter *, int, + netxen_niu_prom_mode_t); + int (*phy_read) (struct netxen_adapter *, long phy, long reg, u32 *); + int (*phy_write) (struct netxen_adapter *, long phy, long reg, u32 val); + int (*init_port) (struct netxen_adapter *, int); + void (*init_niu) (struct netxen_adapter *); + int (*stop_port) (struct netxen_adapter *, int); +}; + +extern char netxen_nic_driver_name[]; + +int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter, + int port); +int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter, + int port); +int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter, + int port); +int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter, + int port); +int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter, + int port); +int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter, + int port); +void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter); +void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter); +void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, int port, + long enable); +void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, int port, + long enable); +int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, long reg, + __le32 * readval); +int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy, + long reg, __le32 val); + +/* Functions available from netxen_nic_hw.c */ +int netxen_niu_xginit(struct netxen_adapter *); +int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu); +int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu); +void netxen_nic_init_niu_gb(struct netxen_adapter *adapter); +void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw); +void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val); +int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off); +void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value); +void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value); + +int netxen_nic_get_board_info(struct netxen_adapter *adapter); +int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, + int len); +int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, + int len); +void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, + unsigned long off, int data); + +/* Functions from netxen_nic_init.c */ +void netxen_phantom_init(struct netxen_adapter *adapter); +void netxen_load_firmware(struct netxen_adapter *adapter); +int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); +int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); + +/* Functions from netxen_nic_isr.c */ +void netxen_nic_isr_other(struct netxen_adapter *adapter); +void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 port, + u32 link); +void netxen_handle_port_int(struct netxen_adapter *adapter, u32 port, + u32 enable); +void netxen_nic_stop_all_ports(struct netxen_adapter *adapter); +void netxen_initialize_adapter_sw(struct netxen_adapter *adapter); +void netxen_initialize_adapter_hw(struct netxen_adapter *adapter); +void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); +int netxen_init_firmware(struct netxen_adapter *adapter); +void netxen_free_hw_resources(struct netxen_adapter *adapter); +void netxen_tso_check(struct netxen_adapter *adapter, + struct cmd_desc_type0 *desc, struct sk_buff *skb); +int netxen_nic_hw_resources(struct netxen_adapter *adapter); +void netxen_nic_clear_stats(struct netxen_adapter *adapter); +int +netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, + struct netxen_port *port); +int netxen_nic_rx_has_work(struct netxen_adapter *adapter); +int netxen_nic_tx_has_work(struct netxen_adapter *adapter); +void netxen_watchdog_task(unsigned long v); +void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, + u32 ringid); +void netxen_process_cmd_ring(unsigned long data); +u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max); +void netxen_nic_set_multi(struct net_device *netdev); +int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); +int netxen_nic_set_mac(struct net_device *netdev, void *p); +struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev); + +static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) +{ + /* + * ISR_INT_MASK: Can be read from window 0 or 1. + */ + writel(0x7ff, (void __iomem *)(adapter->ahw.pci_base + ISR_INT_MASK)); +} + +static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) +{ + u32 mask; + + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + mask = 0x77b; + break; + case NETXEN_NIC_XGBE: + mask = 0x77f; + break; + default: + mask = 0x7ff; + break; + } + + writel(mask, (void __iomem *)(adapter->ahw.pci_base + ISR_INT_MASK)); + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + mask = 0xbff; + writel(mask, (void __iomem *) + (adapter->ahw.pci_base + ISR_INT_TARGET_MASK)); + } +} + +int netxen_is_flash_supported(struct netxen_adapter *adapter); +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]); + +extern void netxen_change_ringparam(struct netxen_adapter *adapter); +extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, + int *valp); + +extern struct ethtool_ops netxen_nic_ethtool_ops; + +#endif /* __NETXEN_NIC_H_ */ diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c new file mode 100644 index 000000000000..caf6cc15b241 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * ethtool support for netxen nic + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "netxen_nic_hw.h" +#include "netxen_nic.h" +#include "netxen_nic_phan_reg.h" +#include "netxen_nic_ioctl.h" + +struct netxen_nic_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define NETXEN_NIC_STAT(m) sizeof(((struct netxen_port *)0)->m), \ + offsetof(struct netxen_port, m) + +static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { + {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)}, + {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)}, + {"xmited_frames", NETXEN_NIC_STAT(stats.xmitedframes)}, + {"xmit_finished", NETXEN_NIC_STAT(stats.xmitfinished)}, + {"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)}, + {"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)}, + {"polled", NETXEN_NIC_STAT(stats.polled)}, + {"uphappy", NETXEN_NIC_STAT(stats.uphappy)}, + {"updropped", NETXEN_NIC_STAT(stats.updropped)}, + {"uplcong", NETXEN_NIC_STAT(stats.uplcong)}, + {"uphcong", NETXEN_NIC_STAT(stats.uphcong)}, + {"upmcong", NETXEN_NIC_STAT(stats.upmcong)}, + {"updunno", NETXEN_NIC_STAT(stats.updunno)}, + {"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)}, + {"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)}, + {"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)}, + {"csummed", NETXEN_NIC_STAT(stats.csummed)}, + {"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)}, + {"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)}, + {"tx_bytes", NETXEN_NIC_STAT(stats.txbytes)}, +}; + +#define NETXEN_NIC_STATS_LEN \ + sizeof(netxen_nic_gstrings_stats) / sizeof(struct netxen_nic_stats) + +static const char netxen_nic_gstrings_test[][ETH_GSTRING_LEN] = { + "Register_Test_offline", "EEPROM_Test_offline", + "Interrupt_Test_offline", "Loopback_Test_offline", + "Link_Test_on_offline" +}; + +#define NETXEN_NIC_TEST_LEN sizeof(netxen_nic_gstrings_test) / ETH_GSTRING_LEN + +#define NETXEN_NIC_REGS_COUNT 42 +#define NETXEN_NIC_REGS_LEN (NETXEN_NIC_REGS_COUNT * sizeof(__le32)) +#define NETXEN_MAX_EEPROM_LEN 1024 + +static int netxen_nic_get_eeprom_len(struct net_device *dev) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + int n; + + if ((netxen_rom_fast_read(adapter, 0, &n) == 0) + && (n & NETXEN_ROM_ROUNDUP)) { + n &= ~NETXEN_ROM_ROUNDUP; + if (n < NETXEN_MAX_EEPROM_LEN) + return n; + } + return 0; +} + +static void +netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + uint32_t fw_major = 0; + uint32_t fw_minor = 0; + uint32_t fw_build = 0; + + strncpy(drvinfo->driver, "netxen_nic", 32); + strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); + fw_major = readl(NETXEN_CRB_NORMALIZE(adapter, + NETXEN_FW_VERSION_MAJOR)); + fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter, + NETXEN_FW_VERSION_MINOR)); + fw_build = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB)); + sprintf(drvinfo->fw_version, "%d.%d.%d", fw_major, fw_minor, fw_build); + + strncpy(drvinfo->bus_info, pci_name(port->pdev), 32); + drvinfo->n_stats = NETXEN_NIC_STATS_LEN; + drvinfo->testinfo_len = NETXEN_NIC_TEST_LEN; + drvinfo->regdump_len = NETXEN_NIC_REGS_LEN; + drvinfo->eedump_len = netxen_nic_get_eeprom_len(dev); +} + +static int +netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + + /* read which mode */ + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + ecmd->supported = (SUPPORTED_10baseT_Half | + SUPPORTED_10baseT_Full | + SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Half | + SUPPORTED_1000baseT_Full | + SUPPORTED_TP | + SUPPORTED_MII | SUPPORTED_Autoneg); + + ecmd->advertising = (ADVERTISED_100baseT_Half | + ADVERTISED_100baseT_Full | + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full | + ADVERTISED_TP | + ADVERTISED_MII | ADVERTISED_Autoneg); + + ecmd->port = PORT_TP; + + if (netif_running(dev)) { + ecmd->speed = port->link_speed; + ecmd->duplex = port->link_duplex; + } else + return -EIO; /* link absent */ + + ecmd->phy_address = port->portnum; + ecmd->transceiver = XCVR_EXTERNAL; + + /* get autoneg settings */ + ecmd->autoneg = port->link_autoneg; + return 0; + } + + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + ecmd->supported = (SUPPORTED_TP | + SUPPORTED_1000baseT_Full | + SUPPORTED_10000baseT_Full); + ecmd->advertising = (ADVERTISED_TP | + ADVERTISED_1000baseT_Full | + ADVERTISED_10000baseT_Full); + ecmd->port = PORT_TP; + + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + ecmd->phy_address = port->portnum; + ecmd->transceiver = XCVR_EXTERNAL; + ecmd->autoneg = AUTONEG_DISABLE; + return 0; + } + + return -EIO; +} + +static int +netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + __le32 status; + + /* read which mode */ + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + /* autonegotiation */ + if (adapter->ops->phy_write + && adapter->ops->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (__le32) ecmd->autoneg) != 0) + return -EIO; + else + port->link_autoneg = ecmd->autoneg; + + if (adapter->ops->phy_read + && adapter->ops->phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) != 0) + return -EIO; + + /* speed */ + switch (ecmd->speed) { + case SPEED_10: + netxen_set_phy_speed(status, 0); + break; + case SPEED_100: + netxen_set_phy_speed(status, 1); + break; + case SPEED_1000: + netxen_set_phy_speed(status, 2); + break; + } + /* set duplex mode */ + if (ecmd->duplex == DUPLEX_HALF) + netxen_clear_phy_duplex(status); + if (ecmd->duplex == DUPLEX_FULL) + netxen_set_phy_duplex(status); + if (adapter->ops->phy_write + && adapter->ops->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + *((int *)&status)) != 0) + return -EIO; + else { + port->link_speed = ecmd->speed; + port->link_duplex = ecmd->duplex; + } + } else + return -EOPNOTSUPP; + + if (netif_running(dev)) { + dev->stop(dev); + dev->open(dev); + } + return 0; +} + +static int netxen_nic_get_regs_len(struct net_device *dev) +{ + return NETXEN_NIC_REGS_LEN; +} + +struct netxen_niu_regs { + __le32 reg[NETXEN_NIC_REGS_COUNT]; +}; + +static struct netxen_niu_regs niu_registers[] = { + { + /* GB Mode */ + { + NETXEN_NIU_GB_SERDES_RESET, + NETXEN_NIU_GB0_MII_MODE, + NETXEN_NIU_GB1_MII_MODE, + NETXEN_NIU_GB2_MII_MODE, + NETXEN_NIU_GB3_MII_MODE, + NETXEN_NIU_GB0_GMII_MODE, + NETXEN_NIU_GB1_GMII_MODE, + NETXEN_NIU_GB2_GMII_MODE, + NETXEN_NIU_GB3_GMII_MODE, + NETXEN_NIU_REMOTE_LOOPBACK, + NETXEN_NIU_GB0_HALF_DUPLEX, + NETXEN_NIU_GB1_HALF_DUPLEX, + NETXEN_NIU_RESET_SYS_FIFOS, + NETXEN_NIU_GB_CRC_DROP, + NETXEN_NIU_GB_DROP_WRONGADDR, + NETXEN_NIU_TEST_MUX_CTL, + + NETXEN_NIU_GB_MAC_CONFIG_0(0), + NETXEN_NIU_GB_MAC_CONFIG_1(0), + NETXEN_NIU_GB_HALF_DUPLEX_CTRL(0), + NETXEN_NIU_GB_MAX_FRAME_SIZE(0), + NETXEN_NIU_GB_TEST_REG(0), + NETXEN_NIU_GB_MII_MGMT_CONFIG(0), + NETXEN_NIU_GB_MII_MGMT_COMMAND(0), + NETXEN_NIU_GB_MII_MGMT_ADDR(0), + NETXEN_NIU_GB_MII_MGMT_CTRL(0), + NETXEN_NIU_GB_MII_MGMT_STATUS(0), + NETXEN_NIU_GB_MII_MGMT_INDICATE(0), + NETXEN_NIU_GB_INTERFACE_CTRL(0), + NETXEN_NIU_GB_INTERFACE_STATUS(0), + NETXEN_NIU_GB_STATION_ADDR_0(0), + NETXEN_NIU_GB_STATION_ADDR_1(0), + -1, + } + }, + { + /* XG Mode */ + { + NETXEN_NIU_XG_SINGLE_TERM, + NETXEN_NIU_XG_DRIVE_HI, + NETXEN_NIU_XG_DRIVE_LO, + NETXEN_NIU_XG_DTX, + NETXEN_NIU_XG_DEQ, + NETXEN_NIU_XG_WORD_ALIGN, + NETXEN_NIU_XG_RESET, + NETXEN_NIU_XG_POWER_DOWN, + NETXEN_NIU_XG_RESET_PLL, + NETXEN_NIU_XG_SERDES_LOOPBACK, + NETXEN_NIU_XG_DO_BYTE_ALIGN, + NETXEN_NIU_XG_TX_ENABLE, + NETXEN_NIU_XG_RX_ENABLE, + NETXEN_NIU_XG_STATUS, + NETXEN_NIU_XG_PAUSE_THRESHOLD, + NETXEN_NIU_XGE_CONFIG_0, + NETXEN_NIU_XGE_CONFIG_1, + NETXEN_NIU_XGE_IPG, + NETXEN_NIU_XGE_STATION_ADDR_0_HI, + NETXEN_NIU_XGE_STATION_ADDR_0_1, + NETXEN_NIU_XGE_STATION_ADDR_1_LO, + NETXEN_NIU_XGE_STATUS, + NETXEN_NIU_XGE_MAX_FRAME_SIZE, + NETXEN_NIU_XGE_PAUSE_FRAME_VALUE, + NETXEN_NIU_XGE_TX_BYTE_CNT, + NETXEN_NIU_XGE_TX_FRAME_CNT, + NETXEN_NIU_XGE_RX_BYTE_CNT, + NETXEN_NIU_XGE_RX_FRAME_CNT, + NETXEN_NIU_XGE_AGGR_ERROR_CNT, + NETXEN_NIU_XGE_MULTICAST_FRAME_CNT, + NETXEN_NIU_XGE_UNICAST_FRAME_CNT, + NETXEN_NIU_XGE_CRC_ERROR_CNT, + NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR, + NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR, + NETXEN_NIU_XGE_LOCAL_ERROR_CNT, + NETXEN_NIU_XGE_REMOTE_ERROR_CNT, + NETXEN_NIU_XGE_CONTROL_CHAR_CNT, + NETXEN_NIU_XGE_PAUSE_FRAME_CNT, + -1, + } + } +}; + +static void +netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + __le32 mode, *regs_buff = p; + void __iomem *addr; + int i, window; + + memset(p, 0, NETXEN_NIC_REGS_LEN); + regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) | + (port->pdev)->device; + /* which mode */ + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_MODE, ®s_buff[0]); + mode = regs_buff[0]; + + /* Common registers to all the modes */ + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER, + ®s_buff[2]); + /* GB/XGB Mode */ + mode = (mode / 2) - 1; + window = 0; + if (mode <= 1) { + for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) { + /* GB: port specific registers */ + if (mode == 0 && i >= 19) + window = port->portnum * 0x10000; + + NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode]. + reg[i - 3] + window, + ®s_buff[i]); + } + + } +} + +static void +netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) +{ + wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; + wol->wolopts = 0; /* options can be added depending upon the mode */ +} + +static u32 netxen_nic_get_link(struct net_device *dev) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + __le32 status; + + /* read which mode */ + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + if (adapter->ops->phy_read + && adapter->ops->phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) != 0) + return -EIO; + else + return (netxen_get_phy_link(status)); + } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + int val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); + return val == XG_LINK_UP; + } + return -EIO; +} + +static int +netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, + u8 * bytes) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + int offset; + + if (eeprom->len == 0) + return -EINVAL; + + eeprom->magic = (port->pdev)->vendor | ((port->pdev)->device << 16); + for (offset = 0; offset < eeprom->len; offset++) + if (netxen_rom_fast_read + (adapter, (8 * offset) + 8, (int *)eeprom->data) == -1) + return -EIO; + return 0; +} + +static void +netxen_nic_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + int i, j; + + ring->rx_pending = 0; + for (i = 0; i < MAX_RCV_CTX; ++i) { + for (j = 0; j < NUM_RCV_DESC_RINGS; j++) + ring->rx_pending += + adapter->recv_ctx[i].rcv_desc[j].rcv_pending; + } + + ring->rx_max_pending = adapter->max_rx_desc_count; + ring->tx_max_pending = adapter->max_tx_desc_count; + ring->rx_mini_max_pending = 0; + ring->rx_mini_pending = 0; + ring->rx_jumbo_max_pending = 0; + ring->rx_jumbo_pending = 0; +} + +static void +netxen_nic_get_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + __le32 val; + + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + /* get flow control settings */ + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum), + (u32 *) & val); + pause->rx_pause = netxen_gb_get_rx_flowctl(val); + pause->tx_pause = netxen_gb_get_tx_flowctl(val); + /* get autoneg settings */ + pause->autoneg = port->link_autoneg; + } +} + +static int +netxen_nic_set_pauseparam(struct net_device *dev, + struct ethtool_pauseparam *pause) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + __le32 val; + unsigned int autoneg; + + /* read mode */ + if (adapter->ahw.board_type == NETXEN_NIC_GBE) { + /* set flow control */ + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum), + (u32 *) & val); + if (pause->tx_pause) + netxen_gb_tx_flowctl(val); + else + netxen_gb_unset_tx_flowctl(val); + if (pause->rx_pause) + netxen_gb_rx_flowctl(val); + else + netxen_gb_unset_rx_flowctl(val); + + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port->portnum), + *(u32 *) (&val)); + /* set autoneg */ + autoneg = pause->autoneg; + if (adapter->ops->phy_write + && adapter->ops->phy_write(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (__le32) autoneg) != 0) + return -EIO; + else { + port->link_autoneg = pause->autoneg; + return 0; + } + } else + return -EOPNOTSUPP; +} + +static int netxen_nic_reg_test(struct net_device *dev) +{ + struct netxen_port *port = netdev_priv(dev); + struct netxen_adapter *adapter = port->adapter; + u32 data_read, data_written, save; + __le32 mode; + + /* + * first test the "Read Only" registers by writing which mode + */ + netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode); + if (netxen_get_niu_enable_ge(mode)) { /* GB Mode */ + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum), + &data_read); + + save = data_read; + if (data_read) + data_written = data_read & 0xDEADBEEF; + else + data_written = 0xDEADBEEF; + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(port-> + portnum), + data_written); + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(port->portnum), + &data_read); + + if (data_written == data_read) { + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(port-> + portnum), + save); + + return 0; + } + + /* netxen_niu_gb_mii_mgmt_indicators is read only */ + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(port-> + portnum), + &data_read); + + save = data_read; + if (data_read) + data_written = data_read & 0xDEADBEEF; + else + data_written = 0xDEADBEEF; + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(port-> + portnum), + data_written); + + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(port-> + portnum), + &data_read); + + if (data_written == data_read) { + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE + (port->portnum), save); + return 0; + } + + /* netxen_niu_gb_interface_status is read only */ + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_INTERFACE_STATUS(port-> + portnum), + &data_read); + + save = data_read; + if (data_read) + data_written = data_read & 0xDEADBEEF; + else + data_written = 0xDEADBEEF; + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_INTERFACE_STATUS(port-> + portnum), + data_written); + + netxen_nic_read_w0(adapter, + NETXEN_NIU_GB_INTERFACE_STATUS(port-> + portnum), + &data_read); + + if (data_written == data_read) { + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_INTERFACE_STATUS + (port->portnum), save); + + return 0; + } + } /* GB Mode */ + return 1; +} + +static int netxen_nic_diag_test_count(struct net_device *dev) +{ + return NETXEN_NIC_TEST_LEN; +} + +static void +netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, + u64 * data) +{ + if (eth_test->flags == ETH_TEST_FL_OFFLINE) { /* offline tests */ + /* link test */ + if (!(data[4] = (u64) netxen_nic_get_link(dev))) + eth_test->flags |= ETH_TEST_FL_FAILED; + + if (netif_running(dev)) + dev->stop(dev); + + /* register tests */ + if (!(data[0] = netxen_nic_reg_test(dev))) + eth_test->flags |= ETH_TEST_FL_FAILED; + /* other tests pass as of now */ + data[1] = data[2] = data[3] = 1; + if (netif_running(dev)) + dev->open(dev); + } else { /* online tests */ + /* link test */ + if (!(data[4] = (u64) netxen_nic_get_link(dev))) + eth_test->flags |= ETH_TEST_FL_FAILED; + + /* other tests pass by default */ + data[0] = data[1] = data[2] = data[3] = 1; + } +} + +static void +netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data) +{ + int index; + + switch (stringset) { + case ETH_SS_TEST: + memcpy(data, *netxen_nic_gstrings_test, + NETXEN_NIC_TEST_LEN * ETH_GSTRING_LEN); + break; + case ETH_SS_STATS: + for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) { + memcpy(data + index * ETH_GSTRING_LEN, + netxen_nic_gstrings_stats[index].stat_string, + ETH_GSTRING_LEN); + } + break; + } +} + +static int netxen_nic_get_stats_count(struct net_device *dev) +{ + return NETXEN_NIC_STATS_LEN; +} + +static void +netxen_nic_get_ethtool_stats(struct net_device *dev, + struct ethtool_stats *stats, u64 * data) +{ + struct netxen_port *port = netdev_priv(dev); + int index; + + for (index = 0; index < NETXEN_NIC_STATS_LEN; index++) { + char *p = + (char *)port + netxen_nic_gstrings_stats[index].stat_offset; + data[index] = + (netxen_nic_gstrings_stats[index].sizeof_stat == + sizeof(u64)) ? *(u64 *) p : *(u32 *) p; + } + +} + +struct ethtool_ops netxen_nic_ethtool_ops = { + .get_settings = netxen_nic_get_settings, + .set_settings = netxen_nic_set_settings, + .get_drvinfo = netxen_nic_get_drvinfo, + .get_regs_len = netxen_nic_get_regs_len, + .get_regs = netxen_nic_get_regs, + .get_wol = netxen_nic_get_wol, + .get_link = netxen_nic_get_link, + .get_eeprom_len = netxen_nic_get_eeprom_len, + .get_eeprom = netxen_nic_get_eeprom, + .get_ringparam = netxen_nic_get_ringparam, + .get_pauseparam = netxen_nic_get_pauseparam, + .set_pauseparam = netxen_nic_set_pauseparam, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, + .self_test_count = netxen_nic_diag_test_count, + .self_test = netxen_nic_diag_test, + .get_strings = netxen_nic_get_strings, + .get_stats_count = netxen_nic_get_stats_count, + .get_ethtool_stats = netxen_nic_get_ethtool_stats, + .get_perm_addr = ethtool_op_get_perm_addr, +}; diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h new file mode 100644 index 000000000000..965cf625ba4b --- /dev/null +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -0,0 +1,618 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + */ + +#ifndef __NETXEN_NIC_HDR_H_ +#define __NETXEN_NIC_HDR_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for memset */ + +/* + * The basic unit of access when reading/writing control registers. + */ + +typedef __le32 netxen_crbword_t; /* single word in CRB space */ + +enum { + NETXEN_HW_H0_CH_HUB_ADR = 0x05, + NETXEN_HW_H1_CH_HUB_ADR = 0x0E, + NETXEN_HW_H2_CH_HUB_ADR = 0x03, + NETXEN_HW_H3_CH_HUB_ADR = 0x01, + NETXEN_HW_H4_CH_HUB_ADR = 0x06, + NETXEN_HW_H5_CH_HUB_ADR = 0x07, + NETXEN_HW_H6_CH_HUB_ADR = 0x08 +}; + +/* Hub 0 */ +enum { + NETXEN_HW_MN_CRB_AGT_ADR = 0x15, + NETXEN_HW_MS_CRB_AGT_ADR = 0x25 +}; + +/* Hub 1 */ +enum { + NETXEN_HW_PS_CRB_AGT_ADR = 0x73, + NETXEN_HW_SS_CRB_AGT_ADR = 0x20, + NETXEN_HW_RPMX3_CRB_AGT_ADR = 0x0b, + NETXEN_HW_QMS_CRB_AGT_ADR = 0x00, + NETXEN_HW_SQGS0_CRB_AGT_ADR = 0x01, + NETXEN_HW_SQGS1_CRB_AGT_ADR = 0x02, + NETXEN_HW_SQGS2_CRB_AGT_ADR = 0x03, + NETXEN_HW_SQGS3_CRB_AGT_ADR = 0x04, + NETXEN_HW_C2C0_CRB_AGT_ADR = 0x58, + NETXEN_HW_C2C1_CRB_AGT_ADR = 0x59, + NETXEN_HW_C2C2_CRB_AGT_ADR = 0x5a, + NETXEN_HW_RPMX2_CRB_AGT_ADR = 0x0a, + NETXEN_HW_RPMX4_CRB_AGT_ADR = 0x0c, + NETXEN_HW_RPMX7_CRB_AGT_ADR = 0x0f, + NETXEN_HW_RPMX9_CRB_AGT_ADR = 0x12, + NETXEN_HW_SMB_CRB_AGT_ADR = 0x18 +}; + +/* Hub 2 */ +enum { + NETXEN_HW_NIU_CRB_AGT_ADR = 0x31, + NETXEN_HW_I2C0_CRB_AGT_ADR = 0x19, + NETXEN_HW_I2C1_CRB_AGT_ADR = 0x29, + + NETXEN_HW_SN_CRB_AGT_ADR = 0x10, + NETXEN_HW_I2Q_CRB_AGT_ADR = 0x20, + NETXEN_HW_LPC_CRB_AGT_ADR = 0x22, + NETXEN_HW_ROMUSB_CRB_AGT_ADR = 0x21, + NETXEN_HW_QM_CRB_AGT_ADR = 0x66, + NETXEN_HW_SQG0_CRB_AGT_ADR = 0x60, + NETXEN_HW_SQG1_CRB_AGT_ADR = 0x61, + NETXEN_HW_SQG2_CRB_AGT_ADR = 0x62, + NETXEN_HW_SQG3_CRB_AGT_ADR = 0x63, + NETXEN_HW_RPMX1_CRB_AGT_ADR = 0x09, + NETXEN_HW_RPMX5_CRB_AGT_ADR = 0x0d, + NETXEN_HW_RPMX6_CRB_AGT_ADR = 0x0e, + NETXEN_HW_RPMX8_CRB_AGT_ADR = 0x11 +}; + +/* Hub 3 */ +enum { + NETXEN_HW_PH_CRB_AGT_ADR = 0x1A, + NETXEN_HW_SRE_CRB_AGT_ADR = 0x50, + NETXEN_HW_EG_CRB_AGT_ADR = 0x51, + NETXEN_HW_RPMX0_CRB_AGT_ADR = 0x08 +}; + +/* Hub 4 */ +enum { + NETXEN_HW_PEGN0_CRB_AGT_ADR = 0x40, + NETXEN_HW_PEGN1_CRB_AGT_ADR, + NETXEN_HW_PEGN2_CRB_AGT_ADR, + NETXEN_HW_PEGN3_CRB_AGT_ADR, + NETXEN_HW_PEGNI_CRB_AGT_ADR, + NETXEN_HW_PEGND_CRB_AGT_ADR, + NETXEN_HW_PEGNC_CRB_AGT_ADR, + NETXEN_HW_PEGR0_CRB_AGT_ADR, + NETXEN_HW_PEGR1_CRB_AGT_ADR, + NETXEN_HW_PEGR2_CRB_AGT_ADR, + NETXEN_HW_PEGR3_CRB_AGT_ADR +}; + +/* Hub 5 */ +enum { + NETXEN_HW_PEGS0_CRB_AGT_ADR = 0x40, + NETXEN_HW_PEGS1_CRB_AGT_ADR, + NETXEN_HW_PEGS2_CRB_AGT_ADR, + NETXEN_HW_PEGS3_CRB_AGT_ADR, + NETXEN_HW_PEGSI_CRB_AGT_ADR, + NETXEN_HW_PEGSD_CRB_AGT_ADR, + NETXEN_HW_PEGSC_CRB_AGT_ADR +}; + +/* Hub 6 */ +enum { + NETXEN_HW_CAS0_CRB_AGT_ADR = 0x46, + NETXEN_HW_CAS1_CRB_AGT_ADR = 0x47, + NETXEN_HW_CAS2_CRB_AGT_ADR = 0x48, + NETXEN_HW_CAS3_CRB_AGT_ADR = 0x49, + NETXEN_HW_NCM_CRB_AGT_ADR = 0x16, + NETXEN_HW_TMR_CRB_AGT_ADR = 0x17, + NETXEN_HW_XDMA_CRB_AGT_ADR = 0x05, + NETXEN_HW_OCM0_CRB_AGT_ADR = 0x06, + NETXEN_HW_OCM1_CRB_AGT_ADR = 0x07 +}; + +/* Floaters - non existent modules */ +#define NETXEN_HW_EFC_RPMX0_CRB_AGT_ADR 0x67 + +/* This field defines PCI/X adr [25:20] of agents on the CRB */ +enum { + NETXEN_HW_PX_MAP_CRB_PH = 0, + NETXEN_HW_PX_MAP_CRB_PS, + NETXEN_HW_PX_MAP_CRB_MN, + NETXEN_HW_PX_MAP_CRB_MS, + NETXEN_HW_PX_MAP_CRB_PGR1, + NETXEN_HW_PX_MAP_CRB_SRE, + NETXEN_HW_PX_MAP_CRB_NIU, + NETXEN_HW_PX_MAP_CRB_QMN, + NETXEN_HW_PX_MAP_CRB_SQN0, + NETXEN_HW_PX_MAP_CRB_SQN1, + NETXEN_HW_PX_MAP_CRB_SQN2, + NETXEN_HW_PX_MAP_CRB_SQN3, + NETXEN_HW_PX_MAP_CRB_QMS, + NETXEN_HW_PX_MAP_CRB_SQS0, + NETXEN_HW_PX_MAP_CRB_SQS1, + NETXEN_HW_PX_MAP_CRB_SQS2, + NETXEN_HW_PX_MAP_CRB_SQS3, + NETXEN_HW_PX_MAP_CRB_PGN0, + NETXEN_HW_PX_MAP_CRB_PGN1, + NETXEN_HW_PX_MAP_CRB_PGN2, + NETXEN_HW_PX_MAP_CRB_PGN3, + NETXEN_HW_PX_MAP_CRB_PGND, + NETXEN_HW_PX_MAP_CRB_PGNI, + NETXEN_HW_PX_MAP_CRB_PGS0, + NETXEN_HW_PX_MAP_CRB_PGS1, + NETXEN_HW_PX_MAP_CRB_PGS2, + NETXEN_HW_PX_MAP_CRB_PGS3, + NETXEN_HW_PX_MAP_CRB_PGSD, + NETXEN_HW_PX_MAP_CRB_PGSI, + NETXEN_HW_PX_MAP_CRB_SN, + NETXEN_HW_PX_MAP_CRB_PGR2, + NETXEN_HW_PX_MAP_CRB_EG, + NETXEN_HW_PX_MAP_CRB_PH2, + NETXEN_HW_PX_MAP_CRB_PS2, + NETXEN_HW_PX_MAP_CRB_CAM, + NETXEN_HW_PX_MAP_CRB_CAS0, + NETXEN_HW_PX_MAP_CRB_CAS1, + NETXEN_HW_PX_MAP_CRB_CAS2, + NETXEN_HW_PX_MAP_CRB_C2C0, + NETXEN_HW_PX_MAP_CRB_C2C1, + NETXEN_HW_PX_MAP_CRB_TIMR, + NETXEN_HW_PX_MAP_CRB_PGR3, + NETXEN_HW_PX_MAP_CRB_RPMX1, + NETXEN_HW_PX_MAP_CRB_RPMX2, + NETXEN_HW_PX_MAP_CRB_RPMX3, + NETXEN_HW_PX_MAP_CRB_RPMX4, + NETXEN_HW_PX_MAP_CRB_RPMX5, + NETXEN_HW_PX_MAP_CRB_RPMX6, + NETXEN_HW_PX_MAP_CRB_RPMX7, + NETXEN_HW_PX_MAP_CRB_XDMA, + NETXEN_HW_PX_MAP_CRB_I2Q, + NETXEN_HW_PX_MAP_CRB_ROMUSB, + NETXEN_HW_PX_MAP_CRB_CAS3, + NETXEN_HW_PX_MAP_CRB_RPMX0, + NETXEN_HW_PX_MAP_CRB_RPMX8, + NETXEN_HW_PX_MAP_CRB_RPMX9, + NETXEN_HW_PX_MAP_CRB_OCM0, + NETXEN_HW_PX_MAP_CRB_OCM1, + NETXEN_HW_PX_MAP_CRB_SMB, + NETXEN_HW_PX_MAP_CRB_I2C0, + NETXEN_HW_PX_MAP_CRB_I2C1, + NETXEN_HW_PX_MAP_CRB_LPC, + NETXEN_HW_PX_MAP_CRB_PGNC, + NETXEN_HW_PX_MAP_CRB_PGR0 +}; + +/* This field defines CRB adr [31:20] of the agents */ + +#define NETXEN_HW_CRB_HUB_AGT_ADR_MN \ + ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MN_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PH \ + ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_PH_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_MS \ + ((NETXEN_HW_H0_CH_HUB_ADR << 7) | NETXEN_HW_MS_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_PS \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_PS_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SS \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SS_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX3_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_QMS \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_QMS_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS0 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS1 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS2 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQS3 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SQGS3_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C0 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_C2C1 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_C2C1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX4_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX7_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9 \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_RPMX9_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SMB \ + ((NETXEN_HW_H1_CH_HUB_ADR << 7) | NETXEN_HW_SMB_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_NIU \ + ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_NIU_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C0 \ + ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_I2C1 \ + ((NETXEN_HW_H2_CH_HUB_ADR << 7) | NETXEN_HW_I2C1_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_SRE \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SRE_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_EG \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_EG_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_QMN \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_QM_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN0 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN1 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN2 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SQN3 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_SQG3_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX5_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX6_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_RPMX8_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS0 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS1 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS2 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_CAS3 \ + ((NETXEN_HW_H3_CH_HUB_ADR << 7) | NETXEN_HW_CAS3_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNI \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNI_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGND \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGND_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN0 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN1 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN2 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGN3 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGN3_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGNC \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGNC_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR0 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR1 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR2 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGR3 \ + ((NETXEN_HW_H4_CH_HUB_ADR << 7) | NETXEN_HW_PEGR3_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSI \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSI_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSD \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSD_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS0 \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS1 \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS2 \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS2_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGS3 \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGS3_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_PGSC \ + ((NETXEN_HW_H5_CH_HUB_ADR << 7) | NETXEN_HW_PEGSC_CRB_AGT_ADR) + +#define NETXEN_HW_CRB_HUB_AGT_ADR_CAM \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_NCM_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_TIMR \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_TMR_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_XDMA \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_XDMA_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_SN \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_SN_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_I2Q \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_I2Q_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_ROMUSB_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM0 \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM0_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_OCM1 \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_OCM1_CRB_AGT_ADR) +#define NETXEN_HW_CRB_HUB_AGT_ADR_LPC \ + ((NETXEN_HW_H6_CH_HUB_ADR << 7) | NETXEN_HW_LPC_CRB_AGT_ADR) + +/* + * MAX_RCV_CTX : The number of receive contexts that are available on + * the phantom. + */ +#define MAX_RCV_CTX 1 + +#define NETXEN_SRE_INT_STATUS (NETXEN_CRB_SRE + 0x00034) +#define NETXEN_SRE_PBI_ACTIVE_STATUS (NETXEN_CRB_SRE + 0x01014) +#define NETXEN_SRE_L1RE_CTL (NETXEN_CRB_SRE + 0x03000) +#define NETXEN_SRE_L2RE_CTL (NETXEN_CRB_SRE + 0x05000) +#define NETXEN_SRE_BUF_CTL (NETXEN_CRB_SRE + 0x01000) + +#define NETXEN_DMA_BASE(U) (NETXEN_CRB_PCIX_MD + 0x20000 + ((U)<<16)) +#define NETXEN_DMA_COMMAND(U) (NETXEN_DMA_BASE(U) + 0x00008) + +#define NETXEN_I2Q_CLR_PCI_HI (NETXEN_CRB_I2Q + 0x00034) + +#define PEG_NETWORK_BASE(N) (NETXEN_CRB_PEG_NET_0 + (((N)&3) << 20)) +#define CRB_REG_EX_PC 0x3c + +#define ROMUSB_GLB (NETXEN_CRB_ROMUSB + 0x00000) +#define ROMUSB_ROM (NETXEN_CRB_ROMUSB + 0x10000) + +#define NETXEN_ROMUSB_GLB_STATUS (ROMUSB_GLB + 0x0004) +#define NETXEN_ROMUSB_GLB_SW_RESET (ROMUSB_GLB + 0x0008) +#define NETXEN_ROMUSB_GLB_PAD_GPIO_I (ROMUSB_GLB + 0x000c) +#define NETXEN_ROMUSB_GLB_CAS_RST (ROMUSB_GLB + 0x0038) +#define NETXEN_ROMUSB_GLB_TEST_MUX_SEL (ROMUSB_GLB + 0x0044) +#define NETXEN_ROMUSB_GLB_PEGTUNE_DONE (ROMUSB_GLB + 0x005c) +#define NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL (ROMUSB_GLB + 0x00A8) + +#define NETXEN_ROMUSB_GPIO(n) (ROMUSB_GLB + 0x60 + (4 * (n))) + +#define NETXEN_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) +#define NETXEN_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) +#define NETXEN_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) +#define NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) +#define NETXEN_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) + +/* Lock IDs for ROM lock */ +#define ROM_LOCK_DRIVER 0x0d417340 + +#define NETXEN_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */ +#define NETXEN_PCI_CRB_WINDOW(A) \ + (NETXEN_PCI_CRBSPACE + (A)*NETXEN_PCI_CRB_WINDOWSIZE) + +#define NETXEN_CRB_NIU NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_NIU) +#define NETXEN_CRB_SRE NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SRE) +#define NETXEN_CRB_ROMUSB \ + NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB) +#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q) +#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64) + +#define NETXEN_CRB_PCIX_HOST NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH) +#define NETXEN_CRB_PCIX_HOST2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PH2) +#define NETXEN_CRB_PEG_NET_0 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN0) +#define NETXEN_CRB_PEG_NET_1 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN1) +#define NETXEN_CRB_PEG_NET_2 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN2) +#define NETXEN_CRB_PEG_NET_3 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGN3) +#define NETXEN_CRB_PEG_NET_D NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGND) +#define NETXEN_CRB_PEG_NET_I NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PGNI) +#define NETXEN_CRB_DDR_NET NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_MN) + +#define NETXEN_CRB_PCIX_MD NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_PS) +#define NETXEN_CRB_PCIE NETXEN_CRB_PCIX_MD + +#define ISR_INT_VECTOR (NETXEN_PCIX_PS_REG(PCIX_INT_VECTOR)) +#define ISR_INT_MASK (NETXEN_PCIX_PS_REG(PCIX_INT_MASK)) +#define ISR_INT_MASK_SLOW (NETXEN_PCIX_PS_REG(PCIX_INT_MASK)) +#define ISR_INT_TARGET_STATUS (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS)) +#define ISR_INT_TARGET_MASK (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK)) + +#define NETXEN_PCI_MAPSIZE 128 +#define NETXEN_PCI_DDR_NET (0x00000000UL) +#define NETXEN_PCI_QDR_NET (0x04000000UL) +#define NETXEN_PCI_DIRECT_CRB (0x04400000UL) +#define NETXEN_PCI_CAMQM_MAX (0x04ffffffUL) +#define NETXEN_PCI_OCM0 (0x05000000UL) +#define NETXEN_PCI_OCM0_MAX (0x050fffffUL) +#define NETXEN_PCI_OCM1 (0x05100000UL) +#define NETXEN_PCI_OCM1_MAX (0x051fffffUL) +#define NETXEN_PCI_CRBSPACE (0x06000000UL) + +#define NETXEN_CRB_CAM NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_CAM) + +#define NETXEN_ADDR_DDR_NET (0x0000000000000000ULL) +#define NETXEN_ADDR_DDR_NET_MAX (0x000000000fffffffULL) +#define NETXEN_ADDR_OCM0 (0x0000000200000000ULL) +#define NETXEN_ADDR_OCM0_MAX (0x00000002000fffffULL) +#define NETXEN_ADDR_OCM1 (0x0000000200400000ULL) +#define NETXEN_ADDR_OCM1_MAX (0x00000002004fffffULL) +#define NETXEN_ADDR_QDR_NET (0x0000000300000000ULL) +#define NETXEN_ADDR_QDR_NET_MAX (0x00000003003fffffULL) + + /* 200ms delay in each loop */ +#define NETXEN_NIU_PHY_WAITLEN 200000 + /* 10 seconds before we give up */ +#define NETXEN_NIU_PHY_WAITMAX 50 +#define NETXEN_NIU_MAX_GBE_PORTS 4 + +#define NETXEN_NIU_MODE (NETXEN_CRB_NIU + 0x00000) + +#define NETXEN_NIU_XG_SINGLE_TERM (NETXEN_CRB_NIU + 0x00004) +#define NETXEN_NIU_XG_DRIVE_HI (NETXEN_CRB_NIU + 0x00008) +#define NETXEN_NIU_XG_DRIVE_LO (NETXEN_CRB_NIU + 0x0000c) +#define NETXEN_NIU_XG_DTX (NETXEN_CRB_NIU + 0x00010) +#define NETXEN_NIU_XG_DEQ (NETXEN_CRB_NIU + 0x00014) +#define NETXEN_NIU_XG_WORD_ALIGN (NETXEN_CRB_NIU + 0x00018) +#define NETXEN_NIU_XG_RESET (NETXEN_CRB_NIU + 0x0001c) +#define NETXEN_NIU_XG_POWER_DOWN (NETXEN_CRB_NIU + 0x00020) +#define NETXEN_NIU_XG_RESET_PLL (NETXEN_CRB_NIU + 0x00024) +#define NETXEN_NIU_XG_SERDES_LOOPBACK (NETXEN_CRB_NIU + 0x00028) +#define NETXEN_NIU_XG_DO_BYTE_ALIGN (NETXEN_CRB_NIU + 0x0002c) +#define NETXEN_NIU_XG_TX_ENABLE (NETXEN_CRB_NIU + 0x00030) +#define NETXEN_NIU_XG_RX_ENABLE (NETXEN_CRB_NIU + 0x00034) +#define NETXEN_NIU_XG_STATUS (NETXEN_CRB_NIU + 0x00038) +#define NETXEN_NIU_XG_PAUSE_THRESHOLD (NETXEN_CRB_NIU + 0x0003c) +#define NETXEN_NIU_INT_MASK (NETXEN_CRB_NIU + 0x00040) +#define NETXEN_NIU_ACTIVE_INT (NETXEN_CRB_NIU + 0x00044) +#define NETXEN_NIU_MASKABLE_INT (NETXEN_CRB_NIU + 0x00048) + +#define NETXEN_NIU_STRAP_VALUE_SAVE_HIGHER (NETXEN_CRB_NIU + 0x0004c) + +#define NETXEN_NIU_GB_SERDES_RESET (NETXEN_CRB_NIU + 0x00050) +#define NETXEN_NIU_GB0_GMII_MODE (NETXEN_CRB_NIU + 0x00054) +#define NETXEN_NIU_GB0_MII_MODE (NETXEN_CRB_NIU + 0x00058) +#define NETXEN_NIU_GB1_GMII_MODE (NETXEN_CRB_NIU + 0x0005c) +#define NETXEN_NIU_GB1_MII_MODE (NETXEN_CRB_NIU + 0x00060) +#define NETXEN_NIU_GB2_GMII_MODE (NETXEN_CRB_NIU + 0x00064) +#define NETXEN_NIU_GB2_MII_MODE (NETXEN_CRB_NIU + 0x00068) +#define NETXEN_NIU_GB3_GMII_MODE (NETXEN_CRB_NIU + 0x0006c) +#define NETXEN_NIU_GB3_MII_MODE (NETXEN_CRB_NIU + 0x00070) +#define NETXEN_NIU_REMOTE_LOOPBACK (NETXEN_CRB_NIU + 0x00074) +#define NETXEN_NIU_GB0_HALF_DUPLEX (NETXEN_CRB_NIU + 0x00078) +#define NETXEN_NIU_GB1_HALF_DUPLEX (NETXEN_CRB_NIU + 0x0007c) +#define NETXEN_NIU_RESET_SYS_FIFOS (NETXEN_CRB_NIU + 0x00088) +#define NETXEN_NIU_GB_CRC_DROP (NETXEN_CRB_NIU + 0x0008c) +#define NETXEN_NIU_GB_DROP_WRONGADDR (NETXEN_CRB_NIU + 0x00090) +#define NETXEN_NIU_TEST_MUX_CTL (NETXEN_CRB_NIU + 0x00094) +#define NETXEN_NIU_XG_PAUSE_CTL (NETXEN_CRB_NIU + 0x00098) +#define NETXEN_NIU_XG_PAUSE_LEVEL (NETXEN_CRB_NIU + 0x000dc) +#define NETXEN_NIU_XG_SEL (NETXEN_CRB_NIU + 0x00128) + +#define NETXEN_MAC_ADDR_CNTL_REG (NETXEN_CRB_NIU + 0x1000) + +#define NETXEN_MULTICAST_ADDR_HI_0 (NETXEN_CRB_NIU + 0x1010) +#define NETXEN_MULTICAST_ADDR_HI_1 (NETXEN_CRB_NIU + 0x1014) +#define NETXEN_MULTICAST_ADDR_HI_2 (NETXEN_CRB_NIU + 0x1018) +#define NETXEN_MULTICAST_ADDR_HI_3 (NETXEN_CRB_NIU + 0x101c) + +#define NETXEN_NIU_GB_MAC_CONFIG_0(I) \ + (NETXEN_CRB_NIU + 0x30000 + (I)*0x10000) +#define NETXEN_NIU_GB_MAC_CONFIG_1(I) \ + (NETXEN_CRB_NIU + 0x30004 + (I)*0x10000) +#define NETXEN_NIU_GB_MAC_IPG_IFG(I) \ + (NETXEN_CRB_NIU + 0x30008 + (I)*0x10000) +#define NETXEN_NIU_GB_HALF_DUPLEX_CTRL(I) \ + (NETXEN_CRB_NIU + 0x3000c + (I)*0x10000) +#define NETXEN_NIU_GB_MAX_FRAME_SIZE(I) \ + (NETXEN_CRB_NIU + 0x30010 + (I)*0x10000) +#define NETXEN_NIU_GB_TEST_REG(I) \ + (NETXEN_CRB_NIU + 0x3001c + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_CONFIG(I) \ + (NETXEN_CRB_NIU + 0x30020 + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_COMMAND(I) \ + (NETXEN_CRB_NIU + 0x30024 + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_ADDR(I) \ + (NETXEN_CRB_NIU + 0x30028 + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_CTRL(I) \ + (NETXEN_CRB_NIU + 0x3002c + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_STATUS(I) \ + (NETXEN_CRB_NIU + 0x30030 + (I)*0x10000) +#define NETXEN_NIU_GB_MII_MGMT_INDICATE(I) \ + (NETXEN_CRB_NIU + 0x30034 + (I)*0x10000) +#define NETXEN_NIU_GB_INTERFACE_CTRL(I) \ + (NETXEN_CRB_NIU + 0x30038 + (I)*0x10000) +#define NETXEN_NIU_GB_INTERFACE_STATUS(I) \ + (NETXEN_CRB_NIU + 0x3003c + (I)*0x10000) +#define NETXEN_NIU_GB_STATION_ADDR_0(I) \ + (NETXEN_CRB_NIU + 0x30040 + (I)*0x10000) +#define NETXEN_NIU_GB_STATION_ADDR_1(I) \ + (NETXEN_CRB_NIU + 0x30044 + (I)*0x10000) + +#define NETXEN_NIU_XGE_CONFIG_0 (NETXEN_CRB_NIU + 0x70000) +#define NETXEN_NIU_XGE_CONFIG_1 (NETXEN_CRB_NIU + 0x70004) +#define NETXEN_NIU_XGE_IPG (NETXEN_CRB_NIU + 0x70008) +#define NETXEN_NIU_XGE_STATION_ADDR_0_HI (NETXEN_CRB_NIU + 0x7000c) +#define NETXEN_NIU_XGE_STATION_ADDR_0_1 (NETXEN_CRB_NIU + 0x70010) +#define NETXEN_NIU_XGE_STATION_ADDR_1_LO (NETXEN_CRB_NIU + 0x70014) +#define NETXEN_NIU_XGE_STATUS (NETXEN_CRB_NIU + 0x70018) +#define NETXEN_NIU_XGE_MAX_FRAME_SIZE (NETXEN_CRB_NIU + 0x7001c) +#define NETXEN_NIU_XGE_PAUSE_FRAME_VALUE (NETXEN_CRB_NIU + 0x70020) +#define NETXEN_NIU_XGE_TX_BYTE_CNT (NETXEN_CRB_NIU + 0x70024) +#define NETXEN_NIU_XGE_TX_FRAME_CNT (NETXEN_CRB_NIU + 0x70028) +#define NETXEN_NIU_XGE_RX_BYTE_CNT (NETXEN_CRB_NIU + 0x7002c) +#define NETXEN_NIU_XGE_RX_FRAME_CNT (NETXEN_CRB_NIU + 0x70030) +#define NETXEN_NIU_XGE_AGGR_ERROR_CNT (NETXEN_CRB_NIU + 0x70034) +#define NETXEN_NIU_XGE_MULTICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x70038) +#define NETXEN_NIU_XGE_UNICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x7003c) +#define NETXEN_NIU_XGE_CRC_ERROR_CNT (NETXEN_CRB_NIU + 0x70040) +#define NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x70044) +#define NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x70048) +#define NETXEN_NIU_XGE_LOCAL_ERROR_CNT (NETXEN_CRB_NIU + 0x7004c) +#define NETXEN_NIU_XGE_REMOTE_ERROR_CNT (NETXEN_CRB_NIU + 0x70050) +#define NETXEN_NIU_XGE_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x70054) +#define NETXEN_NIU_XGE_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x70058) + +/* XG Link status */ +#define XG_LINK_UP 0x10 +#define XG_LINK_DOWN 0x20 + +#define NETXEN_CAM_RAM_BASE (NETXEN_CRB_CAM + 0x02000) +#define NETXEN_CAM_RAM(reg) (NETXEN_CAM_RAM_BASE + (reg)) +#define NETXEN_FW_VERSION_MAJOR (NETXEN_CAM_RAM(0x150)) +#define NETXEN_FW_VERSION_MINOR (NETXEN_CAM_RAM(0x154)) +#define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158)) +#define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100)) + +#define PCIX_PS_OP_ADDR_LO (0x10000) /* Used for PS PCI Memory access */ +#define PCIX_PS_OP_ADDR_HI (0x10004) /* via CRB (PS side only) */ + +#define PCIX_INT_VECTOR (0x10100) +#define PCIX_INT_MASK (0x10104) + +#define PCIX_MN_WINDOW (0x10200) +#define PCIX_MS_WINDOW (0x10204) +#define PCIX_SN_WINDOW (0x10208) +#define PCIX_CRB_WINDOW (0x10210) + +#define PCIX_TARGET_STATUS (0x10118) +#define PCIX_TARGET_MASK (0x10128) + +#define PCIX_MSI_F0 (0x13000) + +#define PCIX_PS_MEM_SPACE (0x90000) + +#define NETXEN_PCIX_PH_REG(reg) (NETXEN_CRB_PCIE + (reg)) +#define NETXEN_PCIX_PS_REG(reg) (NETXEN_CRB_PCIX_MD + (reg)) + +#define NETXEN_PCIE_REG(reg) (NETXEN_CRB_PCIE + (reg)) + +#define PCIE_MAX_DMA_XFER_SIZE (0x1404c) + +#define PCIE_DCR 0x00d8 + +#define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ +#define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ + +#define PCIE_TGT_SPLIT_CHICKEN (0x12080) + +#define PCIE_MAX_MASTER_SPLIT (0x14048) + +#endif /* __NETXEN_NIC_HDR_H_ */ diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c new file mode 100644 index 000000000000..c7d97054d05c --- /dev/null +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -0,0 +1,936 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * Source file for NIC routines to access the Phantom hardware + * + */ + +#include "netxen_nic.h" +#include "netxen_nic_hw.h" +#include "netxen_nic_phan_reg.h" + +/* PCI Windowing for DDR regions. */ + +#define ADDR_IN_RANGE(addr, low, high) \ + (((addr) <= (high)) && ((addr) >= (low))) + +#define NETXEN_FLASH_BASE (BOOTLD_START) +#define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE) +#define NETXEN_MAX_MTU 8000 +#define NETXEN_MIN_MTU 64 +#define NETXEN_ETH_FCS_SIZE 4 +#define NETXEN_ENET_HEADER_SIZE 14 +#define NETXEN_WINDOW_ONE 0x2000000 /* CRB Window: bit 25 of CRB address */ +#define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4) +#define NETXEN_NIU_HDRSIZE (0x1 << 6) +#define NETXEN_NIU_TLRSIZE (0x1 << 5) + +unsigned long netxen_nic_pci_set_window(void __iomem * pci_base, + unsigned long long addr); +void netxen_free_hw_resources(struct netxen_adapter *adapter); + +int netxen_nic_set_mac(struct net_device *netdev, void *p) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + struct sockaddr *addr = p; + + if (netif_running(netdev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + DPRINTK(INFO, "valid ether addr\n"); + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + if (adapter->ops->macaddr_set) + adapter->ops->macaddr_set(port, addr->sa_data); + + return 0; +} + +/* + * netxen_nic_set_multi - Multicast + */ +void netxen_nic_set_multi(struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + struct dev_mc_list *mc_ptr; + __le32 netxen_mac_addr_cntl_data = 0; + + mc_ptr = netdev->mc_list; + if (netdev->flags & IFF_PROMISC) { + if (adapter->ops->set_promisc) + adapter->ops->set_promisc(adapter, + port->portnum, + NETXEN_NIU_PROMISC_MODE); + } else { + if (adapter->ops->unset_promisc) + adapter->ops->unset_promisc(adapter, + port->portnum, + NETXEN_NIU_NON_PROMISC_MODE); + } + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x03); + netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_enable_xtnd0(netxen_mac_addr_cntl_data); + netxen_nic_mcr_set_enable_xtnd1(netxen_mac_addr_cntl_data); + netxen_nic_mcr_set_enable_xtnd2(netxen_mac_addr_cntl_data); + netxen_nic_mcr_set_enable_xtnd3(netxen_mac_addr_cntl_data); + } else { + netxen_nic_mcr_set_mode_select(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_id_pool0(netxen_mac_addr_cntl_data, 0x00); + netxen_nic_mcr_set_id_pool1(netxen_mac_addr_cntl_data, 0x01); + netxen_nic_mcr_set_id_pool2(netxen_mac_addr_cntl_data, 0x02); + netxen_nic_mcr_set_id_pool3(netxen_mac_addr_cntl_data, 0x03); + } + writel(netxen_mac_addr_cntl_data, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_MAC_ADDR_CNTL_REG)); + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + writel(netxen_mac_addr_cntl_data, + NETXEN_CRB_NORMALIZE(adapter, + NETXEN_MULTICAST_ADDR_HI_0)); + } else { + writel(netxen_mac_addr_cntl_data, + NETXEN_CRB_NORMALIZE(adapter, + NETXEN_MULTICAST_ADDR_HI_1)); + } + netxen_mac_addr_cntl_data = 0; + writel(netxen_mac_addr_cntl_data, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_NIU_GB_DROP_WRONGADDR)); +} + +/* + * netxen_nic_change_mtu - Change the Maximum Transfer Unit + * @returns 0 on success, negative on failure + */ +int netxen_nic_change_mtu(struct net_device *netdev, int mtu) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + int eff_mtu = mtu + NETXEN_ENET_HEADER_SIZE + NETXEN_ETH_FCS_SIZE; + + if ((eff_mtu > NETXEN_MAX_MTU) || (eff_mtu < NETXEN_MIN_MTU)) { + printk(KERN_ERR "%s: %s %d is not supported.\n", + netxen_nic_driver_name, netdev->name, mtu); + return -EINVAL; + } + + if (adapter->ops->set_mtu) + adapter->ops->set_mtu(port, mtu); + netdev->mtu = mtu; + + return 0; +} + +/* + * check if the firmware has been downloaded and ready to run and + * setup the address for the descriptors in the adapter + */ +int netxen_nic_hw_resources(struct netxen_adapter *adapter) +{ + struct netxen_hardware_context *hw = &adapter->ahw; + int i; + u32 state = 0; + void *addr; + int loops = 0, err = 0; + int ctx, ring; + u32 card_cmdring = 0; + struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; + struct netxen_recv_context *recv_ctx; + struct netxen_rcv_desc_ctx *rcv_desc; + struct cmd_desc_type0 *pcmd; + + DPRINTK(INFO, "pci_base: %lx\n", adapter->ahw.pci_base); + DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE, + adapter->ahw.pci_base + NETXEN_PCI_CRBSPACE); + DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM, + adapter->ahw.pci_base + NETXEN_CRB_CAM); + DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE, + adapter->ahw.pci_base + NETXEN_CAM_RAM_BASE); + DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1, + adapter->ahw.pci_base + NIC_CRB_BASE_PORT1); + + /* Window 1 call */ + card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING)); + + DPRINTK(INFO, "Command Peg sends 0x%x for cmdring base\n", + card_cmdring); + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + DPRINTK(INFO, "Command Peg ready..waiting for rcv peg\n"); + loops = 0; + state = 0; + /* Window 1 call */ + state = readl(NETXEN_CRB_NORMALIZE(adapter, + recv_crb_registers[ctx]. + crb_rcvpeg_state)); + while (state != PHAN_PEG_RCV_INITIALIZED && loops < 20) { + udelay(100); + /* Window 1 call */ + state = readl(NETXEN_CRB_NORMALIZE(adapter, + recv_crb_registers + [ctx]. + crb_rcvpeg_state)); + loops++; + } + if (loops >= 20) { + printk(KERN_ERR "Rcv Peg initialization not complete:" + "%x.\n", state); + err = -EIO; + return err; + } + } + DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n"); + + addr = pci_alloc_consistent(adapter->ahw.pdev, + sizeof(struct cmd_desc_type0) * + adapter->max_tx_desc_count, + &hw->cmd_desc_phys_addr); + if (addr == NULL) { + DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); + err = -ENOMEM; + return err; + } + + /* we need to prelink all of the cmd descriptors */ + pcmd = (struct cmd_desc_type0 *)addr; + for (i = 1; i < adapter->max_tx_desc_count; i++) { + pcmd->netxen_next = + (card_cmdring + i * sizeof(struct cmd_desc_type0)); + pcmd++; + } + /* fill in last link (point to first) */ + pcmd->netxen_next = card_cmdring; + + hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + recv_ctx = &adapter->recv_ctx[ctx]; + + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + addr = pci_alloc_consistent(adapter->ahw.pdev, + RCV_DESC_RINGSIZE, + &rcv_desc->phys_addr); + if (addr == NULL) { + DPRINTK(ERR, "bad return from " + "pci_alloc_consistent\n"); + netxen_free_hw_resources(adapter); + err = -ENOMEM; + return err; + } + rcv_desc->desc_head = (struct rcv_desc *)addr; + } + + addr = pci_alloc_consistent(adapter->ahw.pdev, + STATUS_DESC_RINGSIZE, + &recv_ctx-> + rcv_status_desc_phys_addr); + if (addr == NULL) { + DPRINTK(ERR, "bad return from" + " pci_alloc_consistent\n"); + netxen_free_hw_resources(adapter); + err = -ENOMEM; + return err; + } + recv_ctx->rcv_status_desc_head = (struct status_desc *)addr; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + rcv_desc_crb = + &recv_crb_registers[ctx].rcv_desc_crb[ring]; + DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n", + ring, rcv_desc_crb->crb_globalrcv_ring); + /* Window = 1 */ + writel(rcv_desc->phys_addr, + NETXEN_CRB_NORMALIZE(adapter, + rcv_desc_crb-> + crb_globalrcv_ring)); + DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x" + " val 0x%x," + " virt %p\n", ctx, + rcv_desc_crb->crb_globalrcv_ring, + rcv_desc->phys_addr, rcv_desc->desc_head); + } + + /* Window = 1 */ + writel(recv_ctx->rcv_status_desc_phys_addr, + NETXEN_CRB_NORMALIZE(adapter, + recv_crb_registers[ctx]. + crb_rcvstatus_ring)); + DPRINTK(INFO, "RCVSTATUS_RING, ctx %d, addr 0x%x," + " val 0x%x,virt%p\n", + ctx, + recv_crb_registers[ctx].crb_rcvstatus_ring, + recv_ctx->rcv_status_desc_phys_addr, + recv_ctx->rcv_status_desc_head); + } + /* Window = 1 */ + writel(hw->cmd_desc_phys_addr, + NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + + return err; +} + +void netxen_free_hw_resources(struct netxen_adapter *adapter) +{ + struct netxen_recv_context *recv_ctx; + struct netxen_rcv_desc_ctx *rcv_desc; + int ctx, ring; + + if (adapter->ahw.cmd_desc_head != NULL) { + pci_free_consistent(adapter->ahw.pdev, + sizeof(struct cmd_desc_type0) * + adapter->max_tx_desc_count, + adapter->ahw.cmd_desc_head, + adapter->ahw.cmd_desc_phys_addr); + adapter->ahw.cmd_desc_head = NULL; + } + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + recv_ctx = &adapter->recv_ctx[ctx]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + + if (rcv_desc->desc_head != NULL) { + pci_free_consistent(adapter->ahw.pdev, + RCV_DESC_RINGSIZE, + rcv_desc->desc_head, + rcv_desc->phys_addr); + rcv_desc->desc_head = NULL; + } + } + + if (recv_ctx->rcv_status_desc_head != NULL) { + pci_free_consistent(adapter->ahw.pdev, + STATUS_DESC_RINGSIZE, + recv_ctx->rcv_status_desc_head, + recv_ctx-> + rcv_status_desc_phys_addr); + recv_ctx->rcv_status_desc_head = NULL; + } + } +} + +void netxen_tso_check(struct netxen_adapter *adapter, + struct cmd_desc_type0 *desc, struct sk_buff *skb) +{ + if (desc->mss) { + desc->total_hdr_length = sizeof(struct ethhdr) + + ((skb->nh.iph)->ihl * sizeof(u32)) + + ((skb->h.th)->doff * sizeof(u32)); + desc->opcode = TX_TCP_LSO; + } else if (skb->ip_summed == CHECKSUM_HW) { + if (skb->nh.iph->protocol == IPPROTO_TCP) { + desc->opcode = TX_TCP_PKT; + } else if (skb->nh.iph->protocol == IPPROTO_UDP) { + desc->opcode = TX_UDP_PKT; + } else { + return; + } + } + CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data); + desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr); + desc->ip_hdr_offset = skb->nh.raw - skb->data; + adapter->stats.xmitcsummed++; +} + +int netxen_is_flash_supported(struct netxen_adapter *adapter) +{ + const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 }; + int addr, val01, val02, i, j; + + /* if the flash size less than 4Mb, make huge war cry and die */ + for (j = 1; j < 4; j++) { + addr = j * 0x100000; + for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) { + if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0 + && netxen_rom_fast_read(adapter, (addr + locs[i]), + &val02) == 0) { + if (val01 == val02) + return -1; + } else + return -1; + } + } + + return 0; +} + +static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, + int size, u32 * buf) +{ + int i, addr; + u32 *ptr32; + + addr = base; + ptr32 = buf; + for (i = 0; i < size / sizeof(u32); i++) { + if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) + return -1; + ptr32++; + addr += sizeof(u32); + } + if ((char *)buf + size > (char *)ptr32) { + u32 local; + + if (netxen_rom_fast_read(adapter, addr, &local) == -1) + return -1; + memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32); + } + + return 0; +} + +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 mac[]) +{ + u32 *pmac = (u32 *) & mac[0]; + + if (netxen_get_flash_block(adapter, + USER_START + + offsetof(struct netxen_new_user_info, + mac_addr), + FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) { + return -1; + } + if (*mac == ~0ULL) { + if (netxen_get_flash_block(adapter, + USER_START_OLD + + offsetof(struct netxen_user_old_info, + mac_addr), + FLASH_NUM_PORTS * sizeof(u64), + pmac) == -1) + return -1; + if (*mac == ~0ULL) + return -1; + } + return 0; +} + +/* + * Changes the CRB window to the specified window. + */ +void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) +{ + void __iomem *offset; + u32 tmp; + int count = 0; + + if (adapter->curr_window == wndw) + return; + + /* + * Move the CRB window. + * We need to write to the "direct access" region of PCI + * to avoid a race condition where the window register has + * not been successfully written across CRB before the target + * register address is received by PCI. The direct region bypasses + * the CRB bus. + */ + offset = adapter->ahw.pci_base + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW); + + if (wndw & 0x1) + wndw = NETXEN_WINDOW_ONE; + + writel(wndw, offset); + + /* MUST make sure window is set before we forge on... */ + while ((tmp = readl(offset)) != wndw) { + printk(KERN_WARNING "%s: %s WARNING: CRB window value not " + "registered properly: 0x%08x.\n", + netxen_nic_driver_name, __FUNCTION__, tmp); + mdelay(1); + if (count >= 10) + break; + count++; + } + + adapter->curr_window = wndw; +} + +void netxen_load_firmware(struct netxen_adapter *adapter) +{ + int i; + long data, size = 0; + long flashaddr = NETXEN_FLASH_BASE, memaddr = NETXEN_PHANTOM_MEM_BASE; + u64 off; + void __iomem *addr; + + size = NETXEN_FIRMWARE_LEN; + writel(1, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); + + for (i = 0; i < size; i++) { + if (netxen_rom_fast_read(adapter, flashaddr, (int *)&data) != 0) { + DPRINTK(ERR, + "Error in netxen_rom_fast_read(). Will skip" + "loading flash image\n"); + return; + } + off = netxen_nic_pci_set_window(adapter->ahw.pci_base, memaddr); + addr = (adapter->ahw.pci_base + off); + writel(data, addr); + flashaddr += 4; + memaddr += 4; + } + udelay(100); + /* make sure Casper is powered on */ + writel(0x3fff, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_CAS_RST)); + + udelay(100); +} + +int +netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, + int len) +{ + void __iomem *addr; + + if (ADDR_IN_WINDOW1(off)) { + addr = NETXEN_CRB_NORMALIZE(adapter, off); + } else { /* Window 0 */ + addr = adapter->ahw.pci_base + off; + netxen_nic_pci_change_crbwindow(adapter, 0); + } + + DPRINTK(INFO, "writing to base %lx offset %llx addr %p" + " data %llx len %d\n", + adapter->ahw.pci_base, off, addr, + *(unsigned long long *)data, len); + switch (len) { + case 1: + writeb(*(u8 *) data, addr); + break; + case 2: + writew(*(u16 *) data, addr); + break; + case 4: + writel(*(u32 *) data, addr); + break; + case 8: + writeq(*(u64 *) data, addr); + break; + default: + DPRINTK(INFO, + "writing data %lx to offset %llx, num words=%d\n", + *(unsigned long *)data, off, (len >> 3)); + + netxen_nic_hw_block_write64((u64 __iomem *) data, addr, + (len >> 3)); + break; + } + if (!ADDR_IN_WINDOW1(off)) + netxen_nic_pci_change_crbwindow(adapter, 1); + + return 0; +} + +int +netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, + int len) +{ + void __iomem *addr; + + if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ + addr = NETXEN_CRB_NORMALIZE(adapter, off); + } else { /* Window 0 */ + addr = adapter->ahw.pci_base + off; + netxen_nic_pci_change_crbwindow(adapter, 0); + } + + DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", + adapter->ahw.pci_base, off, addr); + switch (len) { + case 1: + *(u8 *) data = readb(addr); + break; + case 2: + *(u16 *) data = readw(addr); + break; + case 4: + *(u32 *) data = readl(addr); + break; + case 8: + *(u64 *) data = readq(addr); + break; + default: + netxen_nic_hw_block_read64((u64 __iomem *) data, addr, + (len >> 3)); + break; + } + DPRINTK(INFO, "read %lx\n", *(unsigned long *)data); + + if (!ADDR_IN_WINDOW1(off)) + netxen_nic_pci_change_crbwindow(adapter, 1); + + return 0; +} + +void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) +{ /* Only for window 1 */ + void __iomem *addr; + + addr = NETXEN_CRB_NORMALIZE(adapter, off); + DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n", + adapter->ahw.pci_base, off, addr, val); + writel(val, addr); + +} + +int netxen_nic_reg_read(struct netxen_adapter *adapter, u64 off) +{ /* Only for window 1 */ + void __iomem *addr; + int val; + + addr = NETXEN_CRB_NORMALIZE(adapter, off); + DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", + adapter->ahw.pci_base, off, addr); + val = readl(addr); + writel(val, addr); + + return val; +} + +/* Change the window to 0, write and change back to window 1. */ +void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) +{ + void __iomem *addr; + + netxen_nic_pci_change_crbwindow(adapter, 0); + addr = (void __iomem *)(adapter->ahw.pci_base + index); + writel(value, addr); + netxen_nic_pci_change_crbwindow(adapter, 1); +} + +/* Change the window to 0, read and change back to window 1. */ +void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value) +{ + void __iomem *addr; + + addr = (void __iomem *)(adapter->ahw.pci_base + index); + + netxen_nic_pci_change_crbwindow(adapter, 0); + *value = readl(addr); + netxen_nic_pci_change_crbwindow(adapter, 1); +} + +int netxen_pci_set_window_warning_count = 0; + +unsigned long +netxen_nic_pci_set_window(void __iomem * pci_base, unsigned long long addr) +{ + static int ddr_mn_window = -1; + static int qdr_sn_window = -1; + int window; + + if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { + /* DDR network side */ + addr -= NETXEN_ADDR_DDR_NET; + window = (addr >> 25) & 0x3ff; + if (ddr_mn_window != window) { + ddr_mn_window = window; + writel(window, pci_base + + NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW)); + /* MUST make sure window is set before we forge on... */ + readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW)); + } + addr -= (window * 0x2000000); + addr += NETXEN_PCI_DDR_NET; + } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { + addr -= NETXEN_ADDR_OCM0; + addr += NETXEN_PCI_OCM0; + } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { + addr -= NETXEN_ADDR_OCM1; + addr += NETXEN_PCI_OCM1; + } else + if (ADDR_IN_RANGE + (addr, NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX)) { + /* QDR network side */ + addr -= NETXEN_ADDR_QDR_NET; + window = (addr >> 22) & 0x3f; + if (qdr_sn_window != window) { + qdr_sn_window = window; + writel((window << 22), pci_base + + NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW)); + /* MUST make sure window is set before we forge on... */ + readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW)); + } + addr -= (window * 0x400000); + addr += NETXEN_PCI_QDR_NET; + } else { + /* + * peg gdb frequently accesses memory that doesn't exist, + * this limits the chit chat so debugging isn't slowed down. + */ + if ((netxen_pci_set_window_warning_count++ < 8) + || (netxen_pci_set_window_warning_count % 64 == 0)) + printk("%s: Warning:netxen_nic_pci_set_window()" + " Unknown address range!\n", + netxen_nic_driver_name); + + } + return addr; +} + +int netxen_nic_get_board_info(struct netxen_adapter *adapter) +{ + int rv = 0; + int addr = BRDCFG_START; + struct netxen_board_info *boardinfo; + int index; + u32 *ptr32; + + boardinfo = &adapter->ahw.boardcfg; + ptr32 = (u32 *) boardinfo; + + for (index = 0; index < sizeof(struct netxen_board_info) / sizeof(u32); + index++) { + if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { + return -EIO; + } + ptr32++; + addr += sizeof(u32); + } + if (boardinfo->magic != NETXEN_BDINFO_MAGIC) { + printk("%s: ERROR reading %s board config." + " Read %x, expected %x\n", netxen_nic_driver_name, + netxen_nic_driver_name, + boardinfo->magic, NETXEN_BDINFO_MAGIC); + rv = -1; + } + if (boardinfo->header_version != NETXEN_BDINFO_VERSION) { + printk("%s: Unknown board config version." + " Read %x, expected %x\n", netxen_nic_driver_name, + boardinfo->header_version, NETXEN_BDINFO_VERSION); + rv = -1; + } + + DPRINTK(INFO, "Discovered board type:0x%x ", boardinfo->board_type); + switch ((netxen_brdtype_t) boardinfo->board_type) { + case NETXEN_BRDTYPE_P2_SB35_4G: + adapter->ahw.board_type = NETXEN_NIC_GBE; + break; + case NETXEN_BRDTYPE_P2_SB31_10G: + case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: + case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + adapter->ahw.board_type = NETXEN_NIC_XGBE; + break; + case NETXEN_BRDTYPE_P1_BD: + case NETXEN_BRDTYPE_P1_SB: + case NETXEN_BRDTYPE_P1_SMAX: + case NETXEN_BRDTYPE_P1_SOCK: + adapter->ahw.board_type = NETXEN_NIC_GBE; + break; + default: + printk("%s: Unknown(%x)\n", netxen_nic_driver_name, + boardinfo->board_type); + break; + } + + return rv; +} + +/* NIU access sections */ + +int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu) +{ + struct netxen_adapter *adapter = port->adapter; + netxen_nic_write_w0(adapter, + NETXEN_NIU_GB_MAX_FRAME_SIZE(port->portnum), + new_mtu); + return 0; +} + +int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu) +{ + struct netxen_adapter *adapter = port->adapter; + new_mtu += NETXEN_NIU_HDRSIZE + NETXEN_NIU_TLRSIZE; + netxen_nic_write_w0(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); + return 0; +} + +void netxen_nic_init_niu_gb(struct netxen_adapter *adapter) +{ + int portno; + for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) + netxen_niu_gbe_init_port(adapter, portno); +} + +void netxen_nic_stop_all_ports(struct netxen_adapter *adapter) +{ + int port_nr; + struct netxen_port *port; + + for (port_nr = 0; port_nr < adapter->ahw.max_ports; port_nr++) { + port = adapter->port[port_nr]; + if (adapter->ops->stop_port) + adapter->ops->stop_port(adapter, port->portnum); + } +} + +void +netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, + int data) +{ + void __iomem *addr; + + if (ADDR_IN_WINDOW1(off)) { + writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); + } else { + netxen_nic_pci_change_crbwindow(adapter, 0); + addr = (void __iomem *)(adapter->ahw.pci_base + off); + writel(data, addr); + netxen_nic_pci_change_crbwindow(adapter, 1); + } +} + +void netxen_nic_set_link_parameters(struct netxen_port *port) +{ + struct netxen_adapter *adapter = port->adapter; + __le32 status; + u16 autoneg; + __le32 mode; + + netxen_nic_read_w0(adapter, NETXEN_NIU_MODE, &mode); + if (netxen_get_niu_enable_ge(mode)) { /* Gb 10/100/1000 Mbps mode */ + if (adapter->ops->phy_read + && adapter->ops-> + phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) == 0) { + if (netxen_get_phy_link(status)) { + switch (netxen_get_phy_speed(status)) { + case 0: + port->link_speed = SPEED_10; + break; + case 1: + port->link_speed = SPEED_100; + break; + case 2: + port->link_speed = SPEED_1000; + break; + default: + port->link_speed = -1; + break; + } + switch (netxen_get_phy_duplex(status)) { + case 0: + port->link_duplex = DUPLEX_HALF; + break; + case 1: + port->link_duplex = DUPLEX_FULL; + break; + default: + port->link_duplex = -1; + break; + } + if (adapter->ops->phy_read + && adapter->ops-> + phy_read(adapter, port->portnum, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, + (__le32 *) & autoneg) != 0) + port->link_autoneg = autoneg; + } else + goto link_down; + } else { + link_down: + port->link_speed = -1; + port->link_duplex = -1; + } + } +} + +void netxen_nic_flash_print(struct netxen_adapter *adapter) +{ + int valid = 1; + u32 fw_major = 0; + u32 fw_minor = 0; + u32 fw_build = 0; + + struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); + if (board_info->magic != NETXEN_BDINFO_MAGIC) { + printk + ("NetXen Unknown board config, Read 0x%x expected as 0x%x\n", + board_info->magic, NETXEN_BDINFO_MAGIC); + valid = 0; + } + if (board_info->header_version != NETXEN_BDINFO_VERSION) { + printk("NetXen Unknown board config version." + " Read %x, expected %x\n", + board_info->header_version, NETXEN_BDINFO_VERSION); + valid = 0; + } + if (valid) { + printk("NetXen %s Board #%d, Chip id 0x%x\n", + board_info->board_type == 0x0b ? "XGB" : "GBE", + board_info->board_num, board_info->chip_id); + fw_major = readl(NETXEN_CRB_NORMALIZE(adapter, + NETXEN_FW_VERSION_MAJOR)); + fw_minor = readl(NETXEN_CRB_NORMALIZE(adapter, + NETXEN_FW_VERSION_MINOR)); + fw_build = + readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_FW_VERSION_SUB)); + + printk("NetXen Firmware version %d.%d.%d\n", fw_major, fw_minor, + fw_build); + } + if (fw_major != _NETXEN_NIC_LINUX_MAJOR) { + printk(KERN_ERR "The mismatch in driver version and firmware " + "version major number\n" + "Driver version major number = %d \t" + "Firmware version major number = %d \n", + _NETXEN_NIC_LINUX_MAJOR, fw_major); + adapter->driver_mismatch = 1; + } + if (fw_minor != _NETXEN_NIC_LINUX_MINOR) { + printk(KERN_ERR "The mismatch in driver version and firmware " + "version minor number\n" + "Driver version minor number = %d \t" + "Firmware version minor number = %d \n", + _NETXEN_NIC_LINUX_MINOR, fw_minor); + adapter->driver_mismatch = 1; + } + if (adapter->driver_mismatch) + printk(KERN_INFO "Use the driver with version no %d.%d.xxx\n", + fw_major, fw_minor); +} + +int netxen_crb_read_val(struct netxen_adapter *adapter, unsigned long off) +{ + int data; + netxen_nic_hw_read_wx(adapter, off, &data, 4); + return data; +} diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h new file mode 100644 index 000000000000..fb1a0253863f --- /dev/null +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * Structures, enums, and macros for the MAC + * + */ + +#ifndef __NETXEN_NIC_HW_H_ +#define __NETXEN_NIC_HW_H_ + +#include "netxen_nic_hdr.h" + +/* Hardware memory size of 128 meg */ +#define NETXEN_MEMADDR_MAX (128 * 1024 * 1024) + +#ifndef readq +static inline u64 readq(void __iomem * addr) +{ + return readl(addr) | (((u64) readl(addr + 4)) << 32LL); +} +#endif + +#ifndef writeq +static inline void writeq(u64 val, void __iomem * addr) +{ + writel(((u32) (val)), (addr)); + writel(((u32) (val >> 32)), (addr + 4)); +} +#endif + +static inline void netxen_nic_hw_block_write64(u64 __iomem * data_ptr, + u64 __iomem * addr, + int num_words) +{ + int num; + for (num = 0; num < num_words; num++) { + writeq(readq((void __iomem *)data_ptr), addr); + addr++; + data_ptr++; + } +} + +static inline void netxen_nic_hw_block_read64(u64 __iomem * data_ptr, + u64 __iomem * addr, int num_words) +{ + int num; + for (num = 0; num < num_words; num++) { + writeq(readq((void __iomem *)addr), data_ptr); + addr++; + data_ptr++; + } + +} + +struct netxen_adapter; + +#define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) + +#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \ + addr = (adapter->ahw.pci_base + X); \ + *(u32 *)Y = readl((void __iomem*) addr); + +struct netxen_port; +void netxen_nic_set_link_parameters(struct netxen_port *port); +void netxen_nic_flash_print(struct netxen_adapter *adapter); +int netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, + void *data, int len); +void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, + unsigned long off, int data); +int netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, + void *data, int len); + +typedef u8 netxen_ethernet_macaddr_t[6]; + +/* Nibble or Byte mode for phy interface (GbE mode only) */ +typedef enum { + NETXEN_NIU_10_100_MB = 0, + NETXEN_NIU_1000_MB +} netxen_niu_gbe_ifmode_t; + +#define _netxen_crb_get_bit(var, bit) ((var >> bit) & 0x1) + +/* + * NIU GB MAC Config Register 0 (applies to GB0, GB1, GB2, GB3) + * + * Bit 0 : enable_tx => 1:enable frame xmit, 0:disable + * Bit 1 : tx_synced => R/O: xmit enable synched to xmit stream + * Bit 2 : enable_rx => 1:enable frame recv, 0:disable + * Bit 3 : rx_synced => R/O: recv enable synched to recv stream + * Bit 4 : tx_flowctl => 1:enable pause frame generation, 0:disable + * Bit 5 : rx_flowctl => 1:act on recv'd pause frames, 0:ignore + * Bit 8 : loopback => 1:loop MAC xmits to MAC recvs, 0:normal + * Bit 16: tx_reset_pb => 1:reset frame xmit protocol blk, 0:no-op + * Bit 17: rx_reset_pb => 1:reset frame recv protocol blk, 0:no-op + * Bit 18: tx_reset_mac => 1:reset data/ctl multiplexer blk, 0:no-op + * Bit 19: rx_reset_mac => 1:reset ctl frames & timers blk, 0:no-op + * Bit 31: soft_reset => 1:reset the MAC and the SERDES, 0:no-op + */ + +#define netxen_gb_enable_tx(config_word) \ + set_bit(0, (unsigned long*)(&config_word)) +#define netxen_gb_enable_rx(config_word) \ + set_bit(2, (unsigned long*)(&config_word)) +#define netxen_gb_tx_flowctl(config_word) \ + set_bit(4, (unsigned long*)(&config_word)) +#define netxen_gb_rx_flowctl(config_word) \ + set_bit(5, (unsigned long*)(&config_word)) +#define netxen_gb_tx_reset_pb(config_word) \ + set_bit(16, (unsigned long*)(&config_word)) +#define netxen_gb_rx_reset_pb(config_word) \ + set_bit(17, (unsigned long*)(&config_word)) +#define netxen_gb_tx_reset_mac(config_word) \ + set_bit(18, (unsigned long*)(&config_word)) +#define netxen_gb_rx_reset_mac(config_word) \ + set_bit(19, (unsigned long*)(&config_word)) +#define netxen_gb_soft_reset(config_word) \ + set_bit(31, (unsigned long*)(&config_word)) + +#define netxen_gb_unset_tx_flowctl(config_word) \ + clear_bit(4, (unsigned long *)(&config_word)) +#define netxen_gb_unset_rx_flowctl(config_word) \ + clear_bit(5, (unsigned long*)(&config_word)) + +#define netxen_gb_get_tx_synced(config_word) \ + _netxen_crb_get_bit((config_word), 1) +#define netxen_gb_get_rx_synced(config_word) \ + _netxen_crb_get_bit((config_word), 3) +#define netxen_gb_get_tx_flowctl(config_word) \ + _netxen_crb_get_bit((config_word), 4) +#define netxen_gb_get_rx_flowctl(config_word) \ + _netxen_crb_get_bit((config_word), 5) +#define netxen_gb_get_soft_reset(config_word) \ + _netxen_crb_get_bit((config_word), 31) + +/* + * NIU GB MAC Config Register 1 (applies to GB0, GB1, GB2, GB3) + * + * Bit 0 : duplex => 1:full duplex mode, 0:half duplex + * Bit 1 : crc_enable => 1:append CRC to xmit frames, 0:dont append + * Bit 2 : padshort => 1:pad short frames and add CRC, 0:dont pad + * Bit 4 : checklength => 1:check framelen with actual,0:dont check + * Bit 5 : hugeframes => 1:allow oversize xmit frames, 0:dont allow + * Bits 8-9 : intfmode => 01:nibble (10/100), 10:byte (1000) + * Bits 12-15 : preamblelen => preamble field length in bytes, default 7 + */ + +#define netxen_gb_set_duplex(config_word) \ + set_bit(0, (unsigned long*)&config_word) +#define netxen_gb_set_crc_enable(config_word) \ + set_bit(1, (unsigned long*)&config_word) +#define netxen_gb_set_padshort(config_word) \ + set_bit(2, (unsigned long*)&config_word) +#define netxen_gb_set_checklength(config_word) \ + set_bit(4, (unsigned long*)&config_word) +#define netxen_gb_set_hugeframes(config_word) \ + set_bit(5, (unsigned long*)&config_word) +#define netxen_gb_set_preamblelen(config_word, val) \ + ((config_word) |= ((val) << 12) & 0xF000) +#define netxen_gb_set_intfmode(config_word, val) \ + ((config_word) |= ((val) << 8) & 0x300) + +#define netxen_gb_get_stationaddress_low(config_word) ((config_word) >> 16) + +#define netxen_gb_set_mii_mgmt_clockselect(config_word, val) \ + ((config_word) |= ((val) & 0x07)) +#define netxen_gb_mii_mgmt_reset(config_word) \ + set_bit(31, (unsigned long*)&config_word) +#define netxen_gb_mii_mgmt_unset(config_word) \ + clear_bit(31, (unsigned long*)&config_word) + +/* + * NIU GB MII Mgmt Command Register (applies to GB0, GB1, GB2, GB3) + * Bit 0 : read_cycle => 1:perform single read cycle, 0:no-op + * Bit 1 : scan_cycle => 1:perform continuous read cycles, 0:no-op + */ + +#define netxen_gb_mii_mgmt_set_read_cycle(config_word) \ + set_bit(0, (unsigned long*)&config_word) +#define netxen_gb_mii_mgmt_reg_addr(config_word, val) \ + ((config_word) |= ((val) & 0x1F)) +#define netxen_gb_mii_mgmt_phy_addr(config_word, val) \ + ((config_word) |= (((val) & 0x1F) << 8)) + +/* + * NIU GB MII Mgmt Indicators Register (applies to GB0, GB1, GB2, GB3) + * Read-only register. + * Bit 0 : busy => 1:performing an MII mgmt cycle, 0:idle + * Bit 1 : scanning => 1:scan operation in progress, 0:idle + * Bit 2 : notvalid => :mgmt result data not yet valid, 0:idle + */ +#define netxen_get_gb_mii_mgmt_busy(config_word) \ + _netxen_crb_get_bit(config_word, 0) +#define netxen_get_gb_mii_mgmt_scanning(config_word) \ + _netxen_crb_get_bit(config_word, 1) +#define netxen_get_gb_mii_mgmt_notvalid(config_word) \ + _netxen_crb_get_bit(config_word, 2) + +/* + * PHY-Specific MII control/status registers. + */ +typedef enum { + NETXEN_NIU_GB_MII_MGMT_ADDR_CONTROL = 0, + NETXEN_NIU_GB_MII_MGMT_ADDR_STATUS = 1, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_0 = 2, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_ID_1 = 3, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG = 4, + NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART = 5, + NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG_MORE = 6, + NETXEN_NIU_GB_MII_MGMT_ADDR_NEXTPAGE_XMIT = 7, + NETXEN_NIU_GB_MII_MGMT_ADDR_LNKPART_NEXTPAGE = 8, + NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_CONTROL = 9, + NETXEN_NIU_GB_MII_MGMT_ADDR_1000BT_STATUS = 10, + NETXEN_NIU_GB_MII_MGMT_ADDR_EXTENDED_STATUS = 15, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL = 16, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS = 17, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE = 18, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS = 19, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE = 20, + NETXEN_NIU_GB_MII_MGMT_ADDR_RECV_ERROR_COUNT = 21, + NETXEN_NIU_GB_MII_MGMT_ADDR_LED_CONTROL = 24, + NETXEN_NIU_GB_MII_MGMT_ADDR_LED_OVERRIDE = 25, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_CONTROL_MORE_YET = 26, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS_MORE = 27 +} netxen_niu_phy_register_t; + +/* + * PHY-Specific Status Register (reg 17). + * + * Bit 0 : jabber => 1:jabber detected, 0:not + * Bit 1 : polarity => 1:polarity reversed, 0:normal + * Bit 2 : recvpause => 1:receive pause enabled, 0:disabled + * Bit 3 : xmitpause => 1:transmit pause enabled, 0:disabled + * Bit 4 : energydetect => 1:sleep, 0:active + * Bit 5 : downshift => 1:downshift, 0:no downshift + * Bit 6 : crossover => 1:MDIX (crossover), 0:MDI (no crossover) + * Bits 7-9 : cablelen => not valid in 10Mb/s mode + * 0:<50m, 1:50-80m, 2:80-110m, 3:110-140m, 4:>140m + * Bit 10 : link => 1:link up, 0:link down + * Bit 11 : resolved => 1:speed and duplex resolved, 0:not yet + * Bit 12 : pagercvd => 1:page received, 0:page not received + * Bit 13 : duplex => 1:full duplex, 0:half duplex + * Bits 14-15 : speed => 0:10Mb/s, 1:100Mb/s, 2:1000Mb/s, 3:rsvd + */ + +#define netxen_get_phy_cablelen(config_word) (((config_word) >> 7) & 0x07) +#define netxen_get_phy_speed(config_word) (((config_word) >> 14) & 0x03) + +#define netxen_set_phy_speed(config_word, val) \ + ((config_word) |= ((val & 0x03) << 14)) +#define netxen_set_phy_duplex(config_word) \ + set_bit(13, (unsigned long*)&config_word) +#define netxen_clear_phy_duplex(config_word) \ + clear_bit(13, (unsigned long*)&config_word) + +#define netxen_get_phy_jabber(config_word) \ + _netxen_crb_get_bit(config_word, 0) +#define netxen_get_phy_polarity(config_word) \ + _netxen_crb_get_bit(config_word, 1) +#define netxen_get_phy_recvpause(config_word) \ + _netxen_crb_get_bit(config_word, 2) +#define netxen_get_phy_xmitpause(config_word) \ + _netxen_crb_get_bit(config_word, 3) +#define netxen_get_phy_energydetect(config_word) \ + _netxen_crb_get_bit(config_word, 4) +#define netxen_get_phy_downshift(config_word) \ + _netxen_crb_get_bit(config_word, 5) +#define netxen_get_phy_crossover(config_word) \ + _netxen_crb_get_bit(config_word, 6) +#define netxen_get_phy_link(config_word) \ + _netxen_crb_get_bit(config_word, 10) +#define netxen_get_phy_resolved(config_word) \ + _netxen_crb_get_bit(config_word, 11) +#define netxen_get_phy_pagercvd(config_word) \ + _netxen_crb_get_bit(config_word, 12) +#define netxen_get_phy_duplex(config_word) \ + _netxen_crb_get_bit(config_word, 13) + +/* + * Interrupt Register definition + * This definition applies to registers 18 and 19 (int enable and int status). + * Bit 0 : jabber + * Bit 1 : polarity_changed + * Bit 4 : energy_detect + * Bit 5 : downshift + * Bit 6 : mdi_xover_changed + * Bit 7 : fifo_over_underflow + * Bit 8 : false_carrier + * Bit 9 : symbol_error + * Bit 10: link_status_changed + * Bit 11: autoneg_completed + * Bit 12: page_received + * Bit 13: duplex_changed + * Bit 14: speed_changed + * Bit 15: autoneg_error + */ + +#define netxen_get_phy_int_jabber(config_word) \ + _netxen_crb_get_bit(config_word, 0) +#define netxen_get_phy_int_polarity_changed(config_word) \ + _netxen_crb_get_bit(config_word, 1) +#define netxen_get_phy_int_energy_detect(config_word) \ + _netxen_crb_get_bit(config_word, 4) +#define netxen_get_phy_int_downshift(config_word) \ + _netxen_crb_get_bit(config_word, 5) +#define netxen_get_phy_int_mdi_xover_changed(config_word) \ + _netxen_crb_get_bit(config_word, 6) +#define netxen_get_phy_int_fifo_over_underflow(config_word) \ + _netxen_crb_get_bit(config_word, 7) +#define netxen_get_phy_int_false_carrier(config_word) \ + _netxen_crb_get_bit(config_word, 8) +#define netxen_get_phy_int_symbol_error(config_word) \ + _netxen_crb_get_bit(config_word, 9) +#define netxen_get_phy_int_link_status_changed(config_word) \ + _netxen_crb_get_bit(config_word, 10) +#define netxen_get_phy_int_autoneg_completed(config_word) \ + _netxen_crb_get_bit(config_word, 11) +#define netxen_get_phy_int_page_received(config_word) \ + _netxen_crb_get_bit(config_word, 12) +#define netxen_get_phy_int_duplex_changed(config_word) \ + _netxen_crb_get_bit(config_word, 13) +#define netxen_get_phy_int_speed_changed(config_word) \ + _netxen_crb_get_bit(config_word, 14) +#define netxen_get_phy_int_autoneg_error(config_word) \ + _netxen_crb_get_bit(config_word, 15) + +#define netxen_set_phy_int_link_status_changed(config_word) \ + set_bit(10, (unsigned long*)&config_word) +#define netxen_set_phy_int_autoneg_completed(config_word) \ + set_bit(11, (unsigned long*)&config_word) +#define netxen_set_phy_int_speed_changed(config_word) \ + set_bit(14, (unsigned long*)&config_word) + +/* + * NIU Mode Register. + * Bit 0 : enable FibreChannel + * Bit 1 : enable 10/100/1000 Ethernet + * Bit 2 : enable 10Gb Ethernet + */ + +#define netxen_get_niu_enable_ge(config_word) \ + _netxen_crb_get_bit(config_word, 1) + +/* Promiscous mode options (GbE mode only) */ +typedef enum { + NETXEN_NIU_PROMISC_MODE = 0, + NETXEN_NIU_NON_PROMISC_MODE +} netxen_niu_prom_mode_t; + +/* + * NIU GB Drop CRC Register + * + * Bit 0 : drop_gb0 => 1:drop pkts with bad CRCs, 0:pass them on + * Bit 1 : drop_gb1 => 1:drop pkts with bad CRCs, 0:pass them on + * Bit 2 : drop_gb2 => 1:drop pkts with bad CRCs, 0:pass them on + * Bit 3 : drop_gb3 => 1:drop pkts with bad CRCs, 0:pass them on + */ + +#define netxen_set_gb_drop_gb0(config_word) \ + set_bit(0, (unsigned long*)&config_word) +#define netxen_set_gb_drop_gb1(config_word) \ + set_bit(1, (unsigned long*)&config_word) +#define netxen_set_gb_drop_gb2(config_word) \ + set_bit(2, (unsigned long*)&config_word) +#define netxen_set_gb_drop_gb3(config_word) \ + set_bit(3, (unsigned long*)&config_word) + +#define netxen_clear_gb_drop_gb0(config_word) \ + clear_bit(0, (unsigned long*)&config_word) +#define netxen_clear_gb_drop_gb1(config_word) \ + clear_bit(1, (unsigned long*)&config_word) +#define netxen_clear_gb_drop_gb2(config_word) \ + clear_bit(2, (unsigned long*)&config_word) +#define netxen_clear_gb_drop_gb3(config_word) \ + clear_bit(3, (unsigned long*)&config_word) + +/* + * NIU XG MAC Config Register + * + * Bit 0 : tx_enable => 1:enable frame xmit, 0:disable + * Bit 2 : rx_enable => 1:enable frame recv, 0:disable + * Bit 4 : soft_reset => 1:reset the MAC , 0:no-op + * Bit 27: xaui_framer_reset + * Bit 28: xaui_rx_reset + * Bit 29: xaui_tx_reset + * Bit 30: xg_ingress_afifo_reset + * Bit 31: xg_egress_afifo_reset + */ + +#define netxen_xg_soft_reset(config_word) \ + set_bit(4, (unsigned long*)&config_word) + +/* + * MAC Control Register + * + * Bit 0-1 : id_pool0 + * Bit 2 : enable_xtnd0 + * Bit 4-5 : id_pool1 + * Bit 6 : enable_xtnd1 + * Bit 8-9 : id_pool2 + * Bit 10 : enable_xtnd2 + * Bit 12-13 : id_pool3 + * Bit 14 : enable_xtnd3 + * Bit 24-25 : mode_select + * Bit 28-31 : enable_pool + */ + +#define netxen_nic_mcr_set_id_pool0(config, val) \ + ((config) |= ((val) &0x03)) +#define netxen_nic_mcr_set_enable_xtnd0(config) \ + (set_bit(3, (unsigned long *)&(config))) +#define netxen_nic_mcr_set_id_pool1(config, val) \ + ((config) |= (((val) & 0x03) << 4)) +#define netxen_nic_mcr_set_enable_xtnd1(config) \ + (set_bit(6, (unsigned long *)&(config))) +#define netxen_nic_mcr_set_id_pool2(config, val) \ + ((config) |= (((val) & 0x03) << 8)) +#define netxen_nic_mcr_set_enable_xtnd2(config) \ + (set_bit(10, (unsigned long *)&(config))) +#define netxen_nic_mcr_set_id_pool3(config, val) \ + ((config) |= (((val) & 0x03) << 12)) +#define netxen_nic_mcr_set_enable_xtnd3(config) \ + (set_bit(14, (unsigned long *)&(config))) +#define netxen_nic_mcr_set_mode_select(config, val) \ + ((config) |= (((val) & 0x03) << 24)) +#define netxen_nic_mcr_set_enable_pool(config, val) \ + ((config) |= (((val) & 0x0f) << 28)) + +/* Set promiscuous mode for a GbE interface */ +int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port, + netxen_niu_prom_mode_t mode); +int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, + int port, netxen_niu_prom_mode_t mode); + +/* get/set the MAC address for a given MAC */ +int netxen_niu_macaddr_get(struct netxen_adapter *adapter, int port, + netxen_ethernet_macaddr_t * addr); +int netxen_niu_macaddr_set(struct netxen_port *port, + netxen_ethernet_macaddr_t addr); + +/* XG versons */ +int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int port, + netxen_ethernet_macaddr_t * addr); +int netxen_niu_xg_macaddr_set(struct netxen_port *port, + netxen_ethernet_macaddr_t addr); + +/* Generic enable for GbE ports. Will detect the speed of the link. */ +int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port); + +/* Disable a GbE interface */ +int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port); + +int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port); + +#endif /* __NETXEN_NIC_HW_H_ */ diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c new file mode 100644 index 000000000000..d122e51e43ab --- /dev/null +++ b/drivers/net/netxen/netxen_nic_init.c @@ -0,0 +1,1143 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * Source file for NIC routines to initialize the Phantom Hardware + * + */ + +#include +#include +#include "netxen_nic.h" +#include "netxen_nic_hw.h" +#include "netxen_nic_ioctl.h" +#include "netxen_nic_phan_reg.h" + +struct crb_addr_pair { + long addr; + long data; +}; + +#define NETXEN_MAX_CRB_XFORM 60 +static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; +#define NETXEN_ADDR_ERROR ((unsigned long ) 0xffffffff ) + +#define crb_addr_transform(name) \ + crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \ + NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20 + +static inline void +netxen_nic_locked_write_reg(struct netxen_adapter *adapter, + unsigned long off, int *data) +{ + void __iomem *addr = (adapter->ahw.pci_base + off); + writel(*data, addr); +} + +static void crb_addr_transform_setup(void) +{ + crb_addr_transform(XDMA); + crb_addr_transform(TIMR); + crb_addr_transform(SRE); + crb_addr_transform(SQN3); + crb_addr_transform(SQN2); + crb_addr_transform(SQN1); + crb_addr_transform(SQN0); + crb_addr_transform(SQS3); + crb_addr_transform(SQS2); + crb_addr_transform(SQS1); + crb_addr_transform(SQS0); + crb_addr_transform(RPMX7); + crb_addr_transform(RPMX6); + crb_addr_transform(RPMX5); + crb_addr_transform(RPMX4); + crb_addr_transform(RPMX3); + crb_addr_transform(RPMX2); + crb_addr_transform(RPMX1); + crb_addr_transform(RPMX0); + crb_addr_transform(ROMUSB); + crb_addr_transform(SN); + crb_addr_transform(QMN); + crb_addr_transform(QMS); + crb_addr_transform(PGNI); + crb_addr_transform(PGND); + crb_addr_transform(PGN3); + crb_addr_transform(PGN2); + crb_addr_transform(PGN1); + crb_addr_transform(PGN0); + crb_addr_transform(PGSI); + crb_addr_transform(PGSD); + crb_addr_transform(PGS3); + crb_addr_transform(PGS2); + crb_addr_transform(PGS1); + crb_addr_transform(PGS0); + crb_addr_transform(PS); + crb_addr_transform(PH); + crb_addr_transform(NIU); + crb_addr_transform(I2Q); + crb_addr_transform(EG); + crb_addr_transform(MN); + crb_addr_transform(MS); + crb_addr_transform(CAS2); + crb_addr_transform(CAS1); + crb_addr_transform(CAS0); + crb_addr_transform(CAM); + crb_addr_transform(C2C1); + crb_addr_transform(C2C0); +} + +int netxen_init_firmware(struct netxen_adapter *adapter) +{ + u32 state = 0, loops = 0, err = 0; + + /* Window 1 call */ + state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + + if (state == PHAN_INITIALIZE_ACK) + return 0; + + while (state != PHAN_INITIALIZE_COMPLETE && loops < 2000) { + udelay(100); + /* Window 1 call */ + state = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + + loops++; + } + if (loops >= 2000) { + printk(KERN_ERR "Cmd Peg initialization not complete:%x.\n", + state); + err = -EIO; + return err; + } + /* Window 1 call */ + writel(PHAN_INITIALIZE_ACK, + NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_STATE)); + + return err; +} + +void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) +{ + int ctxid, ring; + u32 i; + u32 num_rx_bufs = 0; + struct netxen_rcv_desc_ctx *rcv_desc; + + DPRINTK(INFO, "initializing some queues: %p\n", adapter); + for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + struct netxen_rx_buffer *rx_buf; + rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring]; + rcv_desc->rcv_free = rcv_desc->max_rx_desc_count; + rcv_desc->begin_alloc = 0; + rx_buf = rcv_desc->rx_buf_arr; + num_rx_bufs = rcv_desc->max_rx_desc_count; + /* + * Now go through all of them, set reference handles + * and put them in the queues. + */ + for (i = 0; i < num_rx_bufs; i++) { + rx_buf->ref_handle = i; + rx_buf->state = NETXEN_BUFFER_FREE; + + DPRINTK(INFO, "Rx buf:ctx%d i(%d) rx_buf:" + "%p\n", ctxid, i, rx_buf); + rx_buf++; + } + } + } + DPRINTK(INFO, "initialized buffers for %s and %s\n", + "adapter->free_cmd_buf_list", "adapter->free_rxbuf"); +} + +void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) +{ + if (netxen_nic_get_board_info(adapter) != 0) + printk("%s: Error getting board config info.\n", + netxen_nic_driver_name); + + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + adapter->ahw.max_ports = 4; + break; + + case NETXEN_NIC_XGBE: + adapter->ahw.max_ports = 1; + break; + + default: + printk(KERN_ERR "%s: Unknown board type\n", + netxen_nic_driver_name); + } +} + +void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) +{ + struct netxen_drvops *ops = adapter->ops; + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + ops->enable_phy_interrupts = + netxen_niu_gbe_enable_phy_interrupts; + ops->disable_phy_interrupts = + netxen_niu_gbe_disable_phy_interrupts; + ops->handle_phy_intr = netxen_nic_gbe_handle_phy_intr; + ops->macaddr_set = netxen_niu_macaddr_set; + ops->set_mtu = netxen_nic_set_mtu_gb; + ops->set_promisc = netxen_niu_set_promiscuous_mode; + ops->unset_promisc = netxen_niu_set_promiscuous_mode; + ops->phy_read = netxen_niu_gbe_phy_read; + ops->phy_write = netxen_niu_gbe_phy_write; + ops->init_port = netxen_niu_gbe_init_port; + ops->init_niu = netxen_nic_init_niu_gb; + ops->stop_port = netxen_niu_disable_gbe_port; + break; + + case NETXEN_NIC_XGBE: + ops->enable_phy_interrupts = + netxen_niu_xgbe_enable_phy_interrupts; + ops->disable_phy_interrupts = + netxen_niu_xgbe_disable_phy_interrupts; + ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; + ops->macaddr_set = netxen_niu_xg_macaddr_set; + ops->set_mtu = netxen_nic_set_mtu_xgb; + ops->set_promisc = netxen_niu_xg_set_promiscuous_mode; + ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode; + ops->stop_port = netxen_niu_disable_xg_port; + break; + + default: + break; + } +} + +/* + * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB + * address to external PCI CRB address. + */ +unsigned long netxen_decode_crb_addr(unsigned long addr) +{ + int i; + unsigned long base_addr, offset, pci_base; + + crb_addr_transform_setup(); + + pci_base = NETXEN_ADDR_ERROR; + base_addr = addr & 0xfff00000; + offset = addr & 0x000fffff; + + for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) { + if (crb_addr_xform[i] == base_addr) { + pci_base = i << 20; + break; + } + } + if (pci_base == NETXEN_ADDR_ERROR) + return pci_base; + else + return (pci_base + offset); +} + +static long rom_max_timeout = 10000; +static long rom_lock_timeout = 1000000; + +static inline int rom_lock(struct netxen_adapter *adapter) +{ + int iter; + u32 done = 0; + int timeout = 0; + + while (!done) { + /* acquire semaphore2 from PCI HW block */ + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_LOCK), + &done); + if (done == 1) + break; + if (timeout >= rom_lock_timeout) + return -EIO; + + timeout++; + /* + * Yield CPU + */ + if (!in_atomic()) + schedule(); + else { + for (iter = 0; iter < 20; iter++) + cpu_relax(); /*This a nop instr on i386 */ + } + } + netxen_nic_reg_write(adapter, NETXEN_ROM_LOCK_ID, ROM_LOCK_DRIVER); + return 0; +} + +static inline void rom_unlock(struct netxen_adapter *adapter) +{ + u32 val; + + /* release semaphore2 */ + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val); + +} + +int netxen_wait_rom_done(struct netxen_adapter *adapter) +{ + long timeout = 0; + long done = 0; + + while (done == 0) { + done = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_GLB_STATUS); + done &= 2; + timeout++; + if (timeout >= rom_max_timeout) { + printk("Timeout reached waiting for rom done"); + return -EIO; + } + } + return 0; +} + +static inline int +do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) +{ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); + udelay(100); /* prevent bursting on CRB */ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); + if (netxen_wait_rom_done(adapter)) { + printk("Error waiting for rom done\n"); + return -EIO; + } + /* reset abyte_cnt and dummy_byte_cnt */ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + udelay(100); /* prevent bursting on CRB */ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); + + *valp = netxen_nic_reg_read(adapter, NETXEN_ROMUSB_ROM_RDATA); + return 0; +} + +int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) +{ + int ret; + + if (rom_lock(adapter) != 0) + return -EIO; + + ret = do_rom_fast_read(adapter, addr, valp); + rom_unlock(adapter); + return ret; +} + +#define NETXEN_BOARDTYPE 0x4008 +#define NETXEN_BOARDNUM 0x400c +#define NETXEN_CHIPNUM 0x4010 +#define NETXEN_ROMBUS_RESET 0xFFFFFFFF +#define NETXEN_ROM_FIRST_BARRIER 0x800000000ULL +#define NETXEN_ROM_FOUND_INIT 0x400 + +int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) +{ + int addr, val, status; + int n, i; + int init_delay = 0; + struct crb_addr_pair *buf; + unsigned long off; + + /* resetall */ + status = netxen_nic_get_board_info(adapter); + if (status) + printk("%s: pinit_from_rom: Error getting board info\n", + netxen_nic_driver_name); + + netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, + NETXEN_ROMBUS_RESET); + + if (verbose) { + int val; + if (netxen_rom_fast_read(adapter, NETXEN_BOARDTYPE, &val) == 0) + printk("P2 ROM board type: 0x%08x\n", val); + else + printk("Could not read board type\n"); + if (netxen_rom_fast_read(adapter, NETXEN_BOARDNUM, &val) == 0) + printk("P2 ROM board num: 0x%08x\n", val); + else + printk("Could not read board number\n"); + if (netxen_rom_fast_read(adapter, NETXEN_CHIPNUM, &val) == 0) + printk("P2 ROM chip num: 0x%08x\n", val); + else + printk("Could not read chip number\n"); + } + + if (netxen_rom_fast_read(adapter, 0, &n) == 0 + && (n & NETXEN_ROM_FIRST_BARRIER)) { + n &= ~NETXEN_ROM_ROUNDUP; + if (n < NETXEN_ROM_FOUND_INIT) { + if (verbose) + printk("%s: %d CRB init values found" + " in ROM.\n", netxen_nic_driver_name, n); + } else { + printk("%s:n=0x%x Error! NetXen card flash not" + " initialized.\n", __FUNCTION__, n); + return -EIO; + } + buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); + if (buf == NULL) { + printk("%s: pinit_from_rom: Unable to calloc memory.\n", + netxen_nic_driver_name); + return -ENOMEM; + } + for (i = 0; i < n; i++) { + if (netxen_rom_fast_read(adapter, 8 * i + 4, &val) != 0 + || netxen_rom_fast_read(adapter, 8 * i + 8, + &addr) != 0) + return -EIO; + + buf[i].addr = addr; + buf[i].data = val; + + if (verbose) + printk("%s: PCI: 0x%08x == 0x%08x\n", + netxen_nic_driver_name, (unsigned int) + netxen_decode_crb_addr((unsigned long) + addr), val); + } + for (i = 0; i < n; i++) { + + off = + netxen_decode_crb_addr((unsigned long)buf[i].addr) + + NETXEN_PCI_CRBSPACE; + /* skipping cold reboot MAGIC */ + if (off == NETXEN_CAM_RAM(0x1fc)) + continue; + + /* After writing this register, HW needs time for CRB */ + /* to quiet down (else crb_window returns 0xffffffff) */ + if (off == NETXEN_ROMUSB_GLB_SW_RESET) { + init_delay = 1; + /* hold xdma in reset also */ + buf[i].data = 0x8000ff; + } + + if (ADDR_IN_WINDOW1(off)) { + writel(buf[i].data, + NETXEN_CRB_NORMALIZE(adapter, off)); + } else { + netxen_nic_pci_change_crbwindow(adapter, 0); + writel(buf[i].data, + adapter->ahw.pci_base + off); + + netxen_nic_pci_change_crbwindow(adapter, 1); + } + if (init_delay == 1) { + ssleep(1); + init_delay = 0; + } + msleep(1); + } + kfree(buf); + + /* disable_peg_cache_all */ + + /* unreset_net_cache */ + netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_SW_RESET, &val, + 4); + netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, + (val & 0xffffff0f)); + /* p2dn replyCount */ + netxen_crb_writelit_adapter(adapter, + NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); + /* disable_peg_cache 0 */ + netxen_crb_writelit_adapter(adapter, + NETXEN_CRB_PEG_NET_D + 0x4c, 8); + /* disable_peg_cache 1 */ + netxen_crb_writelit_adapter(adapter, + NETXEN_CRB_PEG_NET_I + 0x4c, 8); + + /* peg_clr_all */ + + /* peg_clr 0 */ + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, + 0); + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, + 0); + /* peg_clr 1 */ + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, + 0); + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, + 0); + /* peg_clr 2 */ + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, + 0); + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, + 0); + /* peg_clr 3 */ + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, + 0); + netxen_crb_writelit_adapter(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, + 0); + } + return 0; +} + +void netxen_phantom_init(struct netxen_adapter *adapter) +{ + u32 val = 0; + int loops = 0; + + netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, &val, 4); + writel(1, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); + + if (0 == val) { + while (val != PHAN_INITIALIZE_COMPLETE && loops < 200000) { + udelay(100); + val = + readl(NETXEN_CRB_NORMALIZE + (adapter, CRB_CMDPEG_STATE)); + loops++; + } + if (val != PHAN_INITIALIZE_COMPLETE) + printk("WARNING: Initial boot wait loop failed...\n"); + } +} + +int netxen_nic_rx_has_work(struct netxen_adapter *adapter) +{ + int ctx; + + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + struct netxen_recv_context *recv_ctx = + &(adapter->recv_ctx[ctx]); + u32 consumer; + struct status_desc *desc_head; + struct status_desc *desc; /* used to read status desc here */ + + consumer = recv_ctx->status_rx_consumer; + desc_head = recv_ctx->rcv_status_desc_head; + desc = &desc_head[consumer]; + + if (((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) + return 1; + } + + return 0; +} + +void netxen_watchdog_task(unsigned long v) +{ + int port_num; + struct netxen_port *port; + struct net_device *netdev; + struct netxen_adapter *adapter = (struct netxen_adapter *)v; + + for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) { + port = adapter->port[port_num]; + netdev = port->netdev; + + if ((netif_running(netdev)) && !netif_carrier_ok(netdev)) { + printk(KERN_INFO "%s port %d, %s carrier is now ok\n", + netxen_nic_driver_name, port_num, netdev->name); + netif_carrier_on(netdev); + } + + if (netif_queue_stopped(netdev)) + netif_wake_queue(netdev); + } + + netxen_nic_pci_change_crbwindow(adapter, 1); + + if (adapter->ops->handle_phy_intr) + adapter->ops->handle_phy_intr(adapter); + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); +} + +/* + * netxen_process_rcv() send the received packet to the protocol stack. + * and if the number of receives exceeds RX_BUFFERS_REFILL, then we + * invoke the routine to send more rx buffers to the Phantom... + */ +void +netxen_process_rcv(struct netxen_adapter *adapter, int ctxid, + struct status_desc *desc) +{ + struct netxen_port *port = adapter->port[STATUS_DESC_PORT(desc)]; + struct pci_dev *pdev = port->pdev; + struct net_device *netdev = port->netdev; + int index = le16_to_cpu(desc->reference_handle); + struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); + struct netxen_rx_buffer *buffer; + struct sk_buff *skb; + u32 length = le16_to_cpu(desc->total_length); + u32 desc_ctx; + struct netxen_rcv_desc_ctx *rcv_desc; + int ret; + + desc_ctx = STATUS_DESC_TYPE(desc); + if (unlikely(desc_ctx >= NUM_RCV_DESC_RINGS)) { + printk("%s: %s Bad Rcv descriptor ring\n", + netxen_nic_driver_name, netdev->name); + return; + } + + rcv_desc = &recv_ctx->rcv_desc[desc_ctx]; + buffer = &rcv_desc->rx_buf_arr[index]; + + pci_unmap_single(pdev, buffer->dma, rcv_desc->dma_size, + PCI_DMA_FROMDEVICE); + + skb = (struct sk_buff *)buffer->skb; + + if (likely(STATUS_DESC_STATUS(desc) == STATUS_CKSUM_OK)) { + port->stats.csummed++; + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else + skb->ip_summed = CHECKSUM_NONE; + skb->dev = netdev; + skb_put(skb, length); + skb->protocol = eth_type_trans(skb, netdev); + + ret = netif_receive_skb(skb); + + /* + * RH: Do we need these stats on a regular basis. Can we get it from + * Linux stats. + */ + switch (ret) { + case NET_RX_SUCCESS: + port->stats.uphappy++; + break; + + case NET_RX_CN_LOW: + port->stats.uplcong++; + break; + + case NET_RX_CN_MOD: + port->stats.upmcong++; + break; + + case NET_RX_CN_HIGH: + port->stats.uphcong++; + break; + + case NET_RX_DROP: + port->stats.updropped++; + break; + + default: + port->stats.updunno++; + break; + } + + netdev->last_rx = jiffies; + + rcv_desc->rcv_free++; + rcv_desc->rcv_pending--; + + /* + * We just consumed one buffer so post a buffer. + */ + adapter->stats.post_called++; + buffer->skb = NULL; + buffer->state = NETXEN_BUFFER_FREE; + + port->stats.no_rcv++; + port->stats.rxbytes += length; +} + +/* Process Receive status ring */ +u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max) +{ + struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctxid]); + struct status_desc *desc_head = recv_ctx->rcv_status_desc_head; + struct status_desc *desc; /* used to read status desc here */ + u32 consumer = recv_ctx->status_rx_consumer; + int count = 0, ring; + + DPRINTK(INFO, "procesing receive\n"); + /* + * we assume in this case that there is only one port and that is + * port #1...changes need to be done in firmware to indicate port + * number as part of the descriptor. This way we will be able to get + * the netdev which is associated with that device. + */ + while (count < max) { + desc = &desc_head[consumer]; + if (!((le16_to_cpu(desc->owner)) & STATUS_OWNER_HOST)) { + DPRINTK(ERR, "desc %p ownedby %x\n", desc, desc->owner); + break; + } + netxen_process_rcv(adapter, ctxid, desc); + desc->owner = STATUS_OWNER_PHANTOM; + consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1); + count++; + } + if (count) { + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + netxen_post_rx_buffers(adapter, ctxid, ring); + } + } + + /* update the consumer index in phantom */ + if (count) { + adapter->stats.process_rcv++; + recv_ctx->status_rx_consumer = consumer; + + /* Window = 1 */ + writel(consumer, + NETXEN_CRB_NORMALIZE(adapter, + recv_crb_registers[ctxid]. + crb_rcv_status_consumer)); + } + + return count; +} + +/* Process Command status ring */ +void netxen_process_cmd_ring(unsigned long data) +{ + u32 last_consumer; + u32 consumer; + struct netxen_adapter *adapter = (struct netxen_adapter *)data; + int count = 0; + struct netxen_cmd_buffer *buffer; + struct netxen_port *port; /* port #1 */ + struct netxen_port *nport; + struct pci_dev *pdev; + struct netxen_skb_frag *frag; + u32 i; + struct sk_buff *skb = NULL; + int p; + + spin_lock(&adapter->tx_lock); + last_consumer = adapter->last_cmd_consumer; + DPRINTK(INFO, "procesing xmit complete\n"); + /* we assume in this case that there is only one port and that is + * port #1...changes need to be done in firmware to indicate port + * number as part of the descriptor. This way we will be able to get + * the netdev which is associated with that device. + */ + /* Window = 1 */ + consumer = + readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); + + if (last_consumer == consumer) { /* Ring is empty */ + DPRINTK(INFO, "last_consumer %d == consumer %d\n", + last_consumer, consumer); + spin_unlock(&adapter->tx_lock); + return; + } + + adapter->proc_cmd_buf_counter++; + adapter->stats.process_xmit++; + /* + * Not needed - does not seem to be used anywhere. + * adapter->cmd_consumer = consumer; + */ + spin_unlock(&adapter->tx_lock); + + while ((last_consumer != consumer) && (count < MAX_STATUS_HANDLE)) { + buffer = &adapter->cmd_buf_arr[last_consumer]; + port = adapter->port[buffer->port]; + pdev = port->pdev; + frag = &buffer->frag_array[0]; + skb = buffer->skb; + if (skb && (cmpxchg(&buffer->skb, skb, 0) == skb)) { + pci_unmap_single(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + for (i = 1; i < buffer->frag_count; i++) { + DPRINTK(INFO, "getting fragment no %d\n", i); + frag++; /* Get the next frag */ + pci_unmap_page(pdev, frag->dma, frag->length, + PCI_DMA_TODEVICE); + } + + port->stats.skbfreed++; + dev_kfree_skb_any(skb); + skb = NULL; + } else if (adapter->proc_cmd_buf_counter == 1) { + port->stats.txnullskb++; + } + if (unlikely(netif_queue_stopped(port->netdev) + && netif_carrier_ok(port->netdev)) + && ((jiffies - port->netdev->trans_start) > + port->netdev->watchdog_timeo)) { + schedule_work(&port->adapter->tx_timeout_task); + } + + last_consumer = get_next_index(last_consumer, + adapter->max_tx_desc_count); + count++; + } + adapter->stats.noxmitdone += count; + + count = 0; + spin_lock(&adapter->tx_lock); + if ((--adapter->proc_cmd_buf_counter) == 0) { + adapter->last_cmd_consumer = last_consumer; + while ((adapter->last_cmd_consumer != consumer) + && (count < MAX_STATUS_HANDLE)) { + buffer = + &adapter->cmd_buf_arr[adapter->last_cmd_consumer]; + count++; + if (buffer->skb) + break; + else + adapter->last_cmd_consumer = + get_next_index(adapter->last_cmd_consumer, + adapter->max_tx_desc_count); + } + } + if (count) { + for (p = 0; p < adapter->ahw.max_ports; p++) { + nport = adapter->port[p]; + if (netif_queue_stopped(nport->netdev) + && (nport->flags & NETXEN_NETDEV_STATUS)) { + netif_wake_queue(nport->netdev); + nport->flags &= ~NETXEN_NETDEV_STATUS; + } + } + } + + spin_unlock(&adapter->tx_lock); + DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer, + __FUNCTION__); +} + +/* + * netxen_post_rx_buffers puts buffer in the Phantom memory + */ +void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) +{ + struct pci_dev *pdev = adapter->ahw.pdev; + struct sk_buff *skb; + struct netxen_recv_context *recv_ctx = &(adapter->recv_ctx[ctx]); + struct netxen_rcv_desc_ctx *rcv_desc = NULL; + struct netxen_recv_crb *crbarea = &recv_crb_registers[ctx]; + struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; + u32 producer; + struct rcv_desc *pdesc; + struct netxen_rx_buffer *buffer; + int count = 0; + int index = 0; + + adapter->stats.post_called++; + rcv_desc = &recv_ctx->rcv_desc[ringid]; + rcv_desc_crb = &crbarea->rcv_desc_crb[ringid]; + + producer = rcv_desc->producer; + index = rcv_desc->begin_alloc; + buffer = &rcv_desc->rx_buf_arr[index]; + /* We can start writing rx descriptors into the phantom memory. */ + while (buffer->state == NETXEN_BUFFER_FREE) { + skb = dev_alloc_skb(rcv_desc->skb_size); + if (unlikely(!skb)) { + /* + * We need to schedule the posting of buffers to the pegs. + */ + rcv_desc->begin_alloc = index; + DPRINTK(ERR, "unm_post_rx_buffers: " + " allocated only %d buffers\n", count); + break; + } + count++; /* now there should be no failure */ + pdesc = &rcv_desc->desc_head[producer]; + skb_reserve(skb, NET_IP_ALIGN); + /* + * This will be setup when we receive the + * buffer after it has been filled + * skb->dev = netdev; + */ + buffer->skb = skb; + buffer->state = NETXEN_BUFFER_BUSY; + buffer->dma = pci_map_single(pdev, skb->data, + rcv_desc->dma_size, + PCI_DMA_FROMDEVICE); + /* make a rcv descriptor */ + pdesc->reference_handle = le16_to_cpu(buffer->ref_handle); + pdesc->buffer_length = le16_to_cpu(rcv_desc->dma_size); + pdesc->addr_buffer = cpu_to_le64(buffer->dma); + DPRINTK(INFO, "done writing descripter\n"); + producer = + get_next_index(producer, rcv_desc->max_rx_desc_count); + index = get_next_index(index, rcv_desc->max_rx_desc_count); + buffer = &rcv_desc->rx_buf_arr[index]; + } + + /* if we did allocate buffers, then write the count to Phantom */ + if (count) { + rcv_desc->begin_alloc = index; + rcv_desc->rcv_pending += count; + adapter->stats.lastposted = count; + adapter->stats.posted += count; + rcv_desc->producer = producer; + if (rcv_desc->rcv_free >= 32) { + rcv_desc->rcv_free = 0; + /* Window = 1 */ + writel((producer - 1) & + (rcv_desc->max_rx_desc_count - 1), + NETXEN_CRB_NORMALIZE(adapter, + rcv_desc_crb-> + crb_rcv_producer_offset)); + wmb(); + } + } +} + +int netxen_nic_tx_has_work(struct netxen_adapter *adapter) +{ + if (find_diff_among(adapter->last_cmd_consumer, + adapter->cmd_producer, + adapter->max_tx_desc_count) > 0) + return 1; + + return 0; +} + +int +netxen_nic_fill_statistics(struct netxen_adapter *adapter, + struct netxen_port *port, + struct netxen_statistics *netxen_stats) +{ + void __iomem *addr; + + if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + netxen_nic_pci_change_crbwindow(adapter, 0); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_BYTE_CNT, + &(netxen_stats->tx_bytes)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_TX_FRAME_CNT, + &(netxen_stats->tx_packets)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_BYTE_CNT, + &(netxen_stats->rx_bytes)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_RX_FRAME_CNT, + &(netxen_stats->rx_packets)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_AGGR_ERROR_CNT, + &(netxen_stats->rx_errors)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_CRC_ERROR_CNT, + &(netxen_stats->rx_crc_errors)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR, + &(netxen_stats-> + rx_long_length_error)); + NETXEN_NIC_LOCKED_READ_REG(NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR, + &(netxen_stats-> + rx_short_length_error)); + + netxen_nic_pci_change_crbwindow(adapter, 1); + } else { + spin_lock_bh(&adapter->tx_lock); + netxen_stats->tx_bytes = port->stats.txbytes; + netxen_stats->tx_packets = port->stats.xmitedframes + + port->stats.xmitfinished; + netxen_stats->rx_bytes = port->stats.rxbytes; + netxen_stats->rx_packets = port->stats.no_rcv; + netxen_stats->rx_errors = port->stats.rcvdbadskb; + netxen_stats->tx_errors = port->stats.nocmddescriptor; + netxen_stats->rx_short_length_error = port->stats.uplcong; + netxen_stats->rx_long_length_error = port->stats.uphcong; + netxen_stats->rx_crc_errors = 0; + netxen_stats->rx_mac_errors = 0; + spin_unlock_bh(&adapter->tx_lock); + } + return 0; +} + +void netxen_nic_clear_stats(struct netxen_adapter *adapter) +{ + struct netxen_port *port; + int port_num; + + memset(&adapter->stats, 0, sizeof(adapter->stats)); + for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) { + port = adapter->port[port_num]; + memset(&port->stats, 0, sizeof(port->stats)); + } +} + +int +netxen_nic_clear_statistics(struct netxen_adapter *adapter, + struct netxen_port *port) +{ + int data = 0; + + netxen_nic_pci_change_crbwindow(adapter, 0); + + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_BYTE_CNT, &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_TX_FRAME_CNT, + &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_BYTE_CNT, &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_RX_FRAME_CNT, + &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_AGGR_ERROR_CNT, + &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_CRC_ERROR_CNT, + &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_OVERSIZE_FRAME_ERR, + &data); + netxen_nic_locked_write_reg(adapter, NETXEN_NIU_XGE_UNDERSIZE_FRAME_ERR, + &data); + + netxen_nic_pci_change_crbwindow(adapter, 1); + netxen_nic_clear_stats(adapter); + return 0; +} + +int +netxen_nic_do_ioctl(struct netxen_adapter *adapter, void *u_data, + struct netxen_port *port) +{ + struct netxen_nic_ioctl_data data; + struct netxen_nic_ioctl_data *up_data; + int retval = 0; + struct netxen_statistics netxen_stats; + + up_data = (void *)u_data; + + DPRINTK(INFO, "doing ioctl for %p\n", adapter); + if (copy_from_user(&data, (void __user *)up_data, sizeof(data))) { + /* evil user tried to crash the kernel */ + DPRINTK(ERR, "bad copy from userland: %d\n", (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + + /* Shouldn't access beyond legal limits of "char u[64];" member */ + if (!data.ptr && (data.size > sizeof(data.u))) { + /* evil user tried to crash the kernel */ + DPRINTK(ERR, "bad size: %d\n", data.size); + retval = -EFAULT; + goto error_out; + } + + switch (data.cmd) { + case netxen_nic_cmd_pci_read: + if ((retval = netxen_nic_hw_read_wx(adapter, data.off, + &(data.u), data.size))) + goto error_out; + if (copy_to_user + ((void __user *)&(up_data->u), &(data.u), data.size)) { + DPRINTK(ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + data.rv = 0; + break; + + case netxen_nic_cmd_pci_write: + data.rv = netxen_nic_hw_write_wx(adapter, data.off, &(data.u), + data.size); + break; + + case netxen_nic_cmd_pci_config_read: + switch (data.size) { + case 1: + data.rv = pci_read_config_byte(adapter->ahw.pdev, + data.off, + (char *)&(data.u)); + break; + case 2: + data.rv = pci_read_config_word(adapter->ahw.pdev, + data.off, + (short *)&(data.u)); + break; + case 4: + data.rv = pci_read_config_dword(adapter->ahw.pdev, + data.off, + (u32 *) & (data.u)); + break; + } + if (copy_to_user + ((void __user *)&(up_data->u), &(data.u), data.size)) { + DPRINTK(ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + break; + + case netxen_nic_cmd_pci_config_write: + switch (data.size) { + case 1: + data.rv = pci_write_config_byte(adapter->ahw.pdev, + data.off, + *(char *)&(data.u)); + break; + case 2: + data.rv = pci_write_config_word(adapter->ahw.pdev, + data.off, + *(short *)&(data.u)); + break; + case 4: + data.rv = pci_write_config_dword(adapter->ahw.pdev, + data.off, + *(u32 *) & (data.u)); + break; + } + break; + + case netxen_nic_cmd_get_stats: + data.rv = + netxen_nic_fill_statistics(adapter, port, &netxen_stats); + if (copy_to_user + ((void __user *)(up_data->ptr), (void *)&netxen_stats, + sizeof(struct netxen_statistics))) { + DPRINTK(ERR, "bad copy to userland: %d\n", + (int)sizeof(netxen_stats)); + retval = -EFAULT; + goto error_out; + } + up_data->rv = data.rv; + break; + + case netxen_nic_cmd_clear_stats: + data.rv = netxen_nic_clear_statistics(adapter, port); + up_data->rv = data.rv; + break; + + case netxen_nic_cmd_get_version: + if (copy_to_user + ((void __user *)&(up_data->u), NETXEN_NIC_LINUX_VERSIONID, + sizeof(NETXEN_NIC_LINUX_VERSIONID))) { + DPRINTK(ERR, "bad copy to userland: %d\n", + (int)sizeof(data)); + retval = -EFAULT; + goto error_out; + } + break; + + default: + DPRINTK(INFO, "bad command %d for %p\n", data.cmd, adapter); + retval = -EOPNOTSUPP; + goto error_out; + } + put_user(data.rv, (u16 __user *) (&(up_data->rv))); + DPRINTK(INFO, "done ioctl for %p well.\n", adapter); + + error_out: + return retval; +} diff --git a/drivers/net/netxen/netxen_nic_ioctl.h b/drivers/net/netxen/netxen_nic_ioctl.h new file mode 100644 index 000000000000..806818eb9630 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_ioctl.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + */ + +#ifndef __NETXEN_NIC_IOCTL_H__ +#define __NETXEN_NIC_IOCTL_H__ + +#include + +#define NETXEN_CMD_START SIOCDEVPRIVATE +#define NETXEN_NIC_CMD (NETXEN_CMD_START + 1) +#define NETXEN_NIC_NAME (NETXEN_CMD_START + 2) + +typedef enum { + netxen_nic_cmd_none = 0, + netxen_nic_cmd_pci_read, + netxen_nic_cmd_pci_write, + netxen_nic_cmd_pci_mem_read, + netxen_nic_cmd_pci_mem_write, + netxen_nic_cmd_pci_config_read, + netxen_nic_cmd_pci_config_write, + netxen_nic_cmd_get_stats, + netxen_nic_cmd_clear_stats, + netxen_nic_cmd_get_version +} netxen_nic_ioctl_cmd_t; + +struct netxen_nic_ioctl_data { + u32 cmd; + u32 unused1; + u64 off; + u32 size; + u32 rv; + char u[64]; + void *ptr; +}; + +struct netxen_statistics { + u64 rx_packets; + u64 tx_packets; + u64 rx_bytes; + u64 rx_errors; + u64 tx_bytes; + u64 tx_errors; + u64 rx_crc_errors; + u64 rx_short_length_error; + u64 rx_long_length_error; + u64 rx_mac_errors; +}; + +#endif /* __NETXEN_NIC_IOCTL_H_ */ diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c new file mode 100644 index 000000000000..f1c3e5af03a9 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_isr.c @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + */ + +#include +#include + +#include "netxen_nic.h" +#include "netxen_nic_hw.h" +#include "netxen_nic_phan_reg.h" + +/* + * netxen_nic_get_stats - Get System Network Statistics + * @netdev: network interface device structure + */ +struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct net_device_stats *stats = &port->net_stats; + + memset(stats, 0, sizeof(*stats)); + + /* total packets received */ + stats->rx_packets = port->stats.no_rcv; + /* total packets transmitted */ + stats->tx_packets = port->stats.xmitedframes + port->stats.xmitfinished; + /* total bytes received */ + stats->rx_bytes = port->stats.rxbytes; + /* total bytes transmitted */ + stats->tx_bytes = port->stats.txbytes; + /* bad packets received */ + stats->rx_errors = port->stats.rcvdbadskb; + /* packet transmit problems */ + stats->tx_errors = port->stats.nocmddescriptor; + /* no space in linux buffers */ + stats->rx_dropped = port->stats.updropped; + /* no space available in linux */ + stats->tx_dropped = port->stats.txdropped; + + return stats; +} + +void netxen_indicate_link_status(struct netxen_adapter *adapter, u32 portno, + u32 link) +{ + struct netxen_port *pport = adapter->port[portno]; + struct net_device *netdev = pport->netdev; + + if (link) + netif_carrier_on(netdev); + else + netif_carrier_off(netdev); +} + +void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno, + u32 enable) +{ + __le32 int_src; + struct netxen_port *port; + + /* This should clear the interrupt source */ + if (adapter->ops->phy_read) + adapter->ops->phy_read(adapter, portno, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, + &int_src); + if (int_src == 0) { + DPRINTK(INFO, "No phy interrupts for port #%d\n", portno); + return; + } + if (adapter->ops->disable_phy_interrupts) + adapter->ops->disable_phy_interrupts(adapter, portno); + + port = adapter->port[portno]; + + if (netxen_get_phy_int_jabber(int_src)) + DPRINTK(INFO, "NetXen: %s Jabber interrupt \n", + port->netdev->name); + + if (netxen_get_phy_int_polarity_changed(int_src)) + DPRINTK(INFO, "NetXen: %s POLARITY CHANGED int \n", + port->netdev->name); + + if (netxen_get_phy_int_energy_detect(int_src)) + DPRINTK(INFO, "NetXen: %s ENERGY DETECT INT \n", + port->netdev->name); + + if (netxen_get_phy_int_downshift(int_src)) + DPRINTK(INFO, "NetXen: %s DOWNSHIFT INT \n", + port->netdev->name); + /* write it down later.. */ + if ((netxen_get_phy_int_speed_changed(int_src)) + || (netxen_get_phy_int_link_status_changed(int_src))) { + __le32 status; + + DPRINTK(INFO, "NetXen: %s SPEED CHANGED OR" + " LINK STATUS CHANGED \n", port->netdev->name); + + if (adapter->ops->phy_read + && adapter->ops->phy_read(adapter, portno, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) == 0) { + if (netxen_get_phy_int_link_status_changed(int_src)) { + if (netxen_get_phy_link(status)) { + netxen_niu_gbe_init_port(adapter, + portno); + printk("%s: %s Link UP\n", + netxen_nic_driver_name, + port->netdev->name); + + } else { + printk("%s: %s Link DOWN\n", + netxen_nic_driver_name, + port->netdev->name); + } + netxen_indicate_link_status(adapter, portno, + netxen_get_phy_link + (status)); + } + } + } + if (adapter->ops->enable_phy_interrupts) + adapter->ops->enable_phy_interrupts(adapter, portno); +} + +void netxen_nic_isr_other(struct netxen_adapter *adapter) +{ + u32 enable, portno; + u32 i2qhi; + + /* + * bit 3 is for i2qInt, if high its enabled + * check for phy interrupts + * read vector and check for bit 45 for phy + * clear int by writing the same value into ISR_INT_VECTOR REG + */ + + DPRINTK(INFO, "I2Q is the source of INT \n"); + + /* verify the offset */ + i2qhi = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); + + DPRINTK(INFO, "isr NETXEN_I2Q_CLR_PCI_HI = 0x%x \n", i2qhi); + + if (i2qhi & 0x4000) { + for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) { + DPRINTK(INFO, "External PHY interrupt ON PORT %d\n", + portno); + + enable = 1; + netxen_handle_port_int(adapter, portno, enable); + } + + /* Clear the interrupt on I2Q */ + writel((u32) i2qhi, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); + + } +} + +void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter) +{ + u32 val; + val = readl(NETXEN_CRB_NORMALIZE(adapter, ISR_INT_VECTOR)); + if (val & 0x4) { + adapter->stats.otherints++; + netxen_nic_isr_other(adapter); + } +} + +void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) +{ + struct net_device *netdev = adapter->port[0]->netdev; + u32 val; + + /* WINDOW = 1 */ + val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); + + if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) { + printk(KERN_INFO "%s: %s NIC Link is down\n", + netxen_nic_driver_name, netdev->name); + adapter->ahw.xg_linkup = 0; + /* read twice to clear sticky bits */ + /* WINDOW = 0 */ + netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val); + netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val); + + if ((val & 0xffb) != 0xffb) { + printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n", + netxen_nic_driver_name, val); + } + } else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) { + printk(KERN_INFO "%s: %s NIC Link is up\n", + netxen_nic_driver_name, netdev->name); + adapter->ahw.xg_linkup = 1; + } +} diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c new file mode 100644 index 000000000000..b54ea164e0ea --- /dev/null +++ b/drivers/net/netxen/netxen_nic_main.c @@ -0,0 +1,1116 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * Main source file for NetXen NIC Driver on Linux + * + */ + +#include "netxen_nic_hw.h" + +#include "netxen_nic.h" +#define DEFINE_GLOBAL_RECV_CRB +#include "netxen_nic_phan_reg.h" +#include "netxen_nic_ioctl.h" + +MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); + +char netxen_nic_driver_name[] = "netxen"; +static char netxen_nic_driver_string[] = "NetXen Network Driver version " + NETXEN_NIC_LINUX_VERSIONID "-" NETXEN_NIC_BUILD_NO; + +#define NETXEN_NETDEV_WEIGHT 120 +#define NETXEN_ADAPTER_UP_MAGIC 777 + +/* Local functions to NetXen NIC driver */ +static int __devinit netxen_nic_probe(struct pci_dev *pdev, + const struct pci_device_id *ent); +static void __devexit netxen_nic_remove(struct pci_dev *pdev); +static int netxen_nic_open(struct net_device *netdev); +static int netxen_nic_close(struct net_device *netdev); +static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *); +static void netxen_tx_timeout(struct net_device *netdev); +static void netxen_tx_timeout_task(struct net_device *netdev); +static void netxen_watchdog(unsigned long); +static int netxen_handle_int(struct netxen_adapter *, struct net_device *); +static int netxen_nic_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd); +static int netxen_nic_poll(struct net_device *dev, int *budget); +#ifdef CONFIG_NET_POLL_CONTROLLER +static void netxen_nic_poll_controller(struct net_device *netdev); +#endif +static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs); + +/* PCI Device ID Table */ +static struct pci_device_id netxen_pci_tbl[] __devinitdata = { + {PCI_DEVICE(0x4040, 0x0001)}, + {PCI_DEVICE(0x4040, 0x0002)}, + {PCI_DEVICE(0x4040, 0x0003)}, + {PCI_DEVICE(0x4040, 0x0004)}, + {PCI_DEVICE(0x4040, 0x0005)}, + {0,} +}; + +MODULE_DEVICE_TABLE(pci, netxen_pci_tbl); + +/* + * netxen_nic_probe() + * + * The Linux system will invoke this after identifying the vendor ID and + * device Id in the pci_tbl supported by this module. + * + * A quad port card has one operational PCI config space, (function 0), + * which is used to access all four ports. + * + * This routine will initialize the adapter, and setup the global parameters + * along with the port's specific structure. + */ +static int __devinit +netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + struct net_device *netdev = NULL; + struct netxen_adapter *adapter = NULL; + struct netxen_port *port = NULL; + u8 __iomem *mem_ptr = NULL; + unsigned long mem_base, mem_len; + int pci_using_dac, i, err; + int ring; + struct netxen_recv_context *recv_ctx = NULL; + struct netxen_rcv_desc_ctx *rcv_desc = NULL; + struct netxen_cmd_buffer *cmd_buf_arr = NULL; + u64 mac_addr[FLASH_NUM_PORTS + 1]; + int valid_mac; + + if ((err = pci_enable_device(pdev))) + return err; + if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { + err = -ENODEV; + goto err_out_disable_pdev; + } + + if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) + goto err_out_disable_pdev; + + pci_set_master(pdev); + if ((pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) && + (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) == 0)) + pci_using_dac = 1; + else { + if ((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK)) || + (err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))) + goto err_out_free_res; + + pci_using_dac = 0; + } + + /* remap phys address */ + mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ + mem_len = pci_resource_len(pdev, 0); + + /* 128 Meg of memory */ + mem_ptr = ioremap(mem_base, NETXEN_PCI_MAPSIZE_BYTES); + if (mem_ptr == 0UL) { + printk(KERN_ERR "%s: Cannot ioremap adapter memory aborting." + ":%p\n", netxen_nic_driver_name, mem_ptr); + err = -EIO; + goto err_out_free_res; + } + +/* + * Allocate a adapter structure which will manage all the initialization + * as well as the common resources for all ports... + * all the ports will have pointer to this adapter as well as Adapter + * will have pointers of all the ports structures. + */ + + /* One adapter structure for all 4 ports.... */ + adapter = kzalloc(sizeof(struct netxen_adapter), GFP_KERNEL); + if (adapter == NULL) { + printk(KERN_ERR "%s: Could not allocate adapter memory:%d\n", + netxen_nic_driver_name, + (int)sizeof(struct netxen_adapter)); + err = -ENOMEM; + goto err_out_iounmap; + } + + adapter->max_tx_desc_count = MAX_CMD_DESCRIPTORS; + adapter->max_rx_desc_count = MAX_RCV_DESCRIPTORS; + adapter->max_jumbo_rx_desc_count = MAX_JUMBO_RCV_DESCRIPTORS; + + pci_set_drvdata(pdev, adapter); + + cmd_buf_arr = (struct netxen_cmd_buffer *)vmalloc(TX_RINGSIZE); + if (cmd_buf_arr == NULL) { + err = -ENOMEM; + goto err_out_free_adapter; + } + memset(cmd_buf_arr, 0, TX_RINGSIZE); + + for (i = 0; i < MAX_RCV_CTX; ++i) { + recv_ctx = &adapter->recv_ctx[i]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + switch (RCV_DESC_TYPE(ring)) { + case RCV_DESC_NORMAL: + rcv_desc->max_rx_desc_count = + adapter->max_rx_desc_count; + rcv_desc->flags = RCV_DESC_NORMAL; + rcv_desc->dma_size = RX_DMA_MAP_LEN; + rcv_desc->skb_size = MAX_RX_BUFFER_LENGTH; + break; + + case RCV_DESC_JUMBO: + rcv_desc->max_rx_desc_count = + adapter->max_jumbo_rx_desc_count; + rcv_desc->flags = RCV_DESC_JUMBO; + rcv_desc->dma_size = RX_JUMBO_DMA_MAP_LEN; + rcv_desc->skb_size = MAX_RX_JUMBO_BUFFER_LENGTH; + break; + + } + rcv_desc->rx_buf_arr = (struct netxen_rx_buffer *) + vmalloc(RCV_BUFFSIZE); + + if (rcv_desc->rx_buf_arr == NULL) { + err = -ENOMEM; + goto err_out_free_rx_buffer; + } + memset(rcv_desc->rx_buf_arr, 0, RCV_BUFFSIZE); + } + + } + + adapter->ops = kzalloc(sizeof(struct netxen_drvops), GFP_KERNEL); + if (adapter->ops == NULL) { + printk(KERN_ERR + "%s: Could not allocate memory for adapter->ops:%d\n", + netxen_nic_driver_name, + (int)sizeof(struct netxen_adapter)); + err = -ENOMEM; + goto err_out_free_rx_buffer; + } + + adapter->cmd_buf_arr = cmd_buf_arr; + adapter->ahw.pci_base = mem_ptr; + spin_lock_init(&adapter->tx_lock); + spin_lock_init(&adapter->lock); + /* initialize the buffers in adapter */ + netxen_initialize_adapter_sw(adapter); + /* + * Set the CRB window to invalid. If any register in window 0 is + * accessed it should set the window to 0 and then reset it to 1. + */ + adapter->curr_window = 255; + /* + * Adapter in our case is quad port so initialize it before + * initializing the ports + */ + netxen_initialize_adapter_hw(adapter); /* initialize the adapter */ + + netxen_initialize_adapter_ops(adapter); + + init_timer(&adapter->watchdog_timer); + adapter->ahw.xg_linkup = 0; + adapter->watchdog_timer.function = &netxen_watchdog; + adapter->watchdog_timer.data = (unsigned long)adapter; + INIT_WORK(&adapter->watchdog_task, + (void (*)(void *))netxen_watchdog_task, adapter); + adapter->ahw.pdev = pdev; + adapter->proc_cmd_buf_counter = 0; + pci_read_config_byte(pdev, PCI_REVISION_ID, &adapter->ahw.revision_id); + + if (pci_enable_msi(pdev)) { + adapter->flags &= ~NETXEN_NIC_MSI_ENABLED; + printk(KERN_WARNING "%s: unable to allocate MSI interrupt" + " error\n", netxen_nic_driver_name); + } else + adapter->flags |= NETXEN_NIC_MSI_ENABLED; + + if (netxen_is_flash_supported(adapter) == 0 && + netxen_get_flash_mac_addr(adapter, mac_addr) == 0) + valid_mac = 1; + else + valid_mac = 0; + + /* initialize the all the ports */ + + for (i = 0; i < adapter->ahw.max_ports; i++) { + netdev = alloc_etherdev(sizeof(struct netxen_port)); + if (!netdev) { + printk(KERN_ERR "%s: could not allocate netdev for port" + " %d\n", netxen_nic_driver_name, i + 1); + goto err_out_free_dev; + } + + SET_MODULE_OWNER(netdev); + + port = netdev_priv(netdev); + port->netdev = netdev; + port->pdev = pdev; + port->adapter = adapter; + port->portnum = i; /* Gigabit port number from 0-3 */ + + netdev->open = netxen_nic_open; + netdev->stop = netxen_nic_close; + netdev->hard_start_xmit = netxen_nic_xmit_frame; + netdev->get_stats = netxen_nic_get_stats; + netdev->set_multicast_list = netxen_nic_set_multi; + netdev->set_mac_address = netxen_nic_set_mac; + netdev->change_mtu = netxen_nic_change_mtu; + netdev->do_ioctl = netxen_nic_ioctl; + netdev->tx_timeout = netxen_tx_timeout; + netdev->watchdog_timeo = HZ; + + SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); + netdev->poll = netxen_nic_poll; + netdev->weight = NETXEN_NETDEV_WEIGHT; +#ifdef CONFIG_NET_POLL_CONTROLLER + netdev->poll_controller = netxen_nic_poll_controller; +#endif + /* ScatterGather support */ + netdev->features = NETIF_F_SG; + netdev->features |= NETIF_F_IP_CSUM; + netdev->features |= NETIF_F_TSO; + + if (pci_using_dac) + netdev->features |= NETIF_F_HIGHDMA; + + if (valid_mac) { + unsigned char *p = (unsigned char *)&mac_addr[i]; + netdev->dev_addr[0] = *(p + 5); + netdev->dev_addr[1] = *(p + 4); + netdev->dev_addr[2] = *(p + 3); + netdev->dev_addr[3] = *(p + 2); + netdev->dev_addr[4] = *(p + 1); + netdev->dev_addr[5] = *(p + 0); + + memcpy(netdev->perm_addr, netdev->dev_addr, + netdev->addr_len); + if (!is_valid_ether_addr(netdev->perm_addr)) { + printk(KERN_ERR "%s: Bad MAC address " + "%02x:%02x:%02x:%02x:%02x:%02x.\n", + netxen_nic_driver_name, + netdev->dev_addr[0], + netdev->dev_addr[1], + netdev->dev_addr[2], + netdev->dev_addr[3], + netdev->dev_addr[4], + netdev->dev_addr[5]); + } else { + if (adapter->ops->macaddr_set) + adapter->ops->macaddr_set(port, + netdev-> + dev_addr); + } + } + INIT_WORK(&adapter->tx_timeout_task, + (void (*)(void *))netxen_tx_timeout_task, netdev); + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + if ((err = register_netdev(netdev))) { + printk(KERN_ERR "%s: register_netdev failed port #%d" + " aborting\n", netxen_nic_driver_name, i + 1); + err = -EIO; + free_netdev(netdev); + goto err_out_free_dev; + } + adapter->port_count++; + adapter->active_ports = 0; + adapter->port[i] = port; + } + + /* + * Initialize all the CRB registers here. + */ + /* Window = 1 */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + + netxen_phantom_init(adapter); + /* + * delay a while to ensure that the Pegs are up & running. + * Otherwise, we might see some flaky behaviour. + */ + udelay(100); + + switch (adapter->ahw.board_type) { + case NETXEN_NIC_GBE: + printk("%s: QUAD GbE board initialized\n", + netxen_nic_driver_name); + break; + + case NETXEN_NIC_XGBE: + printk("%s: XGbE board initialized\n", netxen_nic_driver_name); + break; + } + + adapter->driver_mismatch = 0; + + return 0; + + err_out_free_dev: + if (adapter->flags & NETXEN_NIC_MSI_ENABLED) + pci_disable_msi(pdev); + for (i = 0; i < adapter->port_count; i++) { + port = adapter->port[i]; + if ((port) && (port->netdev)) { + unregister_netdev(port->netdev); + free_netdev(port->netdev); + } + } + kfree(adapter->ops); + + err_out_free_rx_buffer: + for (i = 0; i < MAX_RCV_CTX; ++i) { + recv_ctx = &adapter->recv_ctx[i]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + if (rcv_desc->rx_buf_arr != NULL) { + vfree(rcv_desc->rx_buf_arr); + rcv_desc->rx_buf_arr = NULL; + } + } + } + + vfree(cmd_buf_arr); + + kfree(adapter->port); + + err_out_free_adapter: + pci_set_drvdata(pdev, NULL); + kfree(adapter); + + err_out_iounmap: + iounmap(mem_ptr); + err_out_free_res: + pci_release_regions(pdev); + err_out_disable_pdev: + pci_disable_device(pdev); + return err; +} + +static void __devexit netxen_nic_remove(struct pci_dev *pdev) +{ + struct netxen_adapter *adapter; + struct netxen_port *port; + struct netxen_rx_buffer *buffer; + struct netxen_recv_context *recv_ctx; + struct netxen_rcv_desc_ctx *rcv_desc; + int i; + int ctxid, ring; + + adapter = pci_get_drvdata(pdev); + if (adapter == NULL) + return; + + netxen_nic_stop_all_ports(adapter); + /* leave the hw in the same state as reboot */ + netxen_pinit_from_rom(adapter, 0); + udelay(500); + netxen_load_firmware(adapter); + + if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) + netxen_nic_disable_int(adapter); + + udelay(500); /* Delay for a while to drain the DMA engines */ + for (i = 0; i < adapter->port_count; i++) { + port = adapter->port[i]; + if ((port) && (port->netdev)) { + unregister_netdev(port->netdev); + free_netdev(port->netdev); + } + } + + if ((adapter->flags & NETXEN_NIC_MSI_ENABLED)) + pci_disable_msi(pdev); + pci_set_drvdata(pdev, NULL); + if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) + netxen_free_hw_resources(adapter); + + iounmap(adapter->ahw.pci_base); + + pci_release_regions(pdev); + pci_disable_device(pdev); + + for (ctxid = 0; ctxid < MAX_RCV_CTX; ++ctxid) { + recv_ctx = &adapter->recv_ctx[ctxid]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = &recv_ctx->rcv_desc[ring]; + for (i = 0; i < rcv_desc->max_rx_desc_count; ++i) { + buffer = &(rcv_desc->rx_buf_arr[i]); + if (buffer->state == NETXEN_BUFFER_FREE) + continue; + pci_unmap_single(pdev, buffer->dma, + rcv_desc->dma_size, + PCI_DMA_FROMDEVICE); + if (buffer->skb != NULL) + dev_kfree_skb_any(buffer->skb); + } + vfree(rcv_desc->rx_buf_arr); + } + } + + vfree(adapter->cmd_buf_arr); + kfree(adapter->ops); + kfree(adapter); +} + +/* + * Called when a network interface is made active + * @returns 0 on success, negative value on failure + */ +static int netxen_nic_open(struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + struct netxen_rcv_desc_ctx *rcv_desc; + int err = 0; + int ctx, ring; + + if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) { + err = netxen_init_firmware(adapter); + if (err != 0) { + printk(KERN_ERR "Failed to init firmware\n"); + return -EIO; + } + netxen_nic_flash_print(adapter); + + /* setup all the resources for the Phantom... */ + /* this include the descriptors for rcv, tx, and status */ + netxen_nic_clear_stats(adapter); + err = netxen_nic_hw_resources(adapter); + if (err) { + printk(KERN_ERR "Error in setting hw resources:%d\n", + err); + return err; + } + if (adapter->ops->init_port + && adapter->ops->init_port(adapter, port->portnum) != 0) { + printk(KERN_ERR "%s: Failed to initialize port %d\n", + netxen_nic_driver_name, port->portnum); + netxen_free_hw_resources(adapter); + return -EIO; + } + if (adapter->ops->init_niu) + adapter->ops->init_niu(adapter); + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { + rcv_desc = + &adapter->recv_ctx[ctx].rcv_desc[ring]; + netxen_post_rx_buffers(adapter, ctx, ring); + } + } + adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; + } + adapter->active_ports++; + if (adapter->active_ports == 1) { + err = request_irq(adapter->ahw.pdev->irq, &netxen_intr, + SA_SHIRQ | SA_SAMPLE_RANDOM, netdev->name, + adapter); + if (err) { + printk(KERN_ERR "request_irq failed with: %d\n", err); + adapter->active_ports--; + return err; + } + adapter->irq = adapter->ahw.pdev->irq; + if (!adapter->driver_mismatch) + mod_timer(&adapter->watchdog_timer, jiffies); + + netxen_nic_enable_int(adapter); + } + + /* Done here again so that even if phantom sw overwrote it, + * we set it */ + if (adapter->ops->macaddr_set) + adapter->ops->macaddr_set(port, netdev->dev_addr); + netxen_nic_set_link_parameters(port); + + netxen_nic_set_multi(netdev); + if (!adapter->driver_mismatch) + netif_start_queue(netdev); + + return 0; +} + +/* + * netxen_nic_close - Disables a network interface entry point + */ +static int netxen_nic_close(struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + int i, j; + struct netxen_cmd_buffer *cmd_buff; + struct netxen_skb_frag *buffrag; + + netif_carrier_off(netdev); + netif_stop_queue(netdev); + + /* disable phy_ints */ + if (adapter->ops->disable_phy_interrupts) + adapter->ops->disable_phy_interrupts(adapter, port->portnum); + + adapter->active_ports--; + + if (!adapter->active_ports) { + netxen_nic_disable_int(adapter); + if (adapter->irq) + free_irq(adapter->irq, adapter); + cmd_buff = adapter->cmd_buf_arr; + for (i = 0; i < adapter->max_tx_desc_count; i++) { + buffrag = cmd_buff->frag_array; + if (buffrag->dma) { + pci_unmap_single(port->pdev, buffrag->dma, + buffrag->length, + PCI_DMA_TODEVICE); + buffrag->dma = (u64) NULL; + } + for (j = 0; j < cmd_buff->frag_count; j++) { + buffrag++; + if (buffrag->dma) { + pci_unmap_page(port->pdev, + buffrag->dma, + buffrag->length, + PCI_DMA_TODEVICE); + buffrag->dma = (u64) NULL; + } + } + /* Free the skb we received in netxen_nic_xmit_frame */ + if (cmd_buff->skb) { + dev_kfree_skb_any(cmd_buff->skb); + cmd_buff->skb = NULL; + } + cmd_buff++; + } + del_timer_sync(&adapter->watchdog_timer); + } + + return 0; +} + +static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + struct netxen_hardware_context *hw = &adapter->ahw; + unsigned int first_seg_len = skb->len - skb->data_len; + struct netxen_skb_frag *buffrag; + unsigned int i; + + u32 producer = 0; + u32 saved_producer = 0; + struct cmd_desc_type0 *hwdesc; + int k; + struct netxen_cmd_buffer *pbuf = NULL; + unsigned int tries = 0; + static int dropped_packet = 0; + int frag_count; + u32 local_producer = 0; + u32 max_tx_desc_count = 0; + u32 last_cmd_consumer = 0; + int no_of_desc; + + port->stats.xmitcalled++; + frag_count = skb_shinfo(skb)->nr_frags + 1; + + if (unlikely(skb->len <= 0)) { + dev_kfree_skb_any(skb); + port->stats.badskblen++; + return NETDEV_TX_OK; + } + + if (frag_count > MAX_BUFFERS_PER_CMD) { + printk("%s: %s netxen_nic_xmit_frame: frag_count (%d)" + "too large, can handle only %d frags\n", + netxen_nic_driver_name, netdev->name, + frag_count, MAX_BUFFERS_PER_CMD); + port->stats.txdropped++; + if ((++dropped_packet & 0xff) == 0xff) + printk("%s: %s droppped packets = %d\n", + netxen_nic_driver_name, netdev->name, + dropped_packet); + + return NETDEV_TX_OK; + } + + /* + * Everything is set up. Now, we just need to transmit it out. + * Note that we have to copy the contents of buffer over to + * right place. Later on, this can be optimized out by de-coupling the + * producer index from the buffer index. + */ + retry_getting_window: + spin_lock_bh(&adapter->tx_lock); + if (adapter->total_threads == MAX_XMIT_PRODUCERS) { + spin_unlock_bh(&adapter->tx_lock); + /* + * Yield CPU + */ + if (!in_atomic()) + schedule(); + else { + for (i = 0; i < 20; i++) + cpu_relax(); /*This a nop instr on i386 */ + } + goto retry_getting_window; + } + local_producer = adapter->cmd_producer; + /* There 4 fragments per descriptor */ + no_of_desc = (frag_count + 3) >> 2; + if (skb_shinfo(skb)->gso_size > 0) { + no_of_desc++; + if (((skb->nh.iph)->ihl * sizeof(u32)) + + ((skb->h.th)->doff * sizeof(u32)) + + sizeof(struct ethhdr) > + (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { + no_of_desc++; + } + } + k = adapter->cmd_producer; + max_tx_desc_count = adapter->max_tx_desc_count; + last_cmd_consumer = adapter->last_cmd_consumer; + if ((k + no_of_desc) >= + ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count : + last_cmd_consumer)) { + spin_unlock_bh(&adapter->tx_lock); + if (tries == 0) { + local_bh_disable(); + netxen_process_cmd_ring((unsigned long)adapter); + local_bh_enable(); + ++tries; + goto retry_getting_window; + } else { + port->stats.nocmddescriptor++; + DPRINTK(ERR, "No command descriptors available," + " producer = %d, consumer = %d count=%llu," + " dropping packet\n", producer, + adapter->last_cmd_consumer, + port->stats.nocmddescriptor); + + spin_lock_bh(&adapter->tx_lock); + netif_stop_queue(netdev); + port->flags |= NETXEN_NETDEV_STATUS; + spin_unlock_bh(&adapter->tx_lock); + return NETDEV_TX_BUSY; + } + } + k = get_index_range(k, max_tx_desc_count, no_of_desc); + adapter->cmd_producer = k; + adapter->total_threads++; + adapter->num_threads++; + + spin_unlock_bh(&adapter->tx_lock); + /* Copy the descriptors into the hardware */ + producer = local_producer; + saved_producer = producer; + hwdesc = &hw->cmd_desc_head[producer]; + memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + /* Take skb->data itself */ + pbuf = &adapter->cmd_buf_arr[producer]; + if (skb_shinfo(skb)->gso_size > 0) { + pbuf->mss = skb_shinfo(skb)->gso_size; + hwdesc->mss = skb_shinfo(skb)->gso_size; + } else { + pbuf->mss = 0; + hwdesc->mss = 0; + } + pbuf->no_of_descriptors = no_of_desc; + pbuf->total_length = skb->len; + pbuf->skb = skb; + pbuf->cmd = TX_ETHER_PKT; + pbuf->frag_count = frag_count; + pbuf->port = port->portnum; + buffrag = &pbuf->frag_array[0]; + buffrag->dma = pci_map_single(port->pdev, skb->data, first_seg_len, + PCI_DMA_TODEVICE); + buffrag->length = first_seg_len; + CMD_DESC_TOTAL_LENGTH_WRT(hwdesc, skb->len); + hwdesc->num_of_buffers = frag_count; + hwdesc->opcode = TX_ETHER_PKT; + + CMD_DESC_PORT_WRT(hwdesc, port->portnum); + hwdesc->buffer1_length = cpu_to_le16(first_seg_len); + hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma); + + for (i = 1, k = 1; i < frag_count; i++, k++) { + struct skb_frag_struct *frag; + int len, temp_len; + unsigned long offset; + dma_addr_t temp_dma; + + /* move to next desc. if there is a need */ + if ((i & 0x3) == 0) { + k = 0; + producer = get_next_index(producer, + adapter->max_tx_desc_count); + hwdesc = &hw->cmd_desc_head[producer]; + memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); + } + frag = &skb_shinfo(skb)->frags[i - 1]; + len = frag->size; + offset = frag->page_offset; + + temp_len = len; + temp_dma = pci_map_page(port->pdev, frag->page, offset, + len, PCI_DMA_TODEVICE); + + buffrag++; + buffrag->dma = temp_dma; + buffrag->length = temp_len; + + DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k); + switch (k) { + case 0: + hwdesc->buffer1_length = cpu_to_le16(temp_len); + hwdesc->addr_buffer1 = cpu_to_le64(temp_dma); + break; + case 1: + hwdesc->buffer2_length = cpu_to_le16(temp_len); + hwdesc->addr_buffer2 = cpu_to_le64(temp_dma); + break; + case 2: + hwdesc->buffer3_length = cpu_to_le16(temp_len); + hwdesc->addr_buffer3 = cpu_to_le64(temp_dma); + break; + case 3: + hwdesc->buffer4_length = temp_len; + hwdesc->addr_buffer4 = cpu_to_le64(temp_dma); + break; + } + frag++; + } + producer = get_next_index(producer, adapter->max_tx_desc_count); + + /* might change opcode to TX_TCP_LSO */ + netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb); + + /* For LSO, we need to copy the MAC/IP/TCP headers into + * the descriptor ring + */ + if (hw->cmd_desc_head[saved_producer].opcode == TX_TCP_LSO) { + int hdr_len, first_hdr_len, more_hdr; + hdr_len = hw->cmd_desc_head[saved_producer].total_hdr_length; + if (hdr_len > (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { + first_hdr_len = + sizeof(struct cmd_desc_type0) - NET_IP_ALIGN; + more_hdr = 1; + } else { + first_hdr_len = hdr_len; + more_hdr = 0; + } + /* copy the MAC/IP/TCP headers to the cmd descriptor list */ + hwdesc = &hw->cmd_desc_head[producer]; + + /* copy the first 64 bytes */ + memcpy(((void *)hwdesc) + NET_IP_ALIGN, + (void *)(skb->data), first_hdr_len); + producer = get_next_index(producer, max_tx_desc_count); + + if (more_hdr) { + hwdesc = &hw->cmd_desc_head[producer]; + /* copy the next 64 bytes - should be enough except + * for pathological case + */ + memcpy((void *)hwdesc, (void *)(skb->data) + + first_hdr_len, hdr_len - first_hdr_len); + producer = get_next_index(producer, max_tx_desc_count); + } + } + spin_lock_bh(&adapter->tx_lock); + port->stats.txbytes += + CMD_DESC_TOTAL_LENGTH(&hw->cmd_desc_head[saved_producer]); + /* Code to update the adapter considering how many producer threads + are currently working */ + if ((--adapter->num_threads) == 0) { + /* This is the last thread */ + u32 crb_producer = adapter->cmd_producer; + writel(crb_producer, + NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); + wmb(); + adapter->total_threads = 0; + } else { + u32 crb_producer = 0; + crb_producer = + readl(NETXEN_CRB_NORMALIZE + (adapter, CRB_CMD_PRODUCER_OFFSET)); + if (crb_producer == local_producer) { + crb_producer = get_index_range(crb_producer, + max_tx_desc_count, + no_of_desc); + writel(crb_producer, + NETXEN_CRB_NORMALIZE(adapter, + CRB_CMD_PRODUCER_OFFSET)); + wmb(); + } + } + + port->stats.xmitfinished++; + spin_unlock_bh(&adapter->tx_lock); + + netdev->trans_start = jiffies; + + DPRINTK(INFO, "wrote CMD producer %x to phantom\n", producer); + + DPRINTK(INFO, "Done. Send\n"); + return NETDEV_TX_OK; +} + +static void netxen_watchdog(unsigned long v) +{ + struct netxen_adapter *adapter = (struct netxen_adapter *)v; + schedule_work(&adapter->watchdog_task); +} + +static void netxen_tx_timeout(struct net_device *netdev) +{ + struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + + schedule_work(&adapter->tx_timeout_task); +} + +static void netxen_tx_timeout_task(struct net_device *netdev) +{ + struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); + unsigned long flags; + + printk(KERN_ERR "%s %s: transmit timeout, resetting.\n", + netxen_nic_driver_name, netdev->name); + + spin_lock_irqsave(&port->adapter->lock, flags); + netxen_nic_close(netdev); + netxen_nic_open(netdev); + spin_unlock_irqrestore(&port->adapter->lock, flags); + netdev->trans_start = jiffies; + netif_wake_queue(netdev); +} + +static int +netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) +{ + u32 ret = 0; + + DPRINTK(INFO, "Entered handle ISR\n"); + + adapter->stats.ints++; + + if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { + int count = 0; + u32 mask; + netxen_nic_disable_int(adapter); + /* Window = 0 or 1 */ + do { + writel(0xffffffff, (void __iomem *) + (adapter->ahw.pci_base + ISR_INT_TARGET_STATUS)); + mask = readl((void __iomem *) + (adapter->ahw.pci_base + ISR_INT_VECTOR)); + } while (((mask & 0x80) != 0) && (++count < 32)); + if ((mask & 0x80) != 0) + printk("Could not disable interrupt completely\n"); + + } + adapter->stats.hostints++; + + if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { + if (netif_rx_schedule_prep(netdev)) { + /* + * Interrupts are already disabled. + */ + __netif_rx_schedule(netdev); + } else { + static unsigned int intcount = 0; + if ((++intcount & 0xfff) == 0xfff) + printk(KERN_ERR + "%s: %s interrupt %d while in poll\n", + netxen_nic_driver_name, netdev->name, + intcount); + } + ret = 1; + } + + if (ret == 0) { + netxen_nic_enable_int(adapter); + } + + return ret; +} + +/* + * netxen_intr - Interrupt Handler + * @irq: interrupt number + * data points to adapter stucture (which may be handling more than 1 port + */ +irqreturn_t netxen_intr(int irq, void *data, struct pt_regs * regs) +{ + struct netxen_adapter *adapter; + struct netxen_port *port; + struct net_device *netdev; + int i; + + if (unlikely(!irq)) { + return IRQ_NONE; /* Not our interrupt */ + } + + adapter = (struct netxen_adapter *)data; + for (i = 0; i < adapter->ahw.max_ports; i++) { + port = adapter->port[i]; + netdev = port->netdev; + + /* process our status queue (for all 4 ports) */ + netxen_handle_int(adapter, netdev); + } + + return IRQ_HANDLED; +} + +static int netxen_nic_poll(struct net_device *netdev, int *budget) +{ + struct netxen_port *port = (struct netxen_port *)netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + int work_to_do = min(*budget, netdev->quota); + int done = 1; + int ctx; + int this_work_done; + + DPRINTK(INFO, "polling for %d descriptors\n", *budget); + port->stats.polled++; + + adapter->work_done = 0; + for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { + /* + * Fairness issue. This will give undue weight to the + * receive context 0. + */ + + /* + * To avoid starvation, we give each of our receivers, + * a fraction of the quota. Sometimes, it might happen that we + * have enough quota to process every packet, but since all the + * packets are on one context, it gets only half of the quota, + * and ends up not processing it. + */ + this_work_done = netxen_process_rcv_ring(adapter, ctx, + work_to_do / + MAX_RCV_CTX); + adapter->work_done += this_work_done; + } + + netdev->quota -= adapter->work_done; + *budget -= adapter->work_done; + + if (adapter->work_done >= work_to_do + && netxen_nic_rx_has_work(adapter) != 0) + done = 0; + + netxen_process_cmd_ring((unsigned long)adapter); + + DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", + adapter->work_done, work_to_do); + if (done) { + netif_rx_complete(netdev); + netxen_nic_enable_int(adapter); + } + + return (done ? 0 : 1); +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +static void netxen_nic_poll_controller(struct net_device *netdev) +{ + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + disable_irq(adapter->irq); + netxen_intr(adapter->irq, adapter, NULL); + enable_irq(adapter->irq); +} +#endif +/* + * netxen_nic_ioctl () We provide the tcl/phanmon support through these + * ioctls. + */ +static int +netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + int err = 0; + struct netxen_port *port = netdev_priv(netdev); + struct netxen_adapter *adapter = port->adapter; + + DPRINTK(INFO, "doing ioctl for %s\n", netdev->name); + switch (cmd) { + case NETXEN_NIC_CMD: + err = netxen_nic_do_ioctl(adapter, (void *)ifr->ifr_data, port); + break; + + case NETXEN_NIC_NAME: + DPRINTK(INFO, "ioctl cmd for NetXen\n"); + if (ifr->ifr_data) { + put_user(port->portnum, (u16 __user *) ifr->ifr_data); + } + break; + + default: + DPRINTK(INFO, "ioctl cmd %x not supported\n", cmd); + err = -EOPNOTSUPP; + break; + } + + return err; +} + +static struct pci_driver netxen_driver = { + .name = netxen_nic_driver_name, + .id_table = netxen_pci_tbl, + .probe = netxen_nic_probe, + .remove = __devexit_p(netxen_nic_remove) +}; + +/* Driver Registration on NetXen card */ + +static int __init netxen_init_module(void) +{ + printk(KERN_INFO "%s \n", netxen_nic_driver_string); + + return pci_module_init(&netxen_driver); +} + +module_init(netxen_init_module); + +static void __exit netxen_exit_module(void) +{ + /* + * Wait for some time to allow the dma to drain, if any. + */ + mdelay(5); + pci_unregister_driver(&netxen_driver); +} + +module_exit(netxen_exit_module); diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c new file mode 100644 index 000000000000..6e421c876fe5 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -0,0 +1,800 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + * + * + * Provides access to the Network Interface Unit h/w block. + * + */ + +#include "netxen_nic.h" +#include + +/* + * netxen_niu_gbe_phy_read - read a register from the GbE PHY via + * mii management interface. + * + * Note: The MII management interface goes through port 0. + * Individual phys are addressed as follows: + * @param phy [15:8] phy id + * @param reg [7:0] register number + * + * @returns 0 on success + * -1 on error + * + */ +int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, + long reg, __le32 * readval) +{ + long timeout = 0; + long result = 0; + long restore = 0; + __le32 address; + __le32 command; + __le32 status; + __le32 mii_cfg; + __le32 mac_cfg0; + + /* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */ + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), + &mac_cfg0, 4)) + return -EIO; + if (netxen_gb_get_soft_reset(mac_cfg0)) { + __le32 temp; + temp = 0; + netxen_gb_tx_reset_pb(temp); + netxen_gb_rx_reset_pb(temp); + netxen_gb_tx_reset_mac(temp); + netxen_gb_rx_reset_mac(temp); + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(0), + &temp, 4)) + return -EIO; + restore = 1; + } + + /* reset MII management interface */ + mii_cfg = 0; + netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7); + netxen_gb_mii_mgmt_reset(mii_cfg); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0), + &mii_cfg, 4)) + return -EIO; + netxen_gb_mii_mgmt_unset(mii_cfg); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0), + &mii_cfg, 4)) + return -EIO; + + address = 0; + netxen_gb_mii_mgmt_reg_addr(address, reg); + netxen_gb_mii_mgmt_phy_addr(address, phy); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), + &address, 4)) + return -EIO; + command = 0; /* turn off any prior activity */ + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), + &command, 4)) + return -EIO; + /* send read command */ + netxen_gb_mii_mgmt_set_read_cycle(command); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), + &command, 4)) + return -EIO; + + status = 0; + do { + if (netxen_nic_hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(0), + &status, 4)) + return -EIO; + timeout++; + } while ((netxen_get_gb_mii_mgmt_busy(status) + || netxen_get_gb_mii_mgmt_notvalid(status)) + && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); + + if (timeout < NETXEN_NIU_PHY_WAITMAX) { + if (netxen_nic_hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_STATUS(0), + readval, 4)) + return -EIO; + result = 0; + } else + result = -1; + + if (restore) + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(0), + &mac_cfg0, 4)) + return -EIO; + + return result; +} + +/* + * netxen_niu_gbe_phy_write - write a register to the GbE PHY via + * mii management interface. + * + * Note: The MII management interface goes through port 0. + * Individual phys are addressed as follows: + * @param phy [15:8] phy id + * @param reg [7:0] register number + * + * @returns 0 on success + * -1 on error + * + */ +int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, + long phy, long reg, __le32 val) +{ + long timeout = 0; + long result = 0; + long restore = 0; + __le32 address; + __le32 command; + __le32 status; + __le32 mac_cfg0; + + /* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */ + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), + &mac_cfg0, 4)) + return -EIO; + if (netxen_gb_get_soft_reset(mac_cfg0)) { + __le32 temp; + temp = 0; + netxen_gb_tx_reset_pb(temp); + netxen_gb_rx_reset_pb(temp); + netxen_gb_tx_reset_mac(temp); + netxen_gb_rx_reset_mac(temp); + + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(0), + &temp, 4)) + return -EIO; + restore = 1; + } + + command = 0; /* turn off any prior activity */ + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_COMMAND(0), + &command, 4)) + return -EIO; + + address = 0; + netxen_gb_mii_mgmt_reg_addr(address, reg); + netxen_gb_mii_mgmt_phy_addr(address, phy); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_ADDR(0), + &address, 4)) + return -EIO; + + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CTRL(0), + &val, 4)) + return -EIO; + + status = 0; + do { + if (netxen_nic_hw_read_wx(adapter, + NETXEN_NIU_GB_MII_MGMT_INDICATE(0), + &status, 4)) + return -EIO; + timeout++; + } while ((netxen_get_gb_mii_mgmt_busy(status)) + && (timeout++ < NETXEN_NIU_PHY_WAITMAX)); + + if (timeout < NETXEN_NIU_PHY_WAITMAX) + result = 0; + else + result = -EIO; + + /* restore the state of port 0 MAC in case we tampered with it */ + if (restore) + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(0), + &mac_cfg0, 4)) + return -EIO; + + return result; +} + +int netxen_niu_xgbe_enable_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x3f); + return 0; +} + +int netxen_niu_gbe_enable_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + int result = 0; + __le32 enable = 0; + netxen_set_phy_int_link_status_changed(enable); + netxen_set_phy_int_autoneg_completed(enable); + netxen_set_phy_int_speed_changed(enable); + + if (0 != + netxen_niu_gbe_phy_write(adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, + enable)) + result = -EIO; + + return result; +} + +int netxen_niu_xgbe_disable_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_INT_MASK, 0x7f); + return 0; +} + +int netxen_niu_gbe_disable_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + int result = 0; + if (0 != + netxen_niu_gbe_phy_write(adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_ENABLE, 0)) + result = -EIO; + + return result; +} + +int netxen_niu_xgbe_clear_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_ACTIVE_INT, -1); + return 0; +} + +int netxen_niu_gbe_clear_phy_interrupts(struct netxen_adapter *adapter, + int port) +{ + int result = 0; + if (0 != + netxen_niu_gbe_phy_write(adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, + -EIO)) + result = -EIO; + + return result; +} + +/* + * netxen_niu_gbe_set_mii_mode- Set 10/100 Mbit Mode for GbE MAC + * + */ +void netxen_niu_gbe_set_mii_mode(struct netxen_adapter *adapter, + int port, long enable) +{ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x80000000); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x0000f0025); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), + 0xf1ff); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB0_GMII_MODE + (port << 3), 0); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB0_MII_MODE + (port << 3), 1); + netxen_crb_writelit_adapter(adapter, + (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + + if (enable) { + /* + * Do NOT enable flow control until a suitable solution for + * shutting down pause frames is found. + */ + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x5); + } + + if (netxen_niu_gbe_enable_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); +} + +/* + * netxen_niu_gbe_set_gmii_mode- Set GbE Mode for GbE MAC + */ +void netxen_niu_gbe_set_gmii_mode(struct netxen_adapter *adapter, + int port, long enable) +{ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_MODE, 0x2); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x80000000); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x0000f0025); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_1(port), + 0xf2ff); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB0_MII_MODE + (port << 3), 0); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB0_GMII_MODE + (port << 3), 1); + netxen_crb_writelit_adapter(adapter, + (NETXEN_NIU_GB0_HALF_DUPLEX + port * 4), 0); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MII_MGMT_CONFIG(port), 0x7); + + if (enable) { + /* + * Do NOT enable flow control until a suitable solution for + * shutting down pause frames is found. + */ + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0(port), + 0x5); + } + + if (netxen_niu_gbe_enable_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX "ERROR enabling PHY interrupts\n"); + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); +} + +int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) +{ + int result = 0; + __le32 status; + if (adapter->ops->disable_phy_interrupts) + adapter->ops->disable_phy_interrupts(adapter, port); + mdelay(2); + + if (0 == + netxen_niu_gbe_phy_read(adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + (__le32 *) & status)) { + if (netxen_get_phy_link(status)) { + if (netxen_get_phy_speed(status) == 2) { + netxen_niu_gbe_set_gmii_mode(adapter, port, 1); + } else if ((netxen_get_phy_speed(status) == 1) + || (netxen_get_phy_speed(status) == 0)) { + netxen_niu_gbe_set_mii_mode(adapter, port, 1); + } else { + result = -1; + } + + } else { + /* We don't have link. Cable must be unconnected. */ + /* Enable phy interrupts so we take action when plugged in */ + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0 + (port), 0x80000000); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_GB_MAC_CONFIG_0 + (port), 0x0000f0025); + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX + "ERROR clearing PHY interrupts\n"); + if (netxen_niu_gbe_enable_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX + "ERROR enabling PHY interrupts\n"); + if (netxen_niu_gbe_clear_phy_interrupts(adapter, port)) + printk(KERN_ERR PFX + "ERROR clearing PHY interrupts\n"); + result = -1; + } + } else { + result = -EIO; + } + return result; +} + +/* + * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts + * @param enable 0 means don't enable the port + * 1 means enable (or re-enable) the port + */ +int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter, + int port, long enable) +{ + int result = 0; + __le32 int_src; + + printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d" + " (device enable = %d)\n", (int)port, (int)enable); + + /* The read of the PHY INT status will clear the pending interrupt status */ + if (netxen_niu_gbe_phy_read(adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, + &int_src) != 0) + result = -EINVAL; + else { + printk(KERN_INFO PFX "PHY Interrupt source = 0x%x \n", int_src); + if (netxen_get_phy_int_jabber(int_src)) + printk(KERN_INFO PFX "jabber Interrupt "); + if (netxen_get_phy_int_polarity_changed(int_src)) + printk(KERN_INFO PFX "polarity changed "); + if (netxen_get_phy_int_energy_detect(int_src)) + printk(KERN_INFO PFX "energy detect \n"); + if (netxen_get_phy_int_downshift(int_src)) + printk(KERN_INFO PFX "downshift \n"); + if (netxen_get_phy_int_mdi_xover_changed(int_src)) + printk(KERN_INFO PFX "mdi_xover_changed "); + if (netxen_get_phy_int_fifo_over_underflow(int_src)) + printk(KERN_INFO PFX "fifo_over_underflow "); + if (netxen_get_phy_int_false_carrier(int_src)) + printk(KERN_INFO PFX "false_carrier "); + if (netxen_get_phy_int_symbol_error(int_src)) + printk(KERN_INFO PFX "symbol_error "); + if (netxen_get_phy_int_autoneg_completed(int_src)) + printk(KERN_INFO PFX "autoneg_completed "); + if (netxen_get_phy_int_page_received(int_src)) + printk(KERN_INFO PFX "page_received "); + if (netxen_get_phy_int_duplex_changed(int_src)) + printk(KERN_INFO PFX "duplex_changed "); + if (netxen_get_phy_int_autoneg_error(int_src)) + printk(KERN_INFO PFX "autoneg_error "); + if ((netxen_get_phy_int_speed_changed(int_src)) + || (netxen_get_phy_int_link_status_changed(int_src))) { + __le32 status; + + printk(KERN_INFO PFX + "speed_changed or link status changed"); + if (netxen_niu_gbe_phy_read + (adapter, port, + NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, + &status) == 0) { + if (netxen_get_phy_speed(status) == 2) { + printk + (KERN_INFO PFX "Link speed changed" + " to 1000 Mbps\n"); + netxen_niu_gbe_set_gmii_mode(adapter, + port, + enable); + } else if (netxen_get_phy_speed(status) == 1) { + printk + (KERN_INFO PFX "Link speed changed" + " to 100 Mbps\n"); + netxen_niu_gbe_set_mii_mode(adapter, + port, + enable); + } else if (netxen_get_phy_speed(status) == 0) { + printk + (KERN_INFO PFX "Link speed changed" + " to 10 Mbps\n"); + netxen_niu_gbe_set_mii_mode(adapter, + port, + enable); + } else { + printk(KERN_ERR PFX "ERROR reading" + "PHY status. Illegal speed.\n"); + result = -1; + } + } else { + printk(KERN_ERR PFX + "ERROR reading PHY status.\n"); + result = -1; + } + + } + printk(KERN_INFO "\n"); + } + return result; +} + +/* + * Return the current station MAC address. + * Note that the passed-in value must already be in network byte order. + */ +int netxen_niu_macaddr_get(struct netxen_adapter *adapter, + int phy, netxen_ethernet_macaddr_t * addr) +{ + u64 result = 0; + __le32 stationhigh; + __le32 stationlow; + + if (addr == NULL) + return -EINVAL; + if ((phy < 0) || (phy > 3)) + return -EINVAL; + + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), + &stationhigh, 4)) + return -EIO; + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), + &stationlow, 4)) + return -EIO; + + result = (u64) netxen_gb_get_stationaddress_low(stationlow); + result |= (u64) stationhigh << 16; + memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t)); + + return 0; +} + +/* + * Set the station MAC address. + * Note that the passed-in value must already be in network byte order. + */ +int netxen_niu_macaddr_set(struct netxen_port *port, + netxen_ethernet_macaddr_t addr) +{ + __le32 temp = 0; + struct netxen_adapter *adapter = port->adapter; + int phy = port->portnum; + + memcpy(&temp, addr, 2); + temp <<= 16; + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), + &temp, 4)) + return -EIO; + + temp = 0; + + memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), + &temp, 4)) + return -2; + + return 0; +} + +/* Enable a GbE interface */ +int netxen_niu_enable_gbe_port(struct netxen_adapter *adapter, + int port, netxen_niu_gbe_ifmode_t mode) +{ + __le32 mac_cfg0; + __le32 mac_cfg1; + __le32 mii_cfg; + + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + return -EINVAL; + + mac_cfg0 = 0; + netxen_gb_soft_reset(mac_cfg0); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + &mac_cfg0, 4)) + return -EIO; + mac_cfg0 = 0; + netxen_gb_enable_tx(mac_cfg0); + netxen_gb_enable_rx(mac_cfg0); + netxen_gb_unset_rx_flowctl(mac_cfg0); + netxen_gb_tx_reset_pb(mac_cfg0); + netxen_gb_rx_reset_pb(mac_cfg0); + netxen_gb_tx_reset_mac(mac_cfg0); + netxen_gb_rx_reset_mac(mac_cfg0); + + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + &mac_cfg0, 4)) + return -EIO; + mac_cfg1 = 0; + netxen_gb_set_preamblelen(mac_cfg1, 0xf); + netxen_gb_set_duplex(mac_cfg1); + netxen_gb_set_crc_enable(mac_cfg1); + netxen_gb_set_padshort(mac_cfg1); + netxen_gb_set_checklength(mac_cfg1); + netxen_gb_set_hugeframes(mac_cfg1); + + if (mode == NETXEN_NIU_10_100_MB) { + netxen_gb_set_intfmode(mac_cfg1, 1); + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_1(port), + &mac_cfg1, 4)) + return -EIO; + + /* set mii mode */ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE + + (port << 3), 0); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE + + (port << 3), 1); + + } else if (mode == NETXEN_NIU_1000_MB) { + netxen_gb_set_intfmode(mac_cfg1, 2); + if (netxen_nic_hw_write_wx(adapter, + NETXEN_NIU_GB_MAC_CONFIG_1(port), + &mac_cfg1, 4)) + return -EIO; + /* set gmii mode */ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_MII_MODE + + (port << 3), 0); + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB0_GMII_MODE + + (port << 3), 1); + } + mii_cfg = 0; + netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(port), + &mii_cfg, 4)) + return -EIO; + mac_cfg0 = 0; + netxen_gb_enable_tx(mac_cfg0); + netxen_gb_enable_rx(mac_cfg0); + netxen_gb_unset_rx_flowctl(mac_cfg0); + netxen_gb_unset_tx_flowctl(mac_cfg0); + + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + &mac_cfg0, 4)) + return -EIO; + return 0; +} + +/* Disable a GbE interface */ +int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port) +{ + __le32 mac_cfg0; + + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + return -EINVAL; + + mac_cfg0 = 0; + netxen_gb_soft_reset(mac_cfg0); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port), + &mac_cfg0, 4)) + return -EIO; + return 0; +} + +/* Disable an XG interface */ +int netxen_niu_disable_xg_port(struct netxen_adapter *adapter, int port) +{ + __le32 mac_cfg; + + if (port != 0) + return -EINVAL; + + mac_cfg = 0; + netxen_xg_soft_reset(mac_cfg); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_CONFIG_0, + &mac_cfg, 4)) + return -EIO; + return 0; +} + +/* Set promiscuous mode for a GbE interface */ +int netxen_niu_set_promiscuous_mode(struct netxen_adapter *adapter, int port, + netxen_niu_prom_mode_t mode) +{ + __le32 reg; + + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + return -EINVAL; + + /* save previous contents */ + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, + ®, 4)) + return -EIO; + if (mode == NETXEN_NIU_PROMISC_MODE) { + switch (port) { + case 0: + netxen_clear_gb_drop_gb0(reg); + break; + case 1: + netxen_clear_gb_drop_gb1(reg); + break; + case 2: + netxen_clear_gb_drop_gb2(reg); + break; + case 3: + netxen_clear_gb_drop_gb3(reg); + break; + default: + return -EIO; + } + } else { + switch (port) { + case 0: + netxen_set_gb_drop_gb0(reg); + break; + case 1: + netxen_set_gb_drop_gb1(reg); + break; + case 2: + netxen_set_gb_drop_gb2(reg); + break; + case 3: + netxen_set_gb_drop_gb3(reg); + break; + default: + return -EIO; + } + } + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_DROP_WRONGADDR, + ®, 4)) + return -EIO; + return 0; +} + +/* + * Set the MAC address for an XG port + * Note that the passed-in value must already be in network byte order. + */ +int netxen_niu_xg_macaddr_set(struct netxen_port *port, + netxen_ethernet_macaddr_t addr) +{ + __le32 temp = 0; + struct netxen_adapter *adapter = port->adapter; + + memcpy(&temp, addr, 2); + temp = cpu_to_le32(temp); + temp <<= 16; + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, + &temp, 4)) + return -EIO; + + temp = 0; + + memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); + temp = cpu_to_le32(temp); + if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, + &temp, 4)) + return -EIO; + + return 0; +} + +/* + * Return the current station MAC address. + * Note that the passed-in value must already be in network byte order. + */ +int netxen_niu_xg_macaddr_get(struct netxen_adapter *adapter, int phy, + netxen_ethernet_macaddr_t * addr) +{ + __le32 stationhigh; + __le32 stationlow; + u64 result; + + if (addr == NULL) + return -EINVAL; + if (phy != 0) + return -EINVAL; + + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_HI, + &stationhigh, 4)) + return -EIO; + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_STATION_ADDR_0_1, + &stationlow, 4)) + return -EIO; + + result = ((u64) stationlow) >> 16; + result |= (u64) stationhigh << 16; + memcpy(*addr, &result, sizeof(netxen_ethernet_macaddr_t)); + + return 0; +} + +int netxen_niu_xg_set_promiscuous_mode(struct netxen_adapter *adapter, + int port, netxen_niu_prom_mode_t mode) +{ + __le32 reg; + + if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + return -EINVAL; + + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_XGE_CONFIG_1, ®, 4)) + return -EIO; + if (mode == NETXEN_NIU_PROMISC_MODE) + reg = (reg | 0x2000UL); + else + reg = (reg & ~0x2000UL); + + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_XGE_CONFIG_1, reg); + + return 0; +} diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h new file mode 100644 index 000000000000..863645ed1cd3 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2003 - 2006 NetXen, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * 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. + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE. + * + * Contact Information: + * info@netxen.com + * NetXen, + * 3965 Freedom Circle, Fourth floor, + * Santa Clara, CA 95054 + */ + +#ifndef __NIC_PHAN_REG_H_ +#define __NIC_PHAN_REG_H_ + +/* + * CRB Registers or queue message done only at initialization time. + */ + +/* + * The following 2 are the base adresses for the CRB registers and their + * offsets will be added to get addresses for the index addresses. + */ +#define NIC_CRB_BASE_PORT1 NETXEN_CAM_RAM(0x200) +#define NIC_CRB_BASE_PORT2 NETXEN_CAM_RAM(0x250) + +#define NETXEN_NIC_REG(X) (NIC_CRB_BASE_PORT1+(X)) + +/* + * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address + * which can be read by the Phantom host to get producer/consumer indexes from + * Phantom/Casper. If it is not HOST_SHARED_MEMORY, then the following + * registers will be used for the addresses of the ring's shared memory + * on the Phantom. + */ + +#define CRB_PHAN_CNTRL_LO_OFFSET NETXEN_NIC_REG(0x00) +#define CRB_PHAN_CNTRL_HI_OFFSET NETXEN_NIC_REG(0x04) + +/* point to the indexes */ +#define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) +#define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) + +/* address of command descriptors in the host memory */ +#define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x30) +#define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x34) + +/* The following 4 CRB registers are for doing performance coal */ +#define CRB_CMD_INTR_LOOP NETXEN_NIC_REG(0x38) +#define CRB_CMD_DMA_LOOP NETXEN_NIC_REG(0x3c) +#define CRB_RCV_INTR_LOOP NETXEN_NIC_REG(0x40) +#define CRB_RCV_DMA_LOOP NETXEN_NIC_REG(0x44) + +/* Needed by the host to find out the state of Phantom's initialization */ +#define CRB_ENABLE_TX_INTR NETXEN_NIC_REG(0x4c) +#define CRB_CMDPEG_STATE NETXEN_NIC_REG(0x50) +#define CRB_CMDPEG_CMDRING NETXEN_NIC_REG(0x54) + +/* Interrupt coalescing parameters */ +#define CRB_GLOBAL_INT_COAL NETXEN_NIC_REG(0x80) +#define CRB_INT_COAL_MODE NETXEN_NIC_REG(0x84) +#define CRB_MAX_RCV_BUFS NETXEN_NIC_REG(0x88) +#define CRB_TX_INT_THRESHOLD NETXEN_NIC_REG(0x8c) +#define CRB_RX_PKT_TIMER NETXEN_NIC_REG(0x90) +#define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x94) +#define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x98) +#define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x9c) + +/* Register for communicating XG link status */ +#define CRB_XG_STATE NETXEN_NIC_REG(0xa0) + +/* Debug registers for controlling NIC pkt gen agent */ +#define CRB_AGENT_GO NETXEN_NIC_REG(0xb0) +#define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0xb4) +#define CRB_AGENT_TX_TYPE NETXEN_NIC_REG(0xb8) +#define CRB_AGENT_TX_ADDR NETXEN_NIC_REG(0xbc) +#define CRB_AGENT_TX_MSS NETXEN_NIC_REG(0xc0) + +/* Debug registers for observing NIC performance */ +#define CRB_TX_STATE NETXEN_NIC_REG(0xd0) +#define CRB_TX_COUNT NETXEN_NIC_REG(0xd4) +#define CRB_RX_STATE NETXEN_NIC_REG(0xd8) + +/* CRB registers per Rcv Descriptor ring */ +struct netxen_rcv_desc_crb { + u32 crb_rcv_producer_offset __attribute__ ((aligned(512))); + u32 crb_rcv_consumer_offset; + u32 crb_globalrcv_ring; +}; + +/* + * CRB registers used by the receive peg logic. One instance of these + * needs to be instantiated per instance of the receive peg. + */ + +struct netxen_recv_crb { + struct netxen_rcv_desc_crb rcv_desc_crb[NUM_RCV_DESC_RINGS]; + u32 crb_rcvstatus_ring; + u32 crb_rcv_status_producer; + u32 crb_rcv_status_consumer; + u32 crb_rcvpeg_state; +}; + +#if defined(DEFINE_GLOBAL_RECV_CRB) +struct netxen_recv_crb recv_crb_registers[] = { + /* + * Instance 0. + */ + { + /* rcv_desc_crb: */ + { + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x18), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x1c), + /* crb_gloablrcv_ring: */ + NETXEN_NIC_REG(0x20), + }, + /* Jumbo frames */ + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x100), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x104), + /* crb_gloablrcv_ring: */ + NETXEN_NIC_REG(0x108), + } + }, + /* crb_rcvstatus_ring: */ + NETXEN_NIC_REG(0x24), + /* crb_rcv_status_producer: */ + NETXEN_NIC_REG(0x28), + /* crb_rcv_status_consumer: */ + NETXEN_NIC_REG(0x2c), + /* crb_rcvpeg_state: */ + NETXEN_NIC_REG(0x48), + + }, + /* + * Instance 1, + */ + { + /* rcv_desc_crb: */ + { + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x80), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x84), + /* crb_globalrcv_ring: */ + NETXEN_NIC_REG(0x88), + }, + /* Jumbo frames */ + { + /* crb_rcv_producer_offset: */ + NETXEN_NIC_REG(0x10C), + /* crb_rcv_consumer_offset: */ + NETXEN_NIC_REG(0x110), + /* crb_globalrcv_ring: */ + NETXEN_NIC_REG(0x114), + } + }, + /* crb_rcvstatus_ring: */ + NETXEN_NIC_REG(0x8c), + /* crb_rcv_status_producer: */ + NETXEN_NIC_REG(0x90), + /* crb_rcv_status_consumer: */ + NETXEN_NIC_REG(0x94), + /* crb_rcvpeg_state: */ + NETXEN_NIC_REG(0x98), + }, +}; +#else +extern struct netxen_recv_crb recv_crb_registers[]; +#endif /* DEFINE_GLOBAL_RECEIVE_CRB */ + +#endif /* __NIC_PHAN_REG_H_ */ -- cgit v1.2.3 From a362bf57aa12835e4fa6af6960e5135b5626bc5b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 18 Oct 2006 00:17:02 +0100 Subject: [PATCH] zd1211rw: Add ID for ZyXEL G-220 Tested by Newsome on IRC zd1211 chip 0586:3401 v4330 high 00-13-49 AL2230_RF pa0 g--- Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 435e16e137b3..7917153a92e9 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -50,6 +50,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3 From 90fb51358a264f2f7e0cabdca6fc229bbc40cd91 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:30 -0800 Subject: e1000: whitespace changes, comments, typos Small whitespace changes, comment changes, typo fixes. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_ethtool.c | 27 +++++----- drivers/net/e1000/e1000_hw.c | 6 ++- drivers/net/e1000/e1000_hw.h | 5 +- drivers/net/e1000/e1000_main.c | 101 +++++++++++++++++++------------------- drivers/net/e1000/e1000_osdep.h | 1 - 5 files changed, 72 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index c564adbd669b..82d2c78e1696 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -133,9 +133,7 @@ e1000_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) if (hw->autoneg == 1) { ecmd->advertising |= ADVERTISED_Autoneg; - /* the e1000 autoneg seems to match ethtool nicely */ - ecmd->advertising |= hw->autoneg_advertised; } @@ -285,7 +283,7 @@ e1000_set_pauseparam(struct net_device *netdev, e1000_reset(adapter); } else retval = ((hw->media_type == e1000_media_type_fiber) ? - e1000_setup_link(hw) : e1000_force_mac_fc(hw)); + e1000_setup_link(hw) : e1000_force_mac_fc(hw)); clear_bit(__E1000_RESETTING, &adapter->flags); return retval; @@ -774,7 +772,7 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) /* The status register is Read Only, so a write should fail. * Some bits that get toggled are ignored. */ - switch (adapter->hw.mac_type) { + switch (adapter->hw.mac_type) { /* there are several bits on newer hardware that are r/w */ case e1000_82571: case e1000_82572: @@ -802,12 +800,14 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) } /* restore previous status */ E1000_WRITE_REG(&adapter->hw, STATUS, before); + if (adapter->hw.mac_type != e1000_ich8lan) { REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF); REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF); } + REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF); REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF); @@ -820,8 +820,9 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF); REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000); + before = (adapter->hw.mac_type == e1000_ich8lan ? - 0x06C3B33E : 0x06DFB3FE); + 0x06C3B33E : 0x06DFB3FE); REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB); REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); @@ -834,10 +835,10 @@ e1000_reg_test(struct e1000_adapter *adapter, uint64_t *data) REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); value = (adapter->hw.mac_type == e1000_ich8lan ? - E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES); + E1000_RAR_ENTRIES_ICH8LAN : E1000_RAR_ENTRIES); for (i = 0; i < value; i++) { REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF, - 0xFFFFFFFF); + 0xFFFFFFFF); } } else { @@ -883,8 +884,7 @@ e1000_eeprom_test(struct e1000_adapter *adapter, uint64_t *data) } static irqreturn_t -e1000_test_intr(int irq, - void *data) +e1000_test_intr(int irq, void *data) { struct net_device *netdev = (struct net_device *) data; struct e1000_adapter *adapter = netdev_priv(netdev); @@ -905,11 +905,11 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) /* NOTE: we don't test MSI interrupts here, yet */ /* Hook up test interrupt handler just for this test */ - if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, - netdev->name, netdev)) + if (!request_irq(irq, &e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, + netdev)) shared_int = FALSE; else if (request_irq(irq, &e1000_test_intr, IRQF_SHARED, - netdev->name, netdev)) { + netdev->name, netdev)) { *data = 1; return -1; } @@ -925,6 +925,7 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data) if (adapter->hw.mac_type == e1000_ich8lan && i == 8) continue; + /* Interrupt to test */ mask = 1 << i; @@ -1674,7 +1675,7 @@ e1000_diag_test(struct net_device *netdev, if (e1000_link_test(adapter, &data[4])) eth_test->flags |= ETH_TEST_FL_FAILED; - /* Offline tests aren't run; pass by default */ + /* Online tests aren't run; pass by default */ data[0] = 0; data[1] = 0; data[2] = 0; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 796c4f7d4260..29e6f6aba9e2 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -2367,6 +2367,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) /* Need to reset the PHY or these changes will be ignored */ mii_ctrl_reg |= MII_CR_RESET; + /* Disable MDI-X support for 10/100 */ } else if (hw->phy_type == e1000_phy_ife) { ret_val = e1000_read_phy_reg(hw, IFE_PHY_MDIX_CONTROL, &phy_data); @@ -2379,6 +2380,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) ret_val = e1000_write_phy_reg(hw, IFE_PHY_MDIX_CONTROL, phy_data); if (ret_val) return ret_val; + } else { /* Clear Auto-Crossover to force MDI manually. IGP requires MDI * forced whenever speed or duplex are forced. @@ -5841,6 +5843,7 @@ e1000_mta_set(struct e1000_hw *hw, hash_reg = (hash_value >> 5) & 0x7F; if (hw->mac_type == e1000_ich8lan) hash_reg &= 0x1F; + hash_bit = hash_value & 0x1F; mta = E1000_READ_REG_ARRAY(hw, MTA, hash_reg); @@ -6026,6 +6029,7 @@ e1000_id_led_init(struct e1000_hw * hw) else eeprom_data = ID_LED_DEFAULT; } + for (i = 0; i < 4; i++) { temp = (eeprom_data >> (i << 2)) & led_mask; switch (temp) { @@ -9013,5 +9017,3 @@ e1000_init_lcd_from_nvm(struct e1000_hw *hw) return E1000_SUCCESS; } - - diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 449a60303e07..b32a0c3cfd10 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -326,6 +326,7 @@ int32_t e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); + void e1000_phy_powerdown_workaround(struct e1000_hw *hw); /* EEPROM Functions */ @@ -390,7 +391,6 @@ int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer, uint16_t length); boolean_t e1000_check_mng_mode(struct e1000_hw *hw); boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw); - int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); @@ -576,6 +576,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); * E1000_RAR_ENTRIES - 1 multicast addresses. */ #define E1000_RAR_ENTRIES 15 + #define E1000_RAR_ENTRIES_ICH8LAN 6 #define MIN_NUMBER_OF_DESCRIPTORS 8 @@ -1335,9 +1336,9 @@ struct e1000_hw_stats { uint64_t gotch; uint64_t rnbc; uint64_t ruc; + uint64_t rfc; uint64_t roc; uint64_t rlerrc; - uint64_t rfc; uint64_t rjc; uint64_t mgprc; uint64_t mgpdc; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 726ec5e88ab2..7b1c092d921c 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -375,7 +375,7 @@ e1000_update_mng_vlan(struct e1000_adapter *adapter) * e1000_release_hw_control resets {CTRL_EXT|FWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that the * driver is no longer loaded. For AMT version (only with 82573) i - * of the f/w this means that the netowrk i/f is closed. + * of the f/w this means that the network i/f is closed. * **/ @@ -416,7 +416,7 @@ e1000_release_hw_control(struct e1000_adapter *adapter) * e1000_get_hw_control sets {CTRL_EXT|FWSM}:DRV_LOAD bit. * For ASF and Pass Through versions of f/w this means that * the driver is loaded. For AMT version (only with 82573) - * of the f/w this means that the netowrk i/f is open. + * of the f/w this means that the network i/f is open. * **/ @@ -426,6 +426,7 @@ e1000_get_hw_control(struct e1000_adapter *adapter) uint32_t ctrl_ext; uint32_t swsm; uint32_t extcnf; + /* Let firmware know the driver has taken over */ switch (adapter->hw.mac_type) { case e1000_82571: @@ -1279,12 +1280,10 @@ e1000_open(struct net_device *netdev) return -EBUSY; /* allocate transmit descriptors */ - if ((err = e1000_setup_all_tx_resources(adapter))) goto err_setup_tx; /* allocate receive descriptors */ - if ((err = e1000_setup_all_rx_resources(adapter))) goto err_setup_rx; @@ -1569,6 +1568,8 @@ e1000_configure_tx(struct e1000_adapter *adapter) if (hw->mac_type == e1000_82571 || hw->mac_type == e1000_82572) { tarc = E1000_READ_REG(hw, TARC0); + /* set the speed mode bit, we'll clear it if we're not at + * gigabit link later */ tarc |= (1 << 21); E1000_WRITE_REG(hw, TARC0, tarc); } else if (hw->mac_type == e1000_80003es2lan) { @@ -2418,6 +2419,7 @@ e1000_watchdog(unsigned long data) DPRINTK(LINK, INFO, "Gigabit has been disabled, downgrading speed\n"); } + if (adapter->hw.mac_type == e1000_82573) { e1000_enable_tx_pkt_filtering(&adapter->hw); if (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id) @@ -2462,13 +2464,12 @@ e1000_watchdog(unsigned long data) if ((adapter->hw.mac_type == e1000_82571 || adapter->hw.mac_type == e1000_82572) && txb2b == 0) { -#define SPEED_MODE_BIT (1 << 21) uint32_t tarc0; tarc0 = E1000_READ_REG(&adapter->hw, TARC0); - tarc0 &= ~SPEED_MODE_BIT; + tarc0 &= ~(1 << 21); E1000_WRITE_REG(&adapter->hw, TARC0, tarc0); } - + #ifdef NETIF_F_TSO /* disable TSO for pcie and 10/100 speeds, to avoid * some hardware issues */ @@ -3010,9 +3011,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) max_per_txd = min(mss << 2, max_per_txd); max_txd_pwr = fls(max_per_txd) - 1; - /* TSO Workaround for 82571/2/3 Controllers -- if skb->data - * points to just header, pull a few bytes of payload from - * frags into skb->data */ + /* TSO Workaround for 82571/2/3 Controllers -- if skb->data + * points to just header, pull a few bytes of payload from + * frags into skb->data */ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); if (skb->data_len && (hdr_len == (skb->len - skb->data_len))) { switch (adapter->hw.mac_type) { @@ -3316,12 +3317,12 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.roc += E1000_READ_REG(hw, ROC); if (adapter->hw.mac_type != e1000_ich8lan) { - adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); - adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); - adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); - adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); - adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); - adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); + adapter->stats.prc64 += E1000_READ_REG(hw, PRC64); + adapter->stats.prc127 += E1000_READ_REG(hw, PRC127); + adapter->stats.prc255 += E1000_READ_REG(hw, PRC255); + adapter->stats.prc511 += E1000_READ_REG(hw, PRC511); + adapter->stats.prc1023 += E1000_READ_REG(hw, PRC1023); + adapter->stats.prc1522 += E1000_READ_REG(hw, PRC1522); } adapter->stats.symerrs += E1000_READ_REG(hw, SYMERRS); @@ -3352,12 +3353,12 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.tpr += E1000_READ_REG(hw, TPR); if (adapter->hw.mac_type != e1000_ich8lan) { - adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); - adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); - adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); - adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); - adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); - adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); + adapter->stats.ptc64 += E1000_READ_REG(hw, PTC64); + adapter->stats.ptc127 += E1000_READ_REG(hw, PTC127); + adapter->stats.ptc255 += E1000_READ_REG(hw, PTC255); + adapter->stats.ptc511 += E1000_READ_REG(hw, PTC511); + adapter->stats.ptc1023 += E1000_READ_REG(hw, PTC1023); + adapter->stats.ptc1522 += E1000_READ_REG(hw, PTC1522); } adapter->stats.mptc += E1000_READ_REG(hw, MPTC); @@ -3383,18 +3384,17 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC); if (adapter->hw.mac_type != e1000_ich8lan) { - adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); - adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); - adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); - adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); - adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); - adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); - adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); + adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC); + adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC); + adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC); + adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC); + adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC); + adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC); + adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC); } } /* Fill out the OS statistics structure */ - adapter->net_stats.rx_packets = adapter->stats.gprc; adapter->net_stats.tx_packets = adapter->stats.gptc; adapter->net_stats.rx_bytes = adapter->stats.gorcl; @@ -3426,7 +3426,6 @@ e1000_update_stats(struct e1000_adapter *adapter) /* Tx Dropped needs to be maintained elsewhere */ /* Phy Stats */ - if (hw->media_type == e1000_media_type_copper) { if ((adapter->link_speed == SPEED_1000) && (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { @@ -3502,6 +3501,8 @@ e1000_intr(int irq, void *data) if (likely(netif_rx_schedule_prep(netdev))) __netif_rx_schedule(netdev); else + /* this really should not happen! if it does it is basically a + * bug, but not a hard error, so enable ints and continue */ e1000_irq_enable(adapter); #else /* Writing IMC and IMS is needed for 82547. @@ -3528,7 +3529,6 @@ e1000_intr(int irq, void *data) e1000_irq_enable(adapter); #endif - return IRQ_HANDLED; } @@ -3615,7 +3615,6 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, if (unlikely(++i == tx_ring->count)) i = 0; } - eop = tx_ring->buffer_info[i].next_to_watch; eop_desc = E1000_TX_DESC(*tx_ring, eop); #ifdef CONFIG_E1000_NAPI @@ -3760,6 +3759,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, while (rx_desc->status & E1000_RXD_STAT_DD) { struct sk_buff *skb; u8 status; + #ifdef CONFIG_E1000_NAPI if (*work_done >= work_to_do) break; @@ -3999,7 +3999,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, goto copydone; } /* if */ } - + for (j = 0; j < adapter->rx_ps_pages; j++) { if (!(length= le16_to_cpu(rx_desc->wb.upper.length[j]))) break; @@ -4234,7 +4234,7 @@ e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter, } skb = netdev_alloc_skb(netdev, - adapter->rx_ps_bsize0 + NET_IP_ALIGN); + adapter->rx_ps_bsize0 + NET_IP_ALIGN); if (unlikely(!skb)) { adapter->alloc_rx_buff_failed++; @@ -4511,7 +4511,6 @@ e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value) return E1000_SUCCESS; } - void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value) { @@ -4534,12 +4533,12 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); if (adapter->hw.mac_type != e1000_ich8lan) { - /* enable VLAN receive filtering */ - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl |= E1000_RCTL_VFE; - rctl &= ~E1000_RCTL_CFIEN; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - e1000_update_mng_vlan(adapter); + /* enable VLAN receive filtering */ + rctl = E1000_READ_REG(&adapter->hw, RCTL); + rctl |= E1000_RCTL_VFE; + rctl &= ~E1000_RCTL_CFIEN; + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + e1000_update_mng_vlan(adapter); } } else { /* disable VLAN tag insert/strip */ @@ -4548,14 +4547,16 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); if (adapter->hw.mac_type != e1000_ich8lan) { - /* disable VLAN filtering */ - rctl = E1000_READ_REG(&adapter->hw, RCTL); - rctl &= ~E1000_RCTL_VFE; - E1000_WRITE_REG(&adapter->hw, RCTL, rctl); - if (adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) { - e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id); - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } + /* disable VLAN filtering */ + rctl = E1000_READ_REG(&adapter->hw, RCTL); + rctl &= ~E1000_RCTL_VFE; + E1000_WRITE_REG(&adapter->hw, RCTL, rctl); + if (adapter->mng_vlan_id != + (uint16_t)E1000_MNG_VLAN_NONE) { + e1000_vlan_rx_kill_vid(netdev, + adapter->mng_vlan_id); + adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; + } } } diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index a464cb290621..3b7eb7c20019 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -119,5 +119,4 @@ typedef enum { #define E1000_READ_ICH8_REG16(a, reg) ( \ readw((a)->flash_address + reg)) - #endif /* _E1000_OSDEP_H_ */ -- cgit v1.2.3 From b00dae7cce465323850c3e1fd3ac8b2d9229735c Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:33 -0800 Subject: e1000: Remove DISABLE_MULR debug code Remove debugging code disabling MULR (multiple reads). It's not usable for a wide audience and there are no known problems with MULR right now. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7b1c092d921c..35d6d080522f 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -602,9 +602,6 @@ void e1000_reset(struct e1000_adapter *adapter) { uint32_t pba, manc; -#ifdef DISABLE_MULR - uint32_t tctl; -#endif uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF; /* Repartition Pba for greater than 9k mtu @@ -671,12 +668,7 @@ e1000_reset(struct e1000_adapter *adapter) e1000_reset_hw(&adapter->hw); if (adapter->hw.mac_type >= e1000_82544) E1000_WRITE_REG(&adapter->hw, WUC, 0); -#ifdef DISABLE_MULR - /* disable Multiple Reads in Transmit Control Register for debugging */ - tctl = E1000_READ_REG(hw, TCTL); - E1000_WRITE_REG(hw, TCTL, tctl & ~E1000_TCTL_MULR); -#endif if (e1000_init_hw(&adapter->hw)) DPRINTK(PROBE, ERR, "Hardware Error\n"); e1000_update_mng_vlan(adapter); -- cgit v1.2.3 From 87ca4e5b8d729fc157a0a599d78ccab245fc0602 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:36 -0800 Subject: e1000: FIX: enable hw TSO for IPV6 Enable TSO for IPV6. All e1000 hardware supports it. This reduces CPU utilizations by 50% when transmitting IPv6 frames. Fix symbol naming enabling ipv6 TSO. Turn off TSO6 for 10/100. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000.h | 3 +++ drivers/net/e1000/e1000_ethtool.c | 7 +++++++ drivers/net/e1000/e1000_main.c | 19 ++++++++++++++----- 3 files changed, 24 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 7ecce438d258..3f0be02e85e2 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -59,6 +59,9 @@ #include #include #include +#ifdef NETIF_F_TSO6 +#include +#endif #include #include #include diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 82d2c78e1696..b9c0927d79b3 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -348,6 +348,13 @@ e1000_set_tso(struct net_device *netdev, uint32_t data) else netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + if (data) + netdev->features |= NETIF_F_TSO6; + else + netdev->features &= ~NETIF_F_TSO6; +#endif + DPRINTK(PROBE, INFO, "TSO is %s\n", data ? "Enabled" : "Disabled"); adapter->tso_force = TRUE; return 0; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 35d6d080522f..38ee39e570ea 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -844,9 +844,9 @@ e1000_probe(struct pci_dev *pdev, (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; -#ifdef NETIF_F_TSO_IPV6 +#ifdef NETIF_F_TSO6 if (adapter->hw.mac_type > e1000_82547_rev_2) - netdev->features |= NETIF_F_TSO_IPV6; + netdev->features |= NETIF_F_TSO6; #endif #endif if (pci_using_dac) @@ -1814,8 +1814,11 @@ e1000_setup_rctl(struct e1000_adapter *adapter) /* Configure extra packet-split registers */ rfctl = E1000_READ_REG(&adapter->hw, RFCTL); rfctl |= E1000_RFCTL_EXTEN; - /* disable IPv6 packet split support */ - rfctl |= E1000_RFCTL_IPV6_DIS; + /* disable packet split support for IPv6 extension headers, + * because some malformed IPv6 headers can hang the RX */ + rfctl |= (E1000_RFCTL_IPV6_EX_DIS | + E1000_RFCTL_NEW_IPV6_EXT_DIS); + E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl); rctl |= E1000_RCTL_DTYP_PS; @@ -2473,9 +2476,15 @@ e1000_watchdog(unsigned long data) DPRINTK(PROBE,INFO, "10/100 speed: disabling TSO\n"); netdev->features &= ~NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features &= ~NETIF_F_TSO6; +#endif break; case SPEED_1000: netdev->features |= NETIF_F_TSO; +#ifdef NETIF_F_TSO6 + netdev->features |= NETIF_F_TSO6; +#endif break; default: /* oops */ @@ -2610,7 +2619,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, 0); cmd_length = E1000_TXD_CMD_IP; ipcse = skb->h.raw - skb->data - 1; -#ifdef NETIF_F_TSO_IPV6 +#ifdef NETIF_F_TSO6 } else if (skb->protocol == htons(ETH_P_IPV6)) { skb->nh.ipv6h->payload_len = 0; skb->h.th->check = -- cgit v1.2.3 From 21c4d5e07859a6fc0f62be37da15b161e142c8d1 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:39 -0800 Subject: e1000: Enble early receive (ERT) on 82573 Enable early receives on 82573 for jumbo frame performance. Jumbo's are only supported on 82573L with ASPM disabled. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 38ee39e570ea..93b97c6b8a63 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1934,6 +1934,12 @@ e1000_configure_rx(struct e1000_adapter *adapter) E1000_WRITE_REG(hw, RXCSUM, rxcsum); } + /* enable early receives on 82573, only takes effect if using > 2048 + * byte total frame size. for example only for jumbo frames */ +#define E1000_ERT_2048 0x100 + if (hw->mac_type == e1000_82573) + E1000_WRITE_REG(hw, ERT, E1000_ERT_2048); + /* Enable Receives */ E1000_WRITE_REG(hw, RCTL, rctl); } -- cgit v1.2.3 From 2ce9047f5d8464039da8ff986e71be5546e229c0 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:47:42 -0800 Subject: e1000: add mmiowb() for IA64 to sync tail writes IA64 SMP systems were seeing TX issues with multiple cpu's attempting to write tail registers unordered. This mmiowb() fixes the issue. Signed-off-by: Auke Kok Signed-off-by: Jesse Brandeburg --- drivers/net/e1000/e1000_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 93b97c6b8a63..681b738c6dac 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2867,6 +2867,9 @@ e1000_tx_queue(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, tx_ring->next_to_use = i; writel(i, adapter->hw.hw_addr + tx_ring->tdt); + /* we need this if more than one processor can write to our tail + * at a time, it syncronizes IO on IA64/Altix systems */ + mmiowb(); } /** -- cgit v1.2.3 From 070f6ffbb8ed5c398e84f1508752b8fd15b05cf2 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 1 Nov 2006 08:47:44 -0800 Subject: e1000: fix VR powerdown code On ich systems during PHY power down to D3, the voltage regulators were left on. Signed-off-by: Auke Kok Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000_hw.c | 9 +++++---- drivers/net/e1000/e1000_hw.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 29e6f6aba9e2..0e2ccf50d4d7 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -3942,14 +3942,15 @@ e1000_phy_powerdown_workaround(struct e1000_hw *hw) E1000_WRITE_REG(hw, PHY_CTRL, reg | E1000_PHY_CTRL_GBE_DISABLE | E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - /* Write VR power-down enable */ + /* Write VR power-down enable - bits 9:8 should be 10b */ e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); - e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data | - IGP3_VR_CTRL_MODE_SHUT); + phy_data |= (1 << 9); + phy_data &= ~(1 << 8); + e1000_write_phy_reg(hw, IGP3_VR_CTRL, phy_data); /* Read it back and test */ e1000_read_phy_reg(hw, IGP3_VR_CTRL, &phy_data); - if ((phy_data & IGP3_VR_CTRL_MODE_SHUT) || retry) + if (((phy_data & IGP3_VR_CTRL_MODE_MASK) == IGP3_VR_CTRL_MODE_SHUT) || retry) break; /* Issue PHY reset and repeat at most one more time */ diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index b32a0c3cfd10..31bea3215841 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -3173,6 +3173,7 @@ struct e1000_host_command_info { #define IGP3_VR_CTRL \ PHY_REG(776, 18) /* Voltage regulator control register */ #define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */ +#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */ #define IGP3_CAPABILITY \ PHY_REG(776, 19) /* IGP3 Capability Register */ -- cgit v1.2.3 From 2bc35c1078fdfe7bb2a849c2d1bee8d9d5fea4a7 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 1 Nov 2006 08:47:47 -0800 Subject: e1000: reorder pci-e infor struct Order pci-e capability struct according to bus/pci bus width ordering preserving the hard pci spec numbers. Signed-off-by: Auke Kok Signed-off-by: Jeff Kirsher --- drivers/net/e1000/e1000_hw.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 31bea3215841..f247f264a57b 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -128,11 +128,13 @@ typedef enum { /* PCI bus widths */ typedef enum { e1000_bus_width_unknown = 0, + /* These PCIe values should literally match the possible return values + * from config space */ + e1000_bus_width_pciex_1 = 1, + e1000_bus_width_pciex_2 = 2, + e1000_bus_width_pciex_4 = 4, e1000_bus_width_32, e1000_bus_width_64, - e1000_bus_width_pciex_1, - e1000_bus_width_pciex_2, - e1000_bus_width_pciex_4, e1000_bus_width_reserved } e1000_bus_width; -- cgit v1.2.3 From 996695de21b9b301ebb32379e2950fc2142df3a7 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:50 -0800 Subject: e1000: simplify skb_put call. Simplify two calls to skb_put by removing one call to it. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 681b738c6dac..44ba52229c73 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -3842,12 +3842,11 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, /* save the skb in buffer_info as good */ buffer_info->skb = skb; skb = new_skb; - skb_put(skb, length); } - } else - skb_put(skb, length); - + /* else just continue with the old one */ + } /* end copybreak code */ + skb_put(skb, length); /* Receive Checksum Offload */ e1000_rx_checksum(adapter, -- cgit v1.2.3 From a9ebadd640927ac6529d904b4131b17e8019d199 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:47:53 -0800 Subject: e1000: Remove unneeded and unwanted memsets This memsetting was added in a paranoid rage debugging TX hangs, but are no longer of importance. We can beef up the performance quite a bit removing them. Make sure to fill in next_to_watch to allow this. Signed-off-by: Auke Kok Signed-off-by: Jesse Brandeburg --- drivers/net/e1000/e1000_main.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 44ba52229c73..9d82bbb1a826 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1993,10 +1993,13 @@ e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, buffer_info->dma, buffer_info->length, PCI_DMA_TODEVICE); + buffer_info->dma = 0; } - if (buffer_info->skb) + if (buffer_info->skb) { dev_kfree_skb_any(buffer_info->skb); - memset(buffer_info, 0, sizeof(struct e1000_buffer)); + buffer_info->skb = NULL; + } + /* buffer_info must be completely set up in the transmit path */ } /** @@ -2661,6 +2664,7 @@ e1000_tso(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, context_desc->cmd_and_length = cpu_to_le32(cmd_length); buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; if (++i == tx_ring->count) i = 0; tx_ring->next_to_use = i; @@ -2695,6 +2699,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; if (unlikely(++i == tx_ring->count)) i = 0; tx_ring->next_to_use = i; @@ -2763,6 +2768,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; len -= size; offset += size; @@ -2802,6 +2808,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, size, PCI_DMA_TODEVICE); buffer_info->time_stamp = jiffies; + buffer_info->next_to_watch = i; len -= size; offset += size; @@ -3620,7 +3627,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, cleaned = (i == eop); e1000_unmap_and_free_tx_resource(adapter, buffer_info); - memset(tx_desc, 0, sizeof(struct e1000_tx_desc)); + tx_desc->upper.data = 0; if (unlikely(++i == tx_ring->count)) i = 0; } -- cgit v1.2.3 From fc2307d00c15385fbdbb5928a8517e5f63c3d068 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:47:56 -0800 Subject: e1000: New hardware support Add support for a Low Profile quad-port PCI-E adapter and 2 variants of the ICH8 systems' onboard NIC's. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_ethtool.c | 1 + drivers/net/e1000/e1000_hw.c | 3 +++ drivers/net/e1000/e1000_hw.h | 3 +++ drivers/net/e1000/e1000_main.c | 4 ++++ 4 files changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index b9c0927d79b3..dbac71ba71b1 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1725,6 +1725,7 @@ static int e1000_wol_exclusion(struct e1000_adapter *adapter, struct ethtool_wol retval = 0; break; case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: /* quad port adapters only support WoL on port A */ if (!adapter->quad_port_a) { diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 0e2ccf50d4d7..0bb9dd82d633 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -385,6 +385,7 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82571EB_FIBER: case E1000_DEV_ID_82571EB_SERDES: case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: hw->mac_type = e1000_82571; break; case E1000_DEV_ID_82572EI_COPPER: @@ -408,6 +409,8 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_ICH8_IGP_AMT: case E1000_DEV_ID_ICH8_IGP_C: case E1000_DEV_ID_ICH8_IFE: + case E1000_DEV_ID_ICH8_IFE_GT: + case E1000_DEV_ID_ICH8_IFE_G: case E1000_DEV_ID_ICH8_IGP_M: hw->mac_type = e1000_ich8lan; break; diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index f247f264a57b..93c1e260ee6a 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -475,6 +475,7 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #define E1000_DEV_ID_82571EB_FIBER 0x105F #define E1000_DEV_ID_82571EB_SERDES 0x1060 #define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 +#define E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE 0x10BC #define E1000_DEV_ID_82572EI_COPPER 0x107D #define E1000_DEV_ID_82572EI_FIBER 0x107E #define E1000_DEV_ID_82572EI_SERDES 0x107F @@ -492,6 +493,8 @@ int32_t e1000_check_phy_reset_block(struct e1000_hw *hw); #define E1000_DEV_ID_ICH8_IGP_AMT 0x104A #define E1000_DEV_ID_ICH8_IGP_C 0x104B #define E1000_DEV_ID_ICH8_IFE 0x104C +#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 +#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 #define E1000_DEV_ID_ICH8_IGP_M 0x104D diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 9d82bbb1a826..96e44a825443 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -103,6 +103,9 @@ static struct pci_device_id e1000_pci_tbl[] = { INTEL_E1000_ETHERNET_DEVICE(0x10B9), INTEL_E1000_ETHERNET_DEVICE(0x10BA), INTEL_E1000_ETHERNET_DEVICE(0x10BB), + INTEL_E1000_ETHERNET_DEVICE(0x10BC), + INTEL_E1000_ETHERNET_DEVICE(0x10C4), + INTEL_E1000_ETHERNET_DEVICE(0x10C5), /* required last entry */ {0,} }; @@ -961,6 +964,7 @@ e1000_probe(struct pci_dev *pdev, break; case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: case E1000_DEV_ID_82571EB_QUAD_COPPER: + case E1000_DEV_ID_82571EB_QUAD_COPPER_LOWPROFILE: /* if quad port adapter, disable WoL on all but port A */ if (global_quad_port_a != 0) adapter->eeprom_wol = 0; -- cgit v1.2.3 From fcfb1224250d7877b6a6c6a947986e08b2160fb6 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:47:59 -0800 Subject: e1000: add queue restart counter Add a netif_wake/start_queue counter to the ethtool statistics to indicated to the user that their transmit ring could be too small for their workload. Signed-off-by: Jesse brandeburg Cc: Jamal Hadi Signed-off-by: Auke Kok --- drivers/net/e1000/e1000.h | 1 + drivers/net/e1000/e1000_ethtool.c | 1 + drivers/net/e1000/e1000_main.c | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 3f0be02e85e2..896ea8a72386 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -265,6 +265,7 @@ struct e1000_adapter { /* TX */ struct e1000_tx_ring *tx_ring; /* One per active queue */ + unsigned int restart_queue; unsigned long tx_queue_len; uint32_t txd_cmd; uint32_t tx_int_delay; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index dbac71ba71b1..da459f7177c6 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -85,6 +85,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { { "tx_single_coll_ok", E1000_STAT(stats.scc) }, { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, + { "tx_restart_queue", E1000_STAT(restart_queue) }, { "rx_long_length_errors", E1000_STAT(stats.roc) }, { "rx_short_length_errors", E1000_STAT(stats.ruc) }, { "rx_align_errors", E1000_STAT(stats.algnerrc) }, diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 96e44a825443..705e654c368a 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2974,6 +2974,7 @@ static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) /* A reprieve! */ netif_start_queue(netdev); + ++adapter->restart_queue; return 0; } @@ -3654,8 +3655,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, * sees the new next_to_clean. */ smp_mb(); - if (netif_queue_stopped(netdev)) + if (netif_queue_stopped(netdev)) { netif_wake_queue(netdev); + ++adapter->restart_queue; + } } if (adapter->detect_tx_hung) { -- cgit v1.2.3 From 2df7d59f287236a636fb2d7e05879e65c8c56492 Mon Sep 17 00:00:00 2001 From: Jeff Kirsher Date: Wed, 1 Nov 2006 08:48:02 -0800 Subject: e1000: rename ICH8 flash macros ICH8 will soon be followed by newer chipsets bearing the same acronym, thus we remove the '8' and make it independent of the version number in the platform name. Signed-off-by: Jeff Kirsher Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_hw.c | 119 ++++++++++++++++++++-------------------- drivers/net/e1000/e1000_hw.h | 73 ++++++++++++------------ drivers/net/e1000/e1000_osdep.h | 8 +-- 3 files changed, 98 insertions(+), 102 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 0bb9dd82d633..3655d902b0bd 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -4555,7 +4555,7 @@ e1000_init_eeprom_params(struct e1000_hw *hw) case e1000_ich8lan: { int32_t i = 0; - uint32_t flash_size = E1000_READ_ICH8_REG(hw, ICH8_FLASH_GFPREG); + uint32_t flash_size = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_GFPREG); eeprom->type = e1000_eeprom_ich8; eeprom->use_eerd = FALSE; @@ -4571,12 +4571,14 @@ e1000_init_eeprom_params(struct e1000_hw *hw) } } - hw->flash_base_addr = (flash_size & ICH8_GFPREG_BASE_MASK) * - ICH8_FLASH_SECTOR_SIZE; + hw->flash_base_addr = (flash_size & ICH_GFPREG_BASE_MASK) * + ICH_FLASH_SECTOR_SIZE; + + hw->flash_bank_size = ((flash_size >> 16) & ICH_GFPREG_BASE_MASK) + 1; + hw->flash_bank_size -= (flash_size & ICH_GFPREG_BASE_MASK); + + hw->flash_bank_size *= ICH_FLASH_SECTOR_SIZE; - hw->flash_bank_size = ((flash_size >> 16) & ICH8_GFPREG_BASE_MASK) + 1; - hw->flash_bank_size -= (flash_size & ICH8_GFPREG_BASE_MASK); - hw->flash_bank_size *= ICH8_FLASH_SECTOR_SIZE; hw->flash_bank_size /= 2 * sizeof(uint16_t); break; @@ -5626,8 +5628,8 @@ e1000_commit_shadow_ram(struct e1000_hw *hw) * signature is valid. We want to do this after the write * has completed so that we don't mark the segment valid * while the write is still in progress */ - if (i == E1000_ICH8_NVM_SIG_WORD) - high_byte = E1000_ICH8_NVM_SIG_MASK | high_byte; + if (i == E1000_ICH_NVM_SIG_WORD) + high_byte = E1000_ICH_NVM_SIG_MASK | high_byte; error = e1000_verify_write_ich8_byte(hw, (i << 1) + new_bank_offset + 1, high_byte); @@ -5649,18 +5651,18 @@ e1000_commit_shadow_ram(struct e1000_hw *hw) * erase as well since these bits are 11 to start with * and we need to change bit 14 to 0b */ e1000_read_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, + E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, &high_byte); high_byte &= 0xBF; error = e1000_verify_write_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte); + E1000_ICH_NVM_SIG_WORD * 2 + 1 + new_bank_offset, high_byte); /* And invalidate the previously valid segment by setting * its signature word (0x13) high_byte to 0b. This can be * done without an erase because flash erase sets all bits * to 1's. We can write 1's to 0's without an erase */ if (error == E1000_SUCCESS) { error = e1000_verify_write_ich8_byte(hw, - E1000_ICH8_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0); + E1000_ICH_NVM_SIG_WORD * 2 + 1 + old_bank_offset, 0); } /* Clear the now not used entry in the cache */ @@ -8494,7 +8496,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw) DEBUGFUNC("e1000_ich8_cycle_init"); - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* May be check the Flash Des Valid bit in Hw status */ if (hsfsts.hsf_status.fldesvalid == 0) { @@ -8507,7 +8509,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw) hsfsts.hsf_status.flcerr = 1; hsfsts.hsf_status.dael = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); /* Either we should have a hardware SPI cycle in progress bit to check * against, in order to start a new cycle or FDONE bit should be changed @@ -8522,13 +8524,13 @@ e1000_ich8_cycle_init(struct e1000_hw *hw) /* There is no cycle running at present, so we can start a cycle */ /* Begin by setting Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); error = E1000_SUCCESS; } else { /* otherwise poll for sometime so the current cycle has a chance * to end before giving up. */ - for (i = 0; i < ICH8_FLASH_COMMAND_TIMEOUT; i++) { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + for (i = 0; i < ICH_FLASH_COMMAND_TIMEOUT; i++) { + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcinprog == 0) { error = E1000_SUCCESS; break; @@ -8539,7 +8541,7 @@ e1000_ich8_cycle_init(struct e1000_hw *hw) /* Successful in waiting for previous cycle to timeout, * now set the Flash Cycle Done. */ hsfsts.hsf_status.flcdone = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFSTS, hsfsts.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval); } else { DEBUGOUT("Flash controller busy, cannot get access"); } @@ -8561,13 +8563,13 @@ e1000_ich8_flash_cycle(struct e1000_hw *hw, uint32_t timeout) uint32_t i = 0; /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); hsflctl.hsf_ctrl.flcgo = 1; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* wait till FDONE bit is set to 1 */ do { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcdone == 1) break; udelay(1); @@ -8601,10 +8603,10 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, DEBUGFUNC("e1000_read_ich8_data"); if (size < 1 || size > 2 || data == 0x0 || - index > ICH8_FLASH_LINEAR_ADDR_MASK) + index > ICH_FLASH_LINEAR_ADDR_MASK) return error; - flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) + hw->flash_base_addr; do { @@ -8614,25 +8616,25 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, if (error != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_READ; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of index into Flash Linear address field in * Flash Address */ /* TODO: TBD maybe check the index against the size of flash */ - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); - error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT); + error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT); /* Check if FCERR is set to 1, if set to 1, clear it and try the whole * sequence a few more times, else read in (shift in) the Flash Data0, * the order is least significant byte first msb to lsb */ if (error == E1000_SUCCESS) { - flash_data = E1000_READ_ICH8_REG(hw, ICH8_FLASH_FDATA0); + flash_data = E1000_READ_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0); if (size == 1) { *data = (uint8_t)(flash_data & 0x000000FF); } else if (size == 2) { @@ -8642,9 +8644,9 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, } else { /* If we've gotten here, then things are probably completely hosed, * but if the error condition is detected, it won't hurt to give - * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* Repeat for some time before giving up. */ continue; @@ -8653,7 +8655,7 @@ e1000_read_ich8_data(struct e1000_hw *hw, uint32_t index, break; } } - } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT); + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return error; } @@ -8680,10 +8682,10 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, DEBUGFUNC("e1000_write_ich8_data"); if (size < 1 || size > 2 || data > size * 0xff || - index > ICH8_FLASH_LINEAR_ADDR_MASK) + index > ICH_FLASH_LINEAR_ADDR_MASK) return error; - flash_linear_address = (ICH8_FLASH_LINEAR_ADDR_MASK & index) + + flash_linear_address = (ICH_FLASH_LINEAR_ADDR_MASK & index) + hw->flash_base_addr; do { @@ -8693,34 +8695,34 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, if (error != E1000_SUCCESS) break; - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ hsflctl.hsf_ctrl.fldbcount = size -1; - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_WRITE; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of index into Flash Linear address field in * Flash Address */ - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); if (size == 1) flash_data = (uint32_t)data & 0x00FF; else flash_data = (uint32_t)data; - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FDATA0, flash_data); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data); /* check if FCERR is set to 1 , if set to 1, clear it and try the whole * sequence a few more times else done */ - error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_COMMAND_TIMEOUT); + error = e1000_ich8_flash_cycle(hw, ICH_FLASH_COMMAND_TIMEOUT); if (error == E1000_SUCCESS) { break; } else { /* If we're here, then things are most likely completely hosed, * but if the error condition is detected, it won't hurt to give - * it another try...ICH8_FLASH_CYCLE_REPEAT_COUNT times. + * it another try...ICH_FLASH_CYCLE_REPEAT_COUNT times. */ - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* Repeat for some time before giving up. */ continue; @@ -8729,7 +8731,7 @@ e1000_write_ich8_data(struct e1000_hw *hw, uint32_t index, uint32_t size, break; } } - } while (count++ < ICH8_FLASH_CYCLE_REPEAT_COUNT); + } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); return error; } @@ -8848,7 +8850,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) int32_t j = 0; int32_t error_flag = 0; - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); /* Determine HW Sector size: Read BERASE bits of Hw flash Status register */ /* 00: The Hw sector is 256 bytes, hence we need to erase 16 @@ -8861,19 +8863,14 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) * 11: The Hw sector size is 64K bytes */ if (hsfsts.hsf_status.berasesz == 0x0) { /* Hw sector size 256 */ - sub_sector_size = ICH8_FLASH_SEG_SIZE_256; - bank_size = ICH8_FLASH_SECTOR_SIZE; - iteration = ICH8_FLASH_SECTOR_SIZE / ICH8_FLASH_SEG_SIZE_256; + sub_sector_size = ICH_FLASH_SEG_SIZE_256; + bank_size = ICH_FLASH_SECTOR_SIZE; + iteration = ICH_FLASH_SECTOR_SIZE / ICH_FLASH_SEG_SIZE_256; } else if (hsfsts.hsf_status.berasesz == 0x1) { - bank_size = ICH8_FLASH_SEG_SIZE_4K; - iteration = 1; - } else if (hw->mac_type != e1000_ich8lan && - hsfsts.hsf_status.berasesz == 0x2) { - /* 8K erase size invalid for ICH8 - added in for ICH9 */ - bank_size = ICH9_FLASH_SEG_SIZE_8K; + bank_size = ICH_FLASH_SEG_SIZE_4K; iteration = 1; } else if (hsfsts.hsf_status.berasesz == 0x3) { - bank_size = ICH8_FLASH_SEG_SIZE_64K; + bank_size = ICH_FLASH_SEG_SIZE_64K; iteration = 1; } else { return error; @@ -8891,9 +8888,9 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) /* Write a value 11 (block Erase) in Flash Cycle field in Hw flash * Control */ - hsflctl.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcycle = ICH8_CYCLE_ERASE; - E1000_WRITE_ICH8_REG16(hw, ICH8_FLASH_HSFCTL, hsflctl.regval); + hsflctl.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL); + hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; + E1000_WRITE_ICH_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval); /* Write the last 24 bits of an index within the block into Flash * Linear address field in Flash Address. This probably needs to @@ -8901,17 +8898,17 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) * the software bank size (4, 8 or 64 KBytes) */ flash_linear_address = bank * bank_size + j * sub_sector_size; flash_linear_address += hw->flash_base_addr; - flash_linear_address &= ICH8_FLASH_LINEAR_ADDR_MASK; + flash_linear_address &= ICH_FLASH_LINEAR_ADDR_MASK; - E1000_WRITE_ICH8_REG(hw, ICH8_FLASH_FADDR, flash_linear_address); + E1000_WRITE_ICH_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_address); - error = e1000_ich8_flash_cycle(hw, ICH8_FLASH_ERASE_TIMEOUT); + error = e1000_ich8_flash_cycle(hw, ICH_FLASH_ERASE_TIMEOUT); /* Check if FCERR is set to 1. If 1, clear it and try the whole * sequence a few more times else Done */ if (error == E1000_SUCCESS) { break; } else { - hsfsts.regval = E1000_READ_ICH8_REG16(hw, ICH8_FLASH_HSFSTS); + hsfsts.regval = E1000_READ_ICH_FLASH_REG16(hw, ICH_FLASH_HSFSTS); if (hsfsts.hsf_status.flcerr == 1) { /* repeat for some time before giving up */ continue; @@ -8920,7 +8917,7 @@ e1000_erase_ich8_4k_segment(struct e1000_hw *hw, uint32_t bank) break; } } - } while ((count < ICH8_FLASH_CYCLE_REPEAT_COUNT) && !error_flag); + } while ((count < ICH_FLASH_CYCLE_REPEAT_COUNT) && !error_flag); if (error_flag == 1) break; } diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 93c1e260ee6a..3321fb13bfa9 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1583,8 +1583,8 @@ struct e1000_hw { #define E1000_HICR_FW_RESET 0xC0 #define E1000_SHADOW_RAM_WORDS 2048 -#define E1000_ICH8_NVM_SIG_WORD 0x13 -#define E1000_ICH8_NVM_SIG_MASK 0xC0 +#define E1000_ICH_NVM_SIG_WORD 0x13 +#define E1000_ICH_NVM_SIG_MASK 0xC0 /* EEPROM Read */ #define E1000_EERD_START 0x00000001 /* Start Read */ @@ -3263,41 +3263,40 @@ struct e1000_host_command_info { #define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ #define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ -#define ICH8_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ -#define ICH8_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ -#define ICH8_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */ -#define ICH8_FLASH_SEG_SIZE_256 256 -#define ICH8_FLASH_SEG_SIZE_4K 4096 -#define ICH9_FLASH_SEG_SIZE_8K 8192 -#define ICH8_FLASH_SEG_SIZE_64K 65536 - -#define ICH8_CYCLE_READ 0x0 -#define ICH8_CYCLE_RESERVED 0x1 -#define ICH8_CYCLE_WRITE 0x2 -#define ICH8_CYCLE_ERASE 0x3 - -#define ICH8_FLASH_GFPREG 0x0000 -#define ICH8_FLASH_HSFSTS 0x0004 -#define ICH8_FLASH_HSFCTL 0x0006 -#define ICH8_FLASH_FADDR 0x0008 -#define ICH8_FLASH_FDATA0 0x0010 -#define ICH8_FLASH_FRACC 0x0050 -#define ICH8_FLASH_FREG0 0x0054 -#define ICH8_FLASH_FREG1 0x0058 -#define ICH8_FLASH_FREG2 0x005C -#define ICH8_FLASH_FREG3 0x0060 -#define ICH8_FLASH_FPR0 0x0074 -#define ICH8_FLASH_FPR1 0x0078 -#define ICH8_FLASH_SSFSTS 0x0090 -#define ICH8_FLASH_SSFCTL 0x0092 -#define ICH8_FLASH_PREOP 0x0094 -#define ICH8_FLASH_OPTYPE 0x0096 -#define ICH8_FLASH_OPMENU 0x0098 - -#define ICH8_FLASH_REG_MAPSIZE 0x00A0 -#define ICH8_FLASH_SECTOR_SIZE 4096 -#define ICH8_GFPREG_BASE_MASK 0x1FFF -#define ICH8_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF +#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ +#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ +#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */ +#define ICH_FLASH_SEG_SIZE_256 256 +#define ICH_FLASH_SEG_SIZE_4K 4096 +#define ICH_FLASH_SEG_SIZE_64K 65536 + +#define ICH_CYCLE_READ 0x0 +#define ICH_CYCLE_RESERVED 0x1 +#define ICH_CYCLE_WRITE 0x2 +#define ICH_CYCLE_ERASE 0x3 + +#define ICH_FLASH_GFPREG 0x0000 +#define ICH_FLASH_HSFSTS 0x0004 +#define ICH_FLASH_HSFCTL 0x0006 +#define ICH_FLASH_FADDR 0x0008 +#define ICH_FLASH_FDATA0 0x0010 +#define ICH_FLASH_FRACC 0x0050 +#define ICH_FLASH_FREG0 0x0054 +#define ICH_FLASH_FREG1 0x0058 +#define ICH_FLASH_FREG2 0x005C +#define ICH_FLASH_FREG3 0x0060 +#define ICH_FLASH_FPR0 0x0074 +#define ICH_FLASH_FPR1 0x0078 +#define ICH_FLASH_SSFSTS 0x0090 +#define ICH_FLASH_SSFCTL 0x0092 +#define ICH_FLASH_PREOP 0x0094 +#define ICH_FLASH_OPTYPE 0x0096 +#define ICH_FLASH_OPMENU 0x0098 + +#define ICH_FLASH_REG_MAPSIZE 0x00A0 +#define ICH_FLASH_SECTOR_SIZE 4096 +#define ICH_GFPREG_BASE_MASK 0x1FFF +#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF /* ICH8 GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ /* Offset 04h HSFSTS */ diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 3b7eb7c20019..18afc0c25dac 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -107,16 +107,16 @@ typedef enum { #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS) -#define E1000_WRITE_ICH8_REG(a, reg, value) ( \ +#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \ writel((value), ((a)->flash_address + reg))) -#define E1000_READ_ICH8_REG(a, reg) ( \ +#define E1000_READ_ICH_FLASH_REG(a, reg) ( \ readl((a)->flash_address + reg)) -#define E1000_WRITE_ICH8_REG16(a, reg, value) ( \ +#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \ writew((value), ((a)->flash_address + reg))) -#define E1000_READ_ICH8_REG16(a, reg) ( \ +#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \ readw((a)->flash_address + reg)) #endif /* _E1000_OSDEP_H_ */ -- cgit v1.2.3 From 6a042dab19567fc888d5b87ce6ab68ac02aea1dc Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:48:04 -0800 Subject: e1000: Only set IDE for tx when we are using TIDV/TADV Spec fix: don't set IDE unless we are actually setting the tx int delay time. Signed-off-by: Auke Kok Signed-off-by: Jesse Brandeburg --- drivers/net/e1000/e1000_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 705e654c368a..fe22ae8f0a3d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1580,8 +1580,11 @@ e1000_configure_tx(struct e1000_adapter *adapter) e1000_config_collision_dist(hw); /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_IDE | E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS; + adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; + + /* only set IDE if we are delaying interrupts using the timers */ + if (adapter->tx_int_delay) + adapter->txd_cmd |= E1000_TXD_CMD_IDE; if (hw->mac_type < e1000_82543) adapter->txd_cmd |= E1000_TXD_CMD_RPS; -- cgit v1.2.3 From 04fedbfbc3dac1158519f8ef8cc8aca4fe79695b Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:48:07 -0800 Subject: e1000: reorder e1000_param.c This file needs some cleanups and reordering - logically order it so that relevant defines and code are together with properly quoted defaults. Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_param.c | 78 +++++++++++------------------------------ 1 file changed, 20 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 9c3c1acefccc..e4f88920b46b 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -44,16 +44,6 @@ */ #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -/* Module Parameters are always initialized to -1, so that the driver - * can tell the difference between no user specified value or the - * user asking for the default value. - * The true default values are loaded in when e1000_check_options is called. - * - * This is a GCC extension to ANSI C. - * See the item "Labeled Elements in Initializers" in the section - * "Extensions to the C Language Family" of the GCC documentation. - */ - #define E1000_PARAM(X, desc) \ static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ static int num_##X = 0; \ @@ -67,7 +57,6 @@ * * Default Value: 256 */ - E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); /* Receive Descriptor Count @@ -77,7 +66,6 @@ E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); * * Default Value: 256 */ - E1000_PARAM(RxDescriptors, "Number of receive descriptors"); /* User Specified Speed Override @@ -90,7 +78,6 @@ E1000_PARAM(RxDescriptors, "Number of receive descriptors"); * * Default Value: 0 */ - E1000_PARAM(Speed, "Speed setting"); /* User Specified Duplex Override @@ -102,7 +89,6 @@ E1000_PARAM(Speed, "Speed setting"); * * Default Value: 0 */ - E1000_PARAM(Duplex, "Duplex setting"); /* Auto-negotiation Advertisement Override @@ -119,8 +105,9 @@ E1000_PARAM(Duplex, "Duplex setting"); * * Default Value: 0x2F (copper); 0x20 (fiber) */ - E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); +#define AUTONEG_ADV_DEFAULT 0x2F +#define AUTONEG_ADV_MASK 0x2F /* User Specified Flow Control Override * @@ -132,8 +119,8 @@ E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); * * Default Value: Read flow control settings from the EEPROM */ - E1000_PARAM(FlowControl, "Flow Control setting"); +#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL /* XsumRX - Receive Checksum Offload Enable/Disable * @@ -144,53 +131,54 @@ E1000_PARAM(FlowControl, "Flow Control setting"); * * Default Value: 1 */ - E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); /* Transmit Interrupt Delay in units of 1.024 microseconds + * Tx interrupt delay needs to typically be set to something non zero * * Valid Range: 0-65535 - * - * Default Value: 64 */ - E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); +#define DEFAULT_TIDV 64 +#define MAX_TXDELAY 0xFFFF +#define MIN_TXDELAY 0 /* Transmit Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 - * - * Default Value: 0 */ - E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); +#define DEFAULT_TADV 64 +#define MAX_TXABSDELAY 0xFFFF +#define MIN_TXABSDELAY 0 /* Receive Interrupt Delay in units of 1.024 microseconds + * hardware will likely hang if you set this to anything but zero. * * Valid Range: 0-65535 - * - * Default Value: 0 */ - E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); +#define DEFAULT_RDTR 0 +#define MAX_RXDELAY 0xFFFF +#define MIN_RXDELAY 0 /* Receive Absolute Interrupt Delay in units of 1.024 microseconds * * Valid Range: 0-65535 - * - * Default Value: 128 */ - E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); +#define DEFAULT_RADV 128 +#define MAX_RXABSDELAY 0xFFFF +#define MIN_RXABSDELAY 0 /* Interrupt Throttle Rate (interrupts/sec) * * Valid Range: 100-100000 (0=off, 1=dynamic) - * - * Default Value: 8000 */ - E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); +#define DEFAULT_ITR 8000 +#define MAX_ITR 100000 +#define MIN_ITR 100 /* Enable Smart Power Down of the PHY * @@ -198,7 +186,6 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); * * Default Value: 0 (disabled) */ - E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); /* Enable Kumeran Lock Loss workaround @@ -207,33 +194,8 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); * * Default Value: 1 (enabled) */ - E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -#define DEFAULT_RDTR 0 -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -#define DEFAULT_RADV 128 -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -#define DEFAULT_TIDV 64 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -#define DEFAULT_TADV 64 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -#define DEFAULT_ITR 8000 -#define MAX_ITR 100000 -#define MIN_ITR 100 - struct e1000_option { enum { enable_option, range_option, list_option } type; char *name; -- cgit v1.2.3 From 9ac98284428961bd5be285a6cc1f5e6f5b6644aa Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:48:10 -0800 Subject: e1000: add dynamic generic MSI interrupt routine Add a generic MSI interrupt routine that is IO read-free, speeding up MSI interrupt handling. Signed-off-by: Jesse Brandeburg Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 90 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index fe22ae8f0a3d..35e4e32c7702 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -157,6 +157,9 @@ static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static int e1000_change_mtu(struct net_device *netdev, int new_mtu); static int e1000_set_mac(struct net_device *netdev, void *p); static irqreturn_t e1000_intr(int irq, void *data); +#ifdef CONFIG_PCI_MSI +static irqreturn_t e1000_intr_msi(int irq, void *data); +#endif static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring); #ifdef CONFIG_E1000_NAPI @@ -288,7 +291,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter) flags = IRQF_SHARED; #ifdef CONFIG_PCI_MSI - if (adapter->hw.mac_type > e1000_82547_rev_2) { + if (adapter->hw.mac_type >= e1000_82571) { adapter->have_msi = TRUE; if ((err = pci_enable_msi(adapter->pdev))) { DPRINTK(PROBE, ERR, @@ -296,8 +299,14 @@ static int e1000_request_irq(struct e1000_adapter *adapter) adapter->have_msi = FALSE; } } - if (adapter->have_msi) + if (adapter->have_msi) { flags &= ~IRQF_SHARED; + err = request_irq(adapter->pdev->irq, &e1000_intr_msi, flags, + netdev->name, netdev); + if (err) + DPRINTK(PROBE, ERR, + "Unable to allocate interrupt Error: %d\n", err); + } else #endif if ((err = request_irq(adapter->pdev->irq, &e1000_intr, flags, netdev->name, netdev))) @@ -3466,6 +3475,83 @@ e1000_update_stats(struct e1000_adapter *adapter) spin_unlock_irqrestore(&adapter->stats_lock, flags); } +#ifdef CONFIG_PCI_MSI + +/** + * e1000_intr_msi - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ + +static +irqreturn_t e1000_intr_msi(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; +#ifndef CONFIG_E1000_NAPI + int i; +#endif + + /* this code avoids the read of ICR but has to get 1000 interrupts + * at every link change event before it will notice the change */ + if (++adapter->detect_link >= 1000) { + uint32_t icr = E1000_READ_REG(hw, ICR); +#ifdef CONFIG_E1000_NAPI + /* read ICR disables interrupts using IAM, so keep up with our + * enable/disable accounting */ + atomic_inc(&adapter->irq_sem); +#endif + adapter->detect_link = 0; + if ((icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) && + (icr & E1000_ICR_INT_ASSERTED)) { + hw->get_link_status = 1; + /* 80003ES2LAN workaround-- + * For packet buffer work-around on link down event; + * disable receives here in the ISR and + * reset adapter in watchdog + */ + if (netif_carrier_ok(netdev) && + (adapter->hw.mac_type == e1000_80003es2lan)) { + /* disable receives */ + uint32_t rctl = E1000_READ_REG(hw, RCTL); + E1000_WRITE_REG(hw, RCTL, rctl & ~E1000_RCTL_EN); + } + /* guard against interrupt when we're going down */ + if (!test_bit(__E1000_DOWN, &adapter->flags)) + mod_timer(&adapter->watchdog_timer, + jiffies + 1); + } + } else { + E1000_WRITE_REG(hw, ICR, (0xffffffff & ~(E1000_ICR_RXSEQ | + E1000_ICR_LSC))); + /* bummer we have to flush here, but things break otherwise as + * some event appears to be lost or delayed and throughput + * drops. In almost all tests this flush is un-necessary */ + E1000_WRITE_FLUSH(hw); +#ifdef CONFIG_E1000_NAPI + /* Interrupt Auto-Mask (IAM)...upon writing ICR, interrupts are + * masked. No need for the IMC write, but it does mean we + * should account for it ASAP. */ + atomic_inc(&adapter->irq_sem); +#endif + } + +#ifdef CONFIG_E1000_NAPI + if (likely(netif_rx_schedule_prep(netdev))) + __netif_rx_schedule(netdev); + else + e1000_irq_enable(adapter); +#else + for (i = 0; i < E1000_MAX_INTR; i++) + if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & + !e1000_clean_tx_irq(adapter, adapter->tx_ring))) + break; +#endif + + return IRQ_HANDLED; +} +#endif /** * e1000_intr - Interrupt Handler -- cgit v1.2.3 From 835bb1298311f372a3387fb40b952b18d90aa9f8 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Wed, 1 Nov 2006 08:48:13 -0800 Subject: e1000: add dynamic itr modes Add a new dynamic itr algorithm, with 2 modes, and make it the default operation mode. This greatly reduces latency and increases small packet performance, at the "cost" of some CPU utilization. Bulk traffic throughput is unaffected. The driver can limit the amount of interrupts per second that the adapter will generate for incoming packets. It does this by writing a value to the adapter that is based on the maximum amount of interrupts that the adapter will generate per second. Setting InterruptThrottleRate to a value greater or equal to 100 will program the adapter to send out a maximum of that many interrupts per second, even if more packets have come in. This reduces interrupt load on the system and can lower CPU utilization under heavy load, but will increase latency as packets are not processed as quickly. The default behaviour of the driver previously assumed a static InterruptThrottleRate value of 8000, providing a good fallback value for all traffic types,but lacking in small packet performance and latency. The hardware can handle many more small packets per second however, and for this reason an adaptive interrupt moderation algorithm was implemented. Since 7.3.x, the driver has two adaptive modes (setting 1 or 3) in which it dynamically adjusts the InterruptThrottleRate value based on the traffic that it receives. After determining the type of incoming traffic in the last timeframe, it will adjust the InterruptThrottleRate to an appropriate value for that traffic. The algorithm classifies the incoming traffic every interval into classes. Once the class is determined, the InterruptThrottleRate value is adjusted to suit that traffic type the best. There are three classes defined: "Bulk traffic", for large amounts of packets of normal size; "Low latency", for small amounts of traffic and/or a significant percentage of small packets; and "Lowest latency", for almost completely small packets or minimal traffic. In dynamic conservative mode, the InterruptThrottleRate value is set to 4000 for traffic that falls in class "Bulk traffic". If traffic falls in the "Low latency" or "Lowest latency" class, the InterruptThrottleRate is increased stepwise to 20000. This default mode is suitable for most applications. For situations where low latency is vital such as cluster or grid computing, the algorithm can reduce latency even more when InterruptThrottleRate is set to mode 1. In this mode, which operates the same as mode 3, the InterruptThrottleRate will be increased stepwise to 70000 for traffic in class "Lowest latency". Setting InterruptThrottleRate to 0 turns off any interrupt moderation and may improve small packet latency, but is generally not suitable for bulk throughput traffic. Signed-off-by: Jesse Brandeburg Cc: Rick Jones Signed-off-by: Auke Kok --- drivers/net/e1000/e1000.h | 13 ++- drivers/net/e1000/e1000_main.c | 226 ++++++++++++++++++++++++++++++++++------ drivers/net/e1000/e1000_param.c | 28 +++-- 3 files changed, 228 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 896ea8a72386..f091042b146e 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -257,6 +257,17 @@ struct e1000_adapter { spinlock_t tx_queue_lock; #endif atomic_t irq_sem; + unsigned int detect_link; + unsigned int total_tx_bytes; + unsigned int total_tx_packets; + unsigned int total_rx_bytes; + unsigned int total_rx_packets; + /* Interrupt Throttle Rate */ + uint32_t itr; + uint32_t itr_setting; + uint16_t tx_itr; + uint16_t rx_itr; + struct work_struct reset_task; uint8_t fc_autoneg; @@ -314,8 +325,6 @@ struct e1000_adapter { uint64_t gorcl_old; uint16_t rx_ps_bsize0; - /* Interrupt Throttle Rate */ - uint32_t itr; /* OS defined structs */ struct net_device *netdev; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 35e4e32c7702..56be5c89363c 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1897,7 +1897,7 @@ e1000_configure_rx(struct e1000_adapter *adapter) if (hw->mac_type >= e1000_82540) { E1000_WRITE_REG(hw, RADV, adapter->rx_abs_int_delay); - if (adapter->itr > 1) + if (adapter->itr_setting != 0) E1000_WRITE_REG(hw, ITR, 1000000000 / (adapter->itr * 256)); } @@ -1907,11 +1907,11 @@ e1000_configure_rx(struct e1000_adapter *adapter) /* Reset delay timers after every interrupt */ ctrl_ext |= E1000_CTRL_EXT_INT_TIMER_CLR; #ifdef CONFIG_E1000_NAPI - /* Auto-Mask interrupts upon ICR read. */ + /* Auto-Mask interrupts upon ICR access */ ctrl_ext |= E1000_CTRL_EXT_IAME; + E1000_WRITE_REG(hw, IAM, 0xffffffff); #endif E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); - E1000_WRITE_REG(hw, IAM, ~0); E1000_WRITE_FLUSH(hw); } @@ -2576,19 +2576,6 @@ e1000_watchdog(unsigned long data) } } - /* Dynamic mode for Interrupt Throttle Rate (ITR) */ - if (adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; Total - * asymmetrical Tx or Rx gets ITR=8000; everyone - * else is between 2000-8000. */ - uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000; - uint32_t dif = (adapter->gotcl > adapter->gorcl ? - adapter->gotcl - adapter->gorcl : - adapter->gorcl - adapter->gotcl) / 10000; - uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256)); - } - /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); @@ -2604,6 +2591,135 @@ e1000_watchdog(unsigned long data) mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } +enum latency_range { + lowest_latency = 0, + low_latency = 1, + bulk_latency = 2, + latency_invalid = 255 +}; + +/** + * e1000_update_itr - update the dynamic ITR value based on statistics + * Stores a new ITR value based on packets and byte + * counts during the last interrupt. The advantage of per interrupt + * computation is faster updates and more accurate ITR for the current + * traffic pattern. Constants in this function were computed + * based on theoretical maximum wire speed and thresholds were set based + * on testing data as well as attempting to minimize response time + * while increasing bulk throughput. + * this functionality is controlled by the InterruptThrottleRate module + * parameter (see e1000_param.c) + * @adapter: pointer to adapter + * @itr_setting: current adapter->itr + * @packets: the number of packets during this measurement interval + * @bytes: the number of bytes during this measurement interval + **/ +static unsigned int e1000_update_itr(struct e1000_adapter *adapter, + uint16_t itr_setting, + int packets, + int bytes) +{ + unsigned int retval = itr_setting; + struct e1000_hw *hw = &adapter->hw; + + if (unlikely(hw->mac_type < e1000_82540)) + goto update_itr_done; + + if (packets == 0) + goto update_itr_done; + + + switch (itr_setting) { + case lowest_latency: + if ((packets < 5) && (bytes > 512)) + retval = low_latency; + break; + case low_latency: /* 50 usec aka 20000 ints/s */ + if (bytes > 10000) { + if ((packets < 10) || + ((bytes/packets) > 1200)) + retval = bulk_latency; + else if ((packets > 35)) + retval = lowest_latency; + } else if (packets <= 2 && bytes < 512) + retval = lowest_latency; + break; + case bulk_latency: /* 250 usec aka 4000 ints/s */ + if (bytes > 25000) { + if (packets > 35) + retval = low_latency; + } else { + if (bytes < 6000) + retval = low_latency; + } + break; + } + +update_itr_done: + return retval; +} + +static void e1000_set_itr(struct e1000_adapter *adapter) +{ + struct e1000_hw *hw = &adapter->hw; + uint16_t current_itr; + uint32_t new_itr = adapter->itr; + + if (unlikely(hw->mac_type < e1000_82540)) + return; + + /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ + if (unlikely(adapter->link_speed != SPEED_1000)) { + current_itr = 0; + new_itr = 4000; + goto set_itr_now; + } + + adapter->tx_itr = e1000_update_itr(adapter, + adapter->tx_itr, + adapter->total_tx_packets, + adapter->total_tx_bytes); + adapter->rx_itr = e1000_update_itr(adapter, + adapter->rx_itr, + adapter->total_rx_packets, + adapter->total_rx_bytes); + + current_itr = max(adapter->rx_itr, adapter->tx_itr); + + /* conservative mode eliminates the lowest_latency setting */ + if (current_itr == lowest_latency && (adapter->itr_setting == 3)) + current_itr = low_latency; + + switch (current_itr) { + /* counts and packets in update_itr are dependent on these numbers */ + case lowest_latency: + new_itr = 70000; + break; + case low_latency: + new_itr = 20000; /* aka hwitr = ~200 */ + break; + case bulk_latency: + new_itr = 4000; + break; + default: + break; + } + +set_itr_now: + if (new_itr != adapter->itr) { + /* this attempts to bias the interrupt rate towards Bulk + * by adding intermediate steps when interrupt rate is + * increasing */ + new_itr = new_itr > adapter->itr ? + min(adapter->itr + (new_itr >> 2), new_itr) : + new_itr; + adapter->itr = new_itr; + E1000_WRITE_REG(hw, ITR, 1000000000 / (new_itr * 256)); + } + + return; +} + #define E1000_TX_FLAGS_CSUM 0x00000001 #define E1000_TX_FLAGS_VLAN 0x00000002 #define E1000_TX_FLAGS_TSO 0x00000004 @@ -3538,15 +3654,27 @@ irqreturn_t e1000_intr_msi(int irq, void *data) } #ifdef CONFIG_E1000_NAPI - if (likely(netif_rx_schedule_prep(netdev))) + if (likely(netif_rx_schedule_prep(netdev))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; __netif_rx_schedule(netdev); - else + } else e1000_irq_enable(adapter); #else + adapter->total_tx_bytes = 0; + adapter->total_rx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_packets = 0; + for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; + + if (likely(adapter->itr_setting & 3)) + e1000_set_itr(adapter); #endif return IRQ_HANDLED; @@ -3568,7 +3696,17 @@ e1000_intr(int irq, void *data) uint32_t rctl, icr = E1000_READ_REG(hw, ICR); #ifndef CONFIG_E1000_NAPI int i; -#else +#endif + if (unlikely(!icr)) + return IRQ_NONE; /* Not our interrupt */ + +#ifdef CONFIG_E1000_NAPI + /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is + * not set, then the adapter didn't send an interrupt */ + if (unlikely(hw->mac_type >= e1000_82571 && + !(icr & E1000_ICR_INT_ASSERTED))) + return IRQ_NONE; + /* Interrupt Auto-Mask...upon reading ICR, * interrupts are masked. No need for the * IMC write, but it does mean we should @@ -3577,14 +3715,6 @@ e1000_intr(int irq, void *data) atomic_inc(&adapter->irq_sem); #endif - if (unlikely(!icr)) { -#ifdef CONFIG_E1000_NAPI - if (hw->mac_type >= e1000_82571) - e1000_irq_enable(adapter); -#endif - return IRQ_NONE; /* Not our interrupt */ - } - if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { hw->get_link_status = 1; /* 80003ES2LAN workaround-- @@ -3605,13 +3735,18 @@ e1000_intr(int irq, void *data) #ifdef CONFIG_E1000_NAPI if (unlikely(hw->mac_type < e1000_82571)) { + /* disable interrupts, without the synchronize_irq bit */ atomic_inc(&adapter->irq_sem); E1000_WRITE_REG(hw, IMC, ~0); E1000_WRITE_FLUSH(hw); } - if (likely(netif_rx_schedule_prep(netdev))) + if (likely(netif_rx_schedule_prep(netdev))) { + adapter->total_tx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_bytes = 0; + adapter->total_rx_packets = 0; __netif_rx_schedule(netdev); - else + } else /* this really should not happen! if it does it is basically a * bug, but not a hard error, so enable ints and continue */ e1000_irq_enable(adapter); @@ -3631,11 +3766,19 @@ e1000_intr(int irq, void *data) E1000_WRITE_REG(hw, IMC, ~0); } + adapter->total_tx_bytes = 0; + adapter->total_rx_bytes = 0; + adapter->total_tx_packets = 0; + adapter->total_rx_packets = 0; + for (i = 0; i < E1000_MAX_INTR; i++) if (unlikely(!adapter->clean_rx(adapter, adapter->rx_ring) & !e1000_clean_tx_irq(adapter, adapter->tx_ring))) break; + if (likely(adapter->itr_setting & 3)) + e1000_set_itr(adapter); + if (hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2) e1000_irq_enable(adapter); @@ -3683,6 +3826,8 @@ e1000_clean(struct net_device *poll_dev, int *budget) if ((!tx_cleaned && (work_done == 0)) || !netif_running(poll_dev)) { quit_polling: + if (likely(adapter->itr_setting & 3)) + e1000_set_itr(adapter); netif_rx_complete(poll_dev); e1000_irq_enable(adapter); return 0; @@ -3709,6 +3854,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, unsigned int count = 0; #endif boolean_t cleaned = FALSE; + unsigned int total_tx_bytes=0, total_tx_packets=0; i = tx_ring->next_to_clean; eop = tx_ring->buffer_info[i].next_to_watch; @@ -3720,6 +3866,13 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, buffer_info = &tx_ring->buffer_info[i]; cleaned = (i == eop); + if (cleaned) { + /* this packet count is wrong for TSO but has a + * tendency to make dynamic ITR change more + * towards bulk */ + total_tx_packets++; + total_tx_bytes += buffer_info->skb->len; + } e1000_unmap_and_free_tx_resource(adapter, buffer_info); tx_desc->upper.data = 0; @@ -3785,6 +3938,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter, netif_stop_queue(netdev); } } + adapter->total_tx_bytes += total_tx_bytes; + adapter->total_tx_packets += total_tx_packets; return cleaned; } @@ -3864,6 +4019,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, unsigned int i; int cleaned_count = 0; boolean_t cleaned = FALSE; + unsigned int total_rx_bytes=0, total_rx_packets=0; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); @@ -3930,6 +4086,10 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter, * done after the TBI_ACCEPT workaround above */ length -= 4; + /* probably a little skewed due to removing CRC */ + total_rx_bytes += length; + total_rx_packets++; + /* code added for copybreak, this should improve * performance for small packets with large amounts * of reassembly being done in the stack */ @@ -3998,6 +4158,8 @@ next_desc: if (cleaned_count) adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); + adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; return cleaned; } @@ -4027,6 +4189,7 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, uint32_t length, staterr; int cleaned_count = 0; boolean_t cleaned = FALSE; + unsigned int total_rx_bytes=0, total_rx_packets=0; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC_PS(*rx_ring, i); @@ -4131,6 +4294,9 @@ e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, pskb_trim(skb, skb->len - 4); copydone: + total_rx_bytes += skb->len; + total_rx_packets++; + e1000_rx_checksum(adapter, staterr, le16_to_cpu(rx_desc->wb.lower.hi_dword.csum_ip.csum), skb); skb->protocol = eth_type_trans(skb, netdev); @@ -4179,6 +4345,8 @@ next_desc: if (cleaned_count) adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); + adapter->total_rx_packets += total_rx_packets; + adapter->total_rx_bytes += total_rx_bytes; return cleaned; } diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index e4f88920b46b..cbfcd7f2889f 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -139,7 +139,7 @@ E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); * Valid Range: 0-65535 */ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); -#define DEFAULT_TIDV 64 +#define DEFAULT_TIDV 8 #define MAX_TXDELAY 0xFFFF #define MIN_TXDELAY 0 @@ -148,7 +148,7 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); * Valid Range: 0-65535 */ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); -#define DEFAULT_TADV 64 +#define DEFAULT_TADV 32 #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 @@ -167,16 +167,16 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); * Valid Range: 0-65535 */ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); -#define DEFAULT_RADV 128 +#define DEFAULT_RADV 8 #define MAX_RXABSDELAY 0xFFFF #define MIN_RXABSDELAY 0 /* Interrupt Throttle Rate (interrupts/sec) * - * Valid Range: 100-100000 (0=off, 1=dynamic) + * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) */ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); -#define DEFAULT_ITR 8000 +#define DEFAULT_ITR 3 #define MAX_ITR 100000 #define MIN_ITR 100 @@ -472,15 +472,27 @@ e1000_check_options(struct e1000_adapter *adapter) break; case 1: DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", - opt.name); + opt.name); + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + break; + case 3: + DPRINTK(PROBE, INFO, + "%s set to dynamic conservative mode\n", + opt.name); + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; break; default: e1000_validate_option(&adapter->itr, &opt, - adapter); + adapter); + /* save the setting, because the dynamic bits change itr */ + adapter->itr_setting = adapter->itr; break; } } else { - adapter->itr = opt.def; + adapter->itr_setting = opt.def; + adapter->itr = 20000; } } { /* Smart Power Down */ -- cgit v1.2.3 From 25006ac61e514628b9d0f78fce0bed155f4f109c Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 1 Nov 2006 08:48:15 -0800 Subject: e1000: increment version to 7.3.15-k2 Signed-off-by: Auke Kok --- drivers/net/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 56be5c89363c..a2f1464ba49d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -35,7 +35,7 @@ static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; #else #define DRIVERNAPI "-NAPI" #endif -#define DRV_VERSION "7.2.9-k4"DRIVERNAPI +#define DRV_VERSION "7.3.15-k2"DRIVERNAPI char e1000_driver_version[] = DRV_VERSION; static char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; -- cgit v1.2.3 From bf793295e1090af84972750898bf8470df5e5419 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Wed, 1 Nov 2006 00:53:05 +0100 Subject: r8169: perform a PHY reset before any other operation at boot time Realtek's 8139/810x (0x8136) PCI-E comes with a touchy PHY. A big heavy reset seems to calm it down. Fix for http://bugzilla.kernel.org/show_bug.cgi?id=7378. Signed-off-by: Francois Romieu Signed-off-by: Darren Salt --- drivers/net/r8169.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b977ed85ff39..45d3ca431957 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -571,8 +571,8 @@ static void rtl8169_xmii_reset_enable(void __iomem *ioaddr) { unsigned int val; - val = (mdio_read(ioaddr, MII_BMCR) | BMCR_RESET) & 0xffff; - mdio_write(ioaddr, MII_BMCR, val); + mdio_write(ioaddr, MII_BMCR, BMCR_RESET); + val = mdio_read(ioaddr, MII_BMCR); } static void rtl8169_check_link_status(struct net_device *dev, @@ -1406,6 +1406,22 @@ static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, free_netdev(dev); } +static void rtl8169_phy_reset(struct net_device *dev, + struct rtl8169_private *tp) +{ + void __iomem *ioaddr = tp->mmio_addr; + int i; + + tp->phy_reset_enable(ioaddr); + for (i = 0; i < 100; i++) { + if (!tp->phy_reset_pending(ioaddr)) + return; + msleep(1); + } + if (netif_msg_link(tp)) + printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); +} + static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -1434,6 +1450,8 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) rtl8169_link_option(board_idx, &autoneg, &speed, &duplex); + rtl8169_phy_reset(dev, tp); + rtl8169_set_speed(dev, autoneg, speed, duplex); if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp)) -- cgit v1.2.3 From c3a9392e4f3b9d97803b067871d66bc143369dbf Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 23 Oct 2006 22:20:15 +0200 Subject: [PATCH] kmemdup() cleanup in drivers/net hi, replace open coded kmemdup() to save some screen space, and allow inlining/not inlining to be triggered by gcc. Signed-off-by: Eric Sesterhenn Signed-off-by: Jeff Garzik --- drivers/net/tulip/de2104x.c | 4 +--- drivers/net/wireless/ipw2100.c | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index f6b3a94e97bf..9d67f11422ec 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1906,9 +1906,7 @@ fill_defaults: de->media[i].csr15 = t21041_csr15[i]; } - de->ee_data = kmalloc(DE_EEPROM_SIZE, GFP_KERNEL); - if (de->ee_data) - memcpy(de->ee_data, &ee_data[0], DE_EEPROM_SIZE); + de->ee_data = kmemdup(&ee_data[0], DE_EEPROM_SIZE, GFP_KERNEL); return; diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 4e4eaa2a99ca..5bf4d4119c3d 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -7568,11 +7568,10 @@ static int ipw2100_wx_set_genie(struct net_device *dev, return -EINVAL; if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); + buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); if (buf == NULL) return -ENOMEM; - memcpy(buf, extra, wrqu->data.length); kfree(ieee->wpa_ie); ieee->wpa_ie = buf; ieee->wpa_ie_len = wrqu->data.length; -- cgit v1.2.3 From b2e68aa337f950e4a8c893a82b95b1755309bc56 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 23 Oct 2006 13:53:17 +0100 Subject: [PATCH] defxx: Big-endian hosts support The PDQ DMA engine requires a different byte-swapping mode for big-endian hosts; also the MAC address which is read from a register through PIO has to be byte-swapped. These changes have been verified with DEFPA-DC (PCI) boards and a Broadcom BCM91250A (MIPS CPU based) host. Signed-off-by: Maciej W. Rozycki Signed-off-by: Jeff Garzik --- drivers/net/defxx.c | 39 +++++++++++++++++++-------------------- drivers/net/defxx.h | 15 ++++++++++++--- 2 files changed, 31 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c index 8f514cc0debd..dc3ab3b5c8cb 100644 --- a/drivers/net/defxx.c +++ b/drivers/net/defxx.c @@ -192,6 +192,7 @@ * 04 Aug 2003 macro Converted to the DMA API. * 14 Aug 2004 macro Fix device names reported. * 14 Jun 2005 macro Use irqreturn_t. + * 23 Oct 2006 macro Big-endian host support. */ /* Include files */ @@ -218,8 +219,8 @@ /* Version information string should be updated prior to each new release! */ #define DRV_NAME "defxx" -#define DRV_VERSION "v1.08" -#define DRV_RELDATE "2005/06/14" +#define DRV_VERSION "v1.09" +#define DRV_RELDATE "2006/10/23" static char version[] __devinitdata = DRV_NAME ": " DRV_VERSION " " DRV_RELDATE @@ -859,6 +860,7 @@ static int __devinit dfx_driver_init(struct net_device *dev, print_name); return(DFX_K_FAILURE); } + data = cpu_to_le32(data); memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32)); if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0, @@ -867,6 +869,7 @@ static int __devinit dfx_driver_init(struct net_device *dev, print_name); return(DFX_K_FAILURE); } + data = cpu_to_le32(data); memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16)); /* @@ -1085,27 +1088,23 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers) } /* - * Set base address of Descriptor Block and bring adapter to DMA_AVAILABLE state + * Set the base address of Descriptor Block and bring adapter + * to DMA_AVAILABLE state. * - * Note: We also set the literal and data swapping requirements in this - * command. Since this driver presently runs on Intel platforms - * which are Little Endian, we'll tell the adapter to byte swap - * data only. This code will need to change when we support - * Big Endian systems (eg. PowerPC). + * Note: We also set the literal and data swapping requirements + * in this command. * - * Assumption: 32-bit physical address of descriptor block is 8Kbyte - * aligned. That is, bits 0-12 of the address must be zero. + * Assumption: 32-bit physical address of descriptor block + * is 8Kbyte aligned. */ - - if (dfx_hw_port_ctrl_req(bp, - PI_PCTRL_M_INIT, - (u32) (bp->descr_block_phys | PI_PDATA_A_INIT_M_BSWAP_DATA), - 0, - NULL) != DFX_K_SUCCESS) - { - printk("%s: Could not set descriptor block address!\n", bp->dev->name); - return(DFX_K_FAILURE); - } + if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT, + (u32)(bp->descr_block_phys | + PI_PDATA_A_INIT_M_BSWAP_INIT), + 0, NULL) != DFX_K_SUCCESS) { + printk("%s: Could not set descriptor block address!\n", + bp->dev->name); + return DFX_K_FAILURE; + } /* Set transmit flush timeout value */ diff --git a/drivers/net/defxx.h b/drivers/net/defxx.h index 8b1e9a11ca21..2ce8f97253eb 100644 --- a/drivers/net/defxx.h +++ b/drivers/net/defxx.h @@ -25,6 +25,7 @@ * macros to DEFXX.C. * 12-Sep-96 LVS Removed packet request header pointers. * 04 Aug 2003 macro Converted to the DMA API. + * 23 Oct 2006 macro Big-endian host support. */ #ifndef _DEFXX_H_ @@ -1344,7 +1345,7 @@ typedef struct /* Register definition structures are defined for both big and little endian systems */ -#ifndef BIG_ENDIAN +#ifndef __BIG_ENDIAN /* Little endian format of Type 1 Producer register */ @@ -1402,7 +1403,11 @@ typedef union } index; } PI_TYPE_2_CONSUMER; -#else +/* Define swapping required by DMA transfers. */ +#define PI_PDATA_A_INIT_M_BSWAP_INIT \ + (PI_PDATA_A_INIT_M_BSWAP_DATA) + +#else /* __BIG_ENDIAN */ /* Big endian format of Type 1 Producer register */ @@ -1460,7 +1465,11 @@ typedef union } index; } PI_TYPE_2_CONSUMER; -#endif /* #ifndef BIG_ENDIAN */ +/* Define swapping required by DMA transfers. */ +#define PI_PDATA_A_INIT_M_BSWAP_INIT \ + (PI_PDATA_A_INIT_M_BSWAP_DATA | PI_PDATA_A_INIT_M_BSWAP_LITERAL) + +#endif /* __BIG_ENDIAN */ /* Define EISA controller register offsets */ -- cgit v1.2.3 From 7e680c22c0579f1db7b84a7b155755a2754f9557 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Mon, 30 Oct 2006 17:31:51 -0500 Subject: [PATCH] forcedeth: add mgmt unit support This patch adds support for the mgmt unit in certain chipsets. The MAC and the mgmt unit share the PHY and therefore proper intialization procedures are needed for them to maintain coexistense. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 151 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 134 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 87af5e497c51..5472d12122b4 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -110,6 +110,7 @@ * 0.55: 22 Mar 2006: Add flow control (pause frame). * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. + * 0.58: 30 Oct 2006: Added support for sideband management unit. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -126,7 +127,7 @@ #else #define DRIVERNAPI #endif -#define FORCEDETH_VERSION "0.57" +#define FORCEDETH_VERSION "0.58" #define DRV_NAME "forcedeth" #include @@ -174,6 +175,7 @@ #define DEV_HAS_PAUSEFRAME_TX 0x0200 /* device supports tx pause frames */ #define DEV_HAS_STATISTICS 0x0400 /* device supports hw statistics */ #define DEV_HAS_TEST_EXTENDED 0x0800 /* device supports extended diagnostic test */ +#define DEV_HAS_MGMT_UNIT 0x1000 /* device supports management unit */ enum { NvRegIrqStatus = 0x000, @@ -222,6 +224,15 @@ enum { #define NVREG_MAC_RESET_ASSERT 0x0F3 NvRegTransmitterControl = 0x084, #define NVREG_XMITCTL_START 0x01 +#define NVREG_XMITCTL_MGMT_ST 0x40000000 +#define NVREG_XMITCTL_SYNC_MASK 0x000f0000 +#define NVREG_XMITCTL_SYNC_NOT_READY 0x0 +#define NVREG_XMITCTL_SYNC_PHY_INIT 0x00040000 +#define NVREG_XMITCTL_MGMT_SEMA_MASK 0x00000f00 +#define NVREG_XMITCTL_MGMT_SEMA_FREE 0x0 +#define NVREG_XMITCTL_HOST_SEMA_MASK 0x0000f000 +#define NVREG_XMITCTL_HOST_SEMA_ACQ 0x0000f000 +#define NVREG_XMITCTL_HOST_LOADED 0x00004000 NvRegTransmitterStatus = 0x088, #define NVREG_XMITSTAT_BUSY 0x01 @@ -304,8 +315,8 @@ enum { #define NVREG_MIISTAT_LINKCHANGE 0x0008 #define NVREG_MIISTAT_MASK 0x000f #define NVREG_MIISTAT_MASK2 0x000f - NvRegUnknownSetupReg4 = 0x184, -#define NVREG_UNKSETUP4_VAL 8 + NvRegMIIMask = 0x184, +#define NVREG_MII_LINKCHANGE 0x0008 NvRegAdapterControl = 0x188, #define NVREG_ADAPTCTL_START 0x02 @@ -719,6 +730,7 @@ struct fe_priv { u32 driver_data; u32 register_size; int rx_csum; + u32 mac_in_use; void __iomem *base; @@ -4030,6 +4042,54 @@ static void nv_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) /* nothing to do */ }; +/* The mgmt unit and driver use a semaphore to access the phy during init */ +static int nv_mgmt_acquire_sema(struct net_device *dev) +{ + u8 __iomem *base = get_hwbase(dev); + int i; + u32 tx_ctrl, mgmt_sema; + + for (i = 0; i < 10; i++) { + mgmt_sema = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_SEMA_MASK; + if (mgmt_sema == NVREG_XMITCTL_MGMT_SEMA_FREE) + break; + msleep(500); + } + + if (mgmt_sema != NVREG_XMITCTL_MGMT_SEMA_FREE) + return 0; + + for (i = 0; i < 2; i++) { + tx_ctrl = readl(base + NvRegTransmitterControl); + tx_ctrl |= NVREG_XMITCTL_HOST_SEMA_ACQ; + writel(tx_ctrl, base + NvRegTransmitterControl); + + /* verify that semaphore was acquired */ + tx_ctrl = readl(base + NvRegTransmitterControl); + if (((tx_ctrl & NVREG_XMITCTL_HOST_SEMA_MASK) == NVREG_XMITCTL_HOST_SEMA_ACQ) && + ((tx_ctrl & NVREG_XMITCTL_MGMT_SEMA_MASK) == NVREG_XMITCTL_MGMT_SEMA_FREE)) + return 1; + else + udelay(50); + } + + return 0; +} + +/* Indicate to mgmt unit whether driver is loaded or not */ +static void nv_mgmt_driver_loaded(struct net_device *dev, int loaded) +{ + u8 __iomem *base = get_hwbase(dev); + u32 tx_ctrl; + + tx_ctrl = readl(base + NvRegTransmitterControl); + if (loaded) + tx_ctrl |= NVREG_XMITCTL_HOST_LOADED; + else + tx_ctrl &= ~NVREG_XMITCTL_HOST_LOADED; + writel(tx_ctrl, base + NvRegTransmitterControl); +} + static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); @@ -4085,7 +4145,7 @@ static int nv_open(struct net_device *dev) NV_SETUP5_DELAY, NV_SETUP5_DELAYMAX, KERN_INFO "open: SetupReg5, Bit 31 remained off\n"); - writel(0, base + NvRegUnknownSetupReg4); + writel(0, base + NvRegMIIMask); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); @@ -4111,7 +4171,7 @@ static int nv_open(struct net_device *dev) writel((np->phyaddr << NVREG_ADAPTCTL_PHYSHIFT)|NVREG_ADAPTCTL_PHYVALID|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl); writel(NVREG_MIISPEED_BIT8|NVREG_MIIDELAY, base + NvRegMIISpeed); - writel(NVREG_UNKSETUP4_VAL, base + NvRegUnknownSetupReg4); + writel(NVREG_MII_LINKCHANGE, base + NvRegMIIMask); if (np->wolenabled) writel(NVREG_WAKEUPFLAGS_ENABLE , base + NvRegWakeUpFlags); @@ -4230,6 +4290,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i u8 __iomem *base; int err, i; u32 powerstate, txreg; + u32 phystate_orig = 0, phystate; + int phyinitialized = 0; dev = alloc_etherdev(sizeof(struct fe_priv)); err = -ENOMEM; @@ -4514,6 +4576,48 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i np->need_linktimer = 0; } + /* clear phy state and temporarily halt phy interrupts */ + writel(0, base + NvRegMIIMask); + phystate = readl(base + NvRegAdapterControl); + if (phystate & NVREG_ADAPTCTL_RUNNING) { + phystate_orig = 1; + phystate &= ~NVREG_ADAPTCTL_RUNNING; + writel(phystate, base + NvRegAdapterControl); + } + writel(NVREG_MIISTAT_MASK, base + NvRegMIIStatus); + + if (id->driver_data & DEV_HAS_MGMT_UNIT) { + writel(0x1, base + 0x204); pci_push(base); + msleep(500); + /* management unit running on the mac? */ + np->mac_in_use = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_MGMT_ST; + if (np->mac_in_use) { + u32 mgmt_sync; + /* management unit setup the phy already? */ + mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK; + if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) { + if (!nv_mgmt_acquire_sema(dev)) { + for (i = 0; i < 5000; i++) { + msleep(1); + mgmt_sync = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_SYNC_MASK; + if (mgmt_sync == NVREG_XMITCTL_SYNC_NOT_READY) + continue; + if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) + phyinitialized = 1; + break; + } + } else { + /* we need to init the phy */ + } + } else if (mgmt_sync == NVREG_XMITCTL_SYNC_PHY_INIT) { + /* phy is inited by SMU */ + phyinitialized = 1; + } else { + /* we need to init the phy */ + } + } + } + /* find a suitable phy */ for (i = 1; i <= 32; i++) { int id1, id2; @@ -4545,8 +4649,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i goto out_error; } - /* reset it */ - phy_init(dev); + if (!phyinitialized) { + /* reset it */ + phy_init(dev); + } + + if (id->driver_data & DEV_HAS_MGMT_UNIT) { + nv_mgmt_driver_loaded(dev, 1); + } /* set default link speed settings */ np->linkspeed = NVREG_LINKSPEED_FORCE|NVREG_LINKSPEED_10; @@ -4565,6 +4675,10 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i return 0; out_error: + if (phystate_orig) + writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl); + if (np->mac_in_use) + nv_mgmt_driver_loaded(dev, 0); pci_set_drvdata(pci_dev, NULL); out_freering: free_rings(dev); @@ -4594,6 +4708,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) writel(np->orig_mac[0], base + NvRegMacAddrA); writel(np->orig_mac[1], base + NvRegMacAddrB); + if (np->mac_in_use) + nv_mgmt_driver_loaded(dev, 0); + /* free all structures */ free_rings(dev); iounmap(get_hwbase(dev)); @@ -4702,43 +4819,43 @@ static struct pci_device_id pci_tbl[] = { }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_14), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP55 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_15), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_VLAN|DEV_HAS_MSI|DEV_HAS_MSI_X|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_16), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_17), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_18), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP61 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_19), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, { /* MCP65 Ethernet Controller */ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), - .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED, + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, {0,}, }; -- cgit v1.2.3 From c5cf9101fefae32df654da5f0e736ffbe28aefdc Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Mon, 30 Oct 2006 17:32:01 -0500 Subject: [PATCH] forcedeth: add recoverable error support This patch adds support to recover from a previously fatal MAC error. In the past the MAC would be hung on an internal fatal error. On new chipsets, the MAC has the ability to enter a non-fatal state and allow the driver to re-init it. Signed-Off-By: Ayaz Abdulla Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 5472d12122b4..3b8087159b6d 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -111,6 +111,7 @@ * 0.56: 22 Mar 2006: Additional ethtool config and moduleparam support. * 0.57: 14 May 2006: Mac address set in probe/remove and order corrections. * 0.58: 30 Oct 2006: Added support for sideband management unit. + * 0.59: 30 Oct 2006: Added support for recoverable error. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -127,7 +128,7 @@ #else #define DRIVERNAPI #endif -#define FORCEDETH_VERSION "0.58" +#define FORCEDETH_VERSION "0.59" #define DRV_NAME "forcedeth" #include @@ -180,7 +181,7 @@ enum { NvRegIrqStatus = 0x000, #define NVREG_IRQSTAT_MIIEVENT 0x040 -#define NVREG_IRQSTAT_MASK 0x1ff +#define NVREG_IRQSTAT_MASK 0x81ff NvRegIrqMask = 0x004, #define NVREG_IRQ_RX_ERROR 0x0001 #define NVREG_IRQ_RX 0x0002 @@ -191,15 +192,16 @@ enum { #define NVREG_IRQ_LINK 0x0040 #define NVREG_IRQ_RX_FORCED 0x0080 #define NVREG_IRQ_TX_FORCED 0x0100 +#define NVREG_IRQ_RECOVER_ERROR 0x8000 #define NVREG_IRQMASK_THROUGHPUT 0x00df #define NVREG_IRQMASK_CPU 0x0040 #define NVREG_IRQ_TX_ALL (NVREG_IRQ_TX_ERR|NVREG_IRQ_TX_OK|NVREG_IRQ_TX_FORCED) #define NVREG_IRQ_RX_ALL (NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_RX_FORCED) -#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK) +#define NVREG_IRQ_OTHER (NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RECOVER_ERROR) #define NVREG_IRQ_UNKNOWN (~(NVREG_IRQ_RX_ERROR|NVREG_IRQ_RX|NVREG_IRQ_RX_NOBUF|NVREG_IRQ_TX_ERR| \ NVREG_IRQ_TX_OK|NVREG_IRQ_TIMER|NVREG_IRQ_LINK|NVREG_IRQ_RX_FORCED| \ - NVREG_IRQ_TX_FORCED)) + NVREG_IRQ_TX_FORCED|NVREG_IRQ_RECOVER_ERROR)) NvRegUnknownSetupReg6 = 0x008, #define NVREG_UNKSETUP6_VAL 3 @@ -718,6 +720,7 @@ struct fe_priv { unsigned int phy_model; u16 gigabit; int intr_test; + int recover_error; /* General data: RO fields */ dma_addr_t ring_addr; @@ -2455,6 +2458,23 @@ static irqreturn_t nv_nic_irq(int foo, void *data) printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", dev->name, events); } + if (unlikely(events & NVREG_IRQ_RECOVER_ERROR)) { + spin_lock(&np->lock); + /* disable interrupts on the nic */ + if (!(np->msi_flags & NV_MSI_X_ENABLED)) + writel(0, base + NvRegIrqMask); + else + writel(np->irqmask, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq = np->irqmask; + np->recover_error = 1; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock(&np->lock); + break; + } #ifdef CONFIG_FORCEDETH_NAPI if (events & NVREG_IRQ_RX_ALL) { netif_rx_schedule(dev); @@ -2685,6 +2705,20 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data) spin_unlock_irqrestore(&np->lock, flags); np->link_timeout = jiffies + LINK_TIMEOUT; } + if (events & NVREG_IRQ_RECOVER_ERROR) { + spin_lock_irq(&np->lock); + /* disable interrupts on the nic */ + writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); + pci_push(base); + + if (!np->in_shutdown) { + np->nic_poll_irq |= NVREG_IRQ_OTHER; + np->recover_error = 1; + mod_timer(&np->nic_poll, jiffies + POLL_WAIT); + } + spin_unlock_irq(&np->lock); + break; + } if (events & (NVREG_IRQ_UNKNOWN)) { printk(KERN_DEBUG "%s: received irq with unknown events 0x%x. Please report\n", dev->name, events); @@ -2914,6 +2948,42 @@ static void nv_do_nic_poll(unsigned long data) } np->nic_poll_irq = 0; + if (np->recover_error) { + np->recover_error = 0; + printk(KERN_INFO "forcedeth: MAC in recoverable error state\n"); + if (netif_running(dev)) { + netif_tx_lock_bh(dev); + spin_lock(&np->lock); + /* stop engines */ + nv_stop_rx(dev); + nv_stop_tx(dev); + nv_txrx_reset(dev); + /* drain rx queue */ + nv_drain_rx(dev); + nv_drain_tx(dev); + /* reinit driver view of the rx queue */ + set_bufsize(dev); + if (nv_init_ring(dev)) { + if (!np->in_shutdown) + mod_timer(&np->oom_kick, jiffies + OOM_REFILL); + } + /* reinit nic view of the rx queue */ + writel(np->rx_buf_sz, base + NvRegOffloadConfig); + setup_hw_rings(dev, NV_SETUP_RX_RING | NV_SETUP_TX_RING); + writel( ((np->rx_ring_size-1) << NVREG_RINGSZ_RXSHIFT) + ((np->tx_ring_size-1) << NVREG_RINGSZ_TXSHIFT), + base + NvRegRingSizes); + pci_push(base); + writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl); + pci_push(base); + + /* restart rx engine */ + nv_start_rx(dev); + nv_start_tx(dev); + spin_unlock(&np->lock); + netif_tx_unlock_bh(dev); + } + } + /* FIXME: Do we need synchronize_irq(dev->irq) here? */ writel(mask, base + NvRegIrqMask); -- cgit v1.2.3 From f4344848f8a7acbef2558dc5b89c62485f147033 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Mon, 6 Nov 2006 00:43:40 -0800 Subject: [PATCH] forcedeth: add support for new mcp67 device Add support for the new mcp67 device into forcedeth. Signed-off-by: Ayaz Abdulla Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 3b8087159b6d..439f41338291 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -4927,6 +4927,22 @@ static struct pci_device_id pci_tbl[] = { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, }, + { /* MCP67 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP67 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP67 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, + { /* MCP67 Ethernet Controller */ + PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), + .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT, + }, {0,}, }; -- cgit v1.2.3 From ac7468e923278cdcb202f8aa992d8f2776f8344c Mon Sep 17 00:00:00 2001 From: Komuro Date: Sun, 15 Oct 2006 10:08:00 +0900 Subject: [PATCH] network: pcnet_cs: remove the code to change the E8390_CMD register from ei_watchdog() Remove the code to change the E8390_CMD register from ei_watchdog(). The 8390-page is always 0 outside the spin_lock. Signed-off-by: komurojun-mbn@nifty.com Signed-off-by: Jeff Garzik --- drivers/net/pcmcia/pcnet_cs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 0c00d182e7fd..c51cc5d8789a 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -1096,7 +1096,6 @@ static void ei_watchdog(u_long arg) /* Check for pending interrupt with expired latency timer: with this, we can limp along even if the interrupt is blocked */ - outb_p(E8390_NODMA+E8390_PAGE0, nic_base + E8390_CMD); if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { if (!info->fast_poll) printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name); -- cgit v1.2.3 From e242040df1da94a9a3daa98ea5539e2b52502bb4 Mon Sep 17 00:00:00 2001 From: Jesse Huang Date: Fri, 20 Oct 2006 14:42:05 -0700 Subject: [PATCH] sundance: remove TxStartThresh and RxEarlyThresh For patent issue need to remove TxStartThresh and RxEarlyThresh. This patent is cut-through patent. If use this function, Tx will start to transmit after few data be move in to Tx FIFO. We are not allow to use those function in DFE530/DFE550/DFE580/DL10050/IP100/IP100A. It will decrease a little performance. Signed-off-by: Jesse Huang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 41c503d8bac4..be1faa020392 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -264,8 +264,6 @@ enum alta_offsets { ASICCtrl = 0x30, EEData = 0x34, EECtrl = 0x36, - TxStartThresh = 0x3c, - RxEarlyThresh = 0x3e, FlashAddr = 0x40, FlashData = 0x44, TxStatus = 0x46, @@ -1111,6 +1109,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) int tx_cnt; int tx_status; int handled = 0; + int i; do { @@ -1153,17 +1152,14 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) np->stats.tx_fifo_errors++; if (tx_status & 0x02) np->stats.tx_window_errors++; + /* ** This reset has been verified on ** DFE-580TX boards ! phdm@macqel.be. */ if (tx_status & 0x10) { /* TxUnderrun */ - unsigned short txthreshold; - - txthreshold = ioread16 (ioaddr + TxStartThresh); /* Restart Tx FIFO and transmitter */ sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); - iowrite16 (txthreshold, ioaddr + TxStartThresh); /* No need to reset the Tx pointer here */ } /* Restart the Tx. */ -- cgit v1.2.3 From 2109f89f3483ff5a05899385ee3fb04d779e9cce Mon Sep 17 00:00:00 2001 From: Jesse Huang Date: Fri, 20 Oct 2006 14:42:11 -0700 Subject: [PATCH] subdance: fix TX Pause bug (reset_tx, intr_handler) Fix TX Pause bug (reset_tx, intr_handler). When MaxCollisions occurred, need to re-enable Tx. But just after re-enable, MaxCollisions maybe occurred again and with TxStatusOverflow. This will cause driver can't check new MaxCollisions to re-enable Tx again, because TxStatusOverflow. For this reason, after re-enable Tx, we need to make sure Tx was actually enabled. Signed-off-by: Jesse Huang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index be1faa020392..91cd2f52e628 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1079,6 +1079,8 @@ reset_tx (struct net_device *dev) /* free all tx skbuff */ for (i = 0; i < TX_RING_SIZE; i++) { + np->tx_ring[i].next_desc = 0; + skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single(np->pci_dev, @@ -1094,6 +1096,10 @@ reset_tx (struct net_device *dev) } np->cur_tx = np->dirty_tx = 0; np->cur_task = 0; + + np->last_tx = 0; + iowrite8(127, ioaddr + TxDMAPollPeriod); + iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); return 0; } @@ -1162,8 +1168,14 @@ static irqreturn_t intr_handler(int irq, void *dev_instance) sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); /* No need to reset the Tx pointer here */ } - /* Restart the Tx. */ - iowrite16 (TxEnable, ioaddr + MACCtrl1); + /* Restart the Tx. Need to make sure tx enabled */ + i = 10; + do { + iowrite16(ioread16(ioaddr + MACCtrl1) | TxEnable, ioaddr + MACCtrl1); + if (ioread16(ioaddr + MACCtrl1) & TxEnabled) + break; + mdelay(1); + } while (--i); } /* Yup, this is a documentation bug. It cost me *hours*. */ iowrite16 (0, ioaddr + TxStatus); -- cgit v1.2.3 From 6b655529c3d817ed1b69cf2dd29e2c3ce5148a2b Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Mon, 16 Oct 2006 16:19:17 -0500 Subject: [PATCH] Fixed a number of bugs in the PHY Layer * genphy_update_link is now exported * Added a fix from ncase@xes-inc.com which changes forcing so it only updates the link. Otherwise, it never tries the lower values, since it is always overwriting the speed/duplex values with the current ones, rather than the intended ones. * Fixed a bug where bringing up a PHY with no link caused it to timeout, and enter forcing mode. Once in forcing mode, plugging in the link didn't autonegotiate. Now the AN state detects the lack of link, and enters the NO_LINK state. AN only times out if the link is up and AN fails * Cleaned up the PHY_AN case, reducing one level of indentation for the timeout code. Signed-off-by: Jeff Garzik --- drivers/net/phy/phy.c | 81 +++++++++++++++++++++----------------------- drivers/net/phy/phy_device.c | 1 + 2 files changed, 40 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 95f0419ba21e..88237bdb5255 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -713,60 +713,57 @@ static void phy_timer(unsigned long data) break; case PHY_AN: + err = phy_read_status(phydev); + + if (err < 0) + break; + + /* If the link is down, give up on + * negotiation for now */ + if (!phydev->link) { + phydev->state = PHY_NOLINK; + netif_carrier_off(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + break; + } + /* Check if negotiation is done. Break * if there's an error */ err = phy_aneg_done(phydev); if (err < 0) break; - /* If auto-negotiation is done, we change to - * either RUNNING, or NOLINK */ + /* If AN is done, we're running */ if (err > 0) { - err = phy_read_status(phydev); + phydev->state = PHY_RUNNING; + netif_carrier_on(phydev->attached_dev); + phydev->adjust_link(phydev->attached_dev); + + } else if (0 == phydev->link_timeout--) { + int idx; - if (err) + needs_aneg = 1; + /* If we have the magic_aneg bit, + * we try again */ + if (phydev->drv->flags & PHY_HAS_MAGICANEG) break; - if (phydev->link) { - phydev->state = PHY_RUNNING; - netif_carrier_on(phydev->attached_dev); - } else { - phydev->state = PHY_NOLINK; - netif_carrier_off(phydev->attached_dev); - } + /* The timer expired, and we still + * don't have a setting, so we try + * forcing it until we find one that + * works, starting from the fastest speed, + * and working our way down */ + idx = phy_find_valid(0, phydev->supported); - phydev->adjust_link(phydev->attached_dev); + phydev->speed = settings[idx].speed; + phydev->duplex = settings[idx].duplex; - } else if (0 == phydev->link_timeout--) { - /* The counter expired, so either we - * switch to forced mode, or the - * magic_aneg bit exists, and we try aneg - * again */ - if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) { - int idx; - - /* We'll start from the - * fastest speed, and work - * our way down */ - idx = phy_find_valid(0, - phydev->supported); - - phydev->speed = settings[idx].speed; - phydev->duplex = settings[idx].duplex; - - phydev->autoneg = AUTONEG_DISABLE; - phydev->state = PHY_FORCING; - phydev->link_timeout = - PHY_FORCE_TIMEOUT; - - pr_info("Trying %d/%s\n", - phydev->speed, - DUPLEX_FULL == - phydev->duplex ? - "FULL" : "HALF"); - } + phydev->autoneg = AUTONEG_DISABLE; - needs_aneg = 1; + pr_info("Trying %d/%s\n", phydev->speed, + DUPLEX_FULL == + phydev->duplex ? + "FULL" : "HALF"); } break; case PHY_NOLINK: @@ -782,7 +779,7 @@ static void phy_timer(unsigned long data) } break; case PHY_FORCING: - err = phy_read_status(phydev); + err = genphy_update_link(phydev); if (err) break; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 3bbd5e70c209..2a08b2b62c4c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -427,6 +427,7 @@ int genphy_update_link(struct phy_device *phydev) return 0; } +EXPORT_SYMBOL(genphy_update_link); /* genphy_read_status * -- cgit v1.2.3 From acd70c2bfddb52aee27a4864c160bea7f0d117e1 Mon Sep 17 00:00:00 2001 From: Jesse Huang Date: Fri, 20 Oct 2006 14:42:13 -0700 Subject: [PATCH] sundance: correct initial and close hardware step. Correct initial and close hardware step. In some embedded system down and up IP100A will cause DMA crash. We add some for safe down and up IP100A. Signed-off-by: Jesse Huang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 91cd2f52e628..fba64d39ba19 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -788,6 +788,7 @@ static int netdev_open(struct net_device *dev) { struct netdev_private *np = netdev_priv(dev); void __iomem *ioaddr = np->base; + unsigned long flags; int i; /* Do we need to reset the chip??? */ @@ -832,6 +833,10 @@ static int netdev_open(struct net_device *dev) iowrite8(0x01, ioaddr + DebugCtrl1); netif_start_queue(dev); + spin_lock_irqsave(&np->lock, flags); + reset_tx(dev); + spin_unlock_irqrestore(&np->lock, flags); + iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); if (netif_msg_ifup(np)) @@ -1651,6 +1656,9 @@ static int netdev_close(struct net_device *dev) /* Disable interrupts by clearing the interrupt mask. */ iowrite16(0x0000, ioaddr + IntrEnable); + /* Disable Rx and Tx DMA for safely release resource */ + iowrite32(0x500, ioaddr + DMACtrl); + /* Stop the chip's Tx and Rx processes. */ iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); -- cgit v1.2.3 From 1494a81410d8c53fa6c800be1e22b6b6f64180e6 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 7 Nov 2006 05:12:16 -0500 Subject: [netdrvr] netxen: build fixes Most contributed and Signed-off-by: Andrew Morton with some from me as well. Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_hdr.h | 1 - drivers/net/netxen/netxen_nic_hw.c | 2 +- drivers/net/netxen/netxen_nic_main.c | 9 ++++++--- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index c7d76c14f7be..0458db45e700 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -30,7 +30,6 @@ #ifndef _NETXEN_NIC_H_ #define _NETXEN_NIC_H_ -#include #include #include #include diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 965cf625ba4b..83bf28b372a4 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -32,7 +32,6 @@ #include #include -#include #include #include diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index c7d97054d05c..9603c635b054 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -351,7 +351,7 @@ void netxen_tso_check(struct netxen_adapter *adapter, ((skb->nh.iph)->ihl * sizeof(u32)) + ((skb->h.th)->doff * sizeof(u32)); desc->opcode = TX_TCP_LSO; - } else if (skb->ip_summed == CHECKSUM_HW) { + } else if (skb->ip_summed == CHECKSUM_COMPLETE) { if (skb->nh.iph->protocol == IPPROTO_TCP) { desc->opcode = TX_TCP_PKT; } else if (skb->nh.iph->protocol == IPPROTO_UDP) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index b54ea164e0ea..145bf47f0a8d 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -38,6 +38,9 @@ #include "netxen_nic_phan_reg.h" #include "netxen_nic_ioctl.h" +#include +#include + MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); @@ -66,7 +69,7 @@ static int netxen_nic_poll(struct net_device *dev, int *budget); #ifdef CONFIG_NET_POLL_CONTROLLER static void netxen_nic_poll_controller(struct net_device *netdev); #endif -static irqreturn_t netxen_intr(int irq, void *data, struct pt_regs *regs); +static irqreturn_t netxen_intr(int irq, void *data); /* PCI Device ID Table */ static struct pci_device_id netxen_pci_tbl[] __devinitdata = { @@ -969,7 +972,7 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) * @irq: interrupt number * data points to adapter stucture (which may be handling more than 1 port */ -irqreturn_t netxen_intr(int irq, void *data, struct pt_regs * regs) +irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter; struct netxen_port *port; @@ -1049,7 +1052,7 @@ static void netxen_nic_poll_controller(struct net_device *netdev) struct netxen_port *port = netdev_priv(netdev); struct netxen_adapter *adapter = port->adapter; disable_irq(adapter->irq); - netxen_intr(adapter->irq, adapter, NULL); + netxen_intr(adapter->irq, adapter); enable_irq(adapter->irq); } #endif -- cgit v1.2.3 From 08c3103a562ed83c4f9ac8fad6f5cb1ebb1f29a0 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 1 Nov 2006 18:11:18 -0600 Subject: [PATCH] bcm43xx: remove badness variable and related routine When the periodic work function in bcm43xx was converted for voluntary preemption to reduce latency, a new function was created to estimate the "badness" of each step, and this quantity was used to determine if preemption should be enabled when periodic work was undertaken. This concept was quite useful while debugging of periodic work was in progress. Now that this routine seems to be working correctly, it is time to simplify the code. This patch keeps the functionality intact, but simplifies the code. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 41 +++++------------------------ 1 file changed, 7 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index c6bd86889f1b..b199d32c37ea 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3209,55 +3209,27 @@ static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) static void do_periodic_work(struct bcm43xx_private *bcm) { - unsigned int state; - - state = bcm->periodic_state; - if (state % 8 == 0) + if (bcm->periodic_state % 8 == 0) bcm43xx_periodic_every120sec(bcm); - if (state % 4 == 0) + if (bcm->periodic_state % 4 == 0) bcm43xx_periodic_every60sec(bcm); - if (state % 2 == 0) + if (bcm->periodic_state % 2 == 0) bcm43xx_periodic_every30sec(bcm); - if (state % 1 == 0) - bcm43xx_periodic_every15sec(bcm); - bcm->periodic_state = state + 1; + bcm43xx_periodic_every15sec(bcm); schedule_delayed_work(&bcm->periodic_work, HZ * 15); } -/* Estimate a "Badness" value based on the periodic work - * state-machine state. "Badness" is worse (bigger), if the - * periodic work will take longer. - */ -static int estimate_periodic_work_badness(unsigned int state) -{ - int badness = 0; - - if (state % 8 == 0) /* every 120 sec */ - badness += 10; - if (state % 4 == 0) /* every 60 sec */ - badness += 5; - if (state % 2 == 0) /* every 30 sec */ - badness += 1; - if (state % 1 == 0) /* every 15 sec */ - badness += 1; - -#define BADNESS_LIMIT 4 - return badness; -} - static void bcm43xx_periodic_work_handler(void *d) { struct bcm43xx_private *bcm = d; struct net_device *net_dev = bcm->net_dev; unsigned long flags; u32 savedirqs = 0; - int badness; unsigned long orig_trans_start = 0; mutex_lock(&bcm->mutex); - badness = estimate_periodic_work_badness(bcm->periodic_state); - if (badness > BADNESS_LIMIT) { + if (unlikely(bcm->periodic_state % 4 == 0)) { /* Periodic work will take a long time, so we want it to * be preemtible. */ @@ -3289,7 +3261,7 @@ static void bcm43xx_periodic_work_handler(void *d) do_periodic_work(bcm); - if (badness > BADNESS_LIMIT) { + if (unlikely(bcm->periodic_state % 4 == 0)) { spin_lock_irqsave(&bcm->irq_lock, flags); tasklet_enable(&bcm->isr_tasklet); bcm43xx_interrupt_enable(bcm, savedirqs); @@ -3300,6 +3272,7 @@ static void bcm43xx_periodic_work_handler(void *d) net_dev->trans_start = orig_trans_start; } mmiowb(); + bcm->periodic_state++; spin_unlock_irqrestore(&bcm->irq_lock, flags); mutex_unlock(&bcm->mutex); } -- cgit v1.2.3 From 7f424ff4825adeae8d236fb3eafd699e6b2665e1 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 2 Nov 2006 21:56:52 -0600 Subject: [PATCH] bcm43xx: Remove useless core enable/disable messages In the softmac version of bcm43xx, the core scan logs whether each core is enabled or disabled. This information is useless as one of the next steps is to enable all cores. This patch removes this output from the log. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index b199d32c37ea..60a97450a6ed 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -2684,14 +2684,10 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) bcm->chip_id, bcm->chip_rev); dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); if (bcm->core_chipcommon.available) { - dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", - core_id, core_rev, core_vendor, - bcm43xx_core_enabled(bcm) ? "enabled" : "disabled"); - } - - if (bcm->core_chipcommon.available) + dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n", + core_id, core_rev, core_vendor); current_core = 1; - else + } else current_core = 0; for ( ; current_core < core_count; current_core++) { struct bcm43xx_coreinfo *core; @@ -2709,9 +2705,8 @@ static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) core_rev = (sb_id_hi & 0xF); core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x, %s\n", - current_core, core_id, core_rev, core_vendor, - bcm43xx_core_enabled(bcm) ? "enabled" : "disabled" ); + dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n", + current_core, core_id, core_rev, core_vendor); core = NULL; switch (core_id) { -- cgit v1.2.3 From 02e0e5e935cad59a2d30a004df9065e8697543e3 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 7 Nov 2006 20:53:48 -0500 Subject: [PATCH] wireless: clean-up some "check return code" warnings Clean-up some warnings from missing return code checks, mostly from calling pci_enable_device during a PCI resume. Signed-off-by: John W. Linville --- drivers/net/wireless/hostap/hostap_pci.c | 8 +++++++- drivers/net/wireless/ipw2100.c | 8 +++++++- drivers/net/wireless/ipw2200.c | 8 +++++++- drivers/net/wireless/orinoco_pci.h | 7 ++++++- drivers/net/wireless/prism54/islpci_hotplug.c | 20 ++++++++++++++++---- 5 files changed, 43 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index c2fa011be291..d1de9766c831 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -425,8 +425,14 @@ static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int prism2_pci_resume(struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); + int err; - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + dev->name); + return err; + } pci_restore_state(pdev); prism2_hw_config(dev, 0); if (netif_running(dev)) { diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 5bf4d4119c3d..3bc6be9d20f8 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -6423,6 +6423,7 @@ static int ipw2100_resume(struct pci_dev *pci_dev) { struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); struct net_device *dev = priv->net_dev; + int err; u32 val; if (IPW2100_PM_DISABLED) @@ -6433,7 +6434,12 @@ static int ipw2100_resume(struct pci_dev *pci_dev) IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name); pci_set_power_state(pci_dev, PCI_D0); - pci_enable_device(pci_dev); + err = pci_enable_device(pci_dev); + if (err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + dev->name); + return err; + } pci_restore_state(pci_dev); /* diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 72120d5c2f7b..c692d01a76ca 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -11727,12 +11727,18 @@ static int ipw_pci_resume(struct pci_dev *pdev) { struct ipw_priv *priv = pci_get_drvdata(pdev); struct net_device *dev = priv->net_dev; + int err; u32 val; printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name); pci_set_power_state(pdev, PCI_D0); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + dev->name); + return err; + } pci_restore_state(pdev); /* diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h index be1abea4b64f..f4e5e06760c1 100644 --- a/drivers/net/wireless/orinoco_pci.h +++ b/drivers/net/wireless/orinoco_pci.h @@ -60,7 +60,12 @@ static int orinoco_pci_resume(struct pci_dev *pdev) int err; pci_set_power_state(pdev, 0); - pci_enable_device(pdev); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + dev->name); + return err; + } pci_restore_state(pdev); err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index f6354b1cbc28..e0bca3abdf68 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -170,14 +170,15 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* enable MWI */ - pci_set_mwi(pdev); + if (pci_set_mwi(pdev)) + goto do_pci_release_regions; /* setup the network device interface and its structure */ if (!(ndev = islpci_setup(pdev))) { /* error configuring the driver as a network device */ printk(KERN_ERR "%s: could not configure network device\n", DRV_NAME); - goto do_pci_release_regions; + goto do_pci_clear_mwi; } priv = netdev_priv(ndev); @@ -207,6 +208,8 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_drvdata(pdev, NULL); free_netdev(ndev); priv = NULL; + do_pci_clear_mwi: + pci_clear_mwi(pdev); do_pci_release_regions: pci_release_regions(pdev); do_pci_disable_device: @@ -254,6 +257,8 @@ prism54_remove(struct pci_dev *pdev) free_netdev(ndev); priv = NULL; + pci_clear_mwi(pdev); + pci_release_regions(pdev); pci_disable_device(pdev); @@ -287,12 +292,19 @@ prism54_resume(struct pci_dev *pdev) { struct net_device *ndev = pci_get_drvdata(pdev); islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; - BUG_ON(!priv); + int err; - pci_enable_device(pdev); + BUG_ON(!priv); printk(KERN_NOTICE "%s: got resume request\n", ndev->name); + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s: pci_enable_device failed on resume\n", + ndev->name); + return err; + } + pci_restore_state(pdev); /* alright let's go into the PREBOOT state */ -- cgit v1.2.3 From f2d71c2d800e68f158a5949e38b23f5140948548 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Tue, 7 Nov 2006 13:27:02 +0300 Subject: [PATCH] add netpoll support for gianfar: respin The patch inlined below adds NET_POLL_CONTROLLER support for gianfar network driver, slightly modified wrt the comments from Andy Fleming. drivers/net/gianfar.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) Signed-off-by: Vitaly Wool Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index a06d8d1aaceb..6bf18c82083d 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -133,6 +133,9 @@ static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr); #ifdef CONFIG_GFAR_NAPI static int gfar_poll(struct net_device *dev, int *budget); #endif +#ifdef CONFIG_NET_POLL_CONTROLLER +static void gfar_netpoll(struct net_device *dev); +#endif int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length); static void gfar_vlan_rx_register(struct net_device *netdev, @@ -259,6 +262,9 @@ static int gfar_probe(struct platform_device *pdev) #ifdef CONFIG_GFAR_NAPI dev->poll = gfar_poll; dev->weight = GFAR_DEV_WEIGHT; +#endif +#ifdef CONFIG_NET_POLL_CONTROLLER + dev->poll_controller = gfar_netpoll; #endif dev->stop = gfar_close; dev->get_stats = gfar_get_stats; @@ -1536,6 +1542,33 @@ static int gfar_poll(struct net_device *dev, int *budget) } #endif +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + * Polling 'interrupt' - used by things like netconsole to send skbs + * without having to re-enable interrupts. It's not called while + * the interrupt routine is executing. + */ +static void gfar_netpoll(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + + /* If the device has multiple interrupts, run tx/rx */ + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) { + disable_irq(priv->interruptTransmit); + disable_irq(priv->interruptReceive); + disable_irq(priv->interruptError); + gfar_interrupt(priv->interruptTransmit, dev); + enable_irq(priv->interruptError); + enable_irq(priv->interruptReceive); + enable_irq(priv->interruptTransmit); + } else { + disable_irq(priv->interruptTransmit); + gfar_interrupt(priv->interruptTransmit, dev); + enable_irq(priv->interruptTransmit); + } +} +#endif + /* The interrupt handler for devices with one interrupt */ static irqreturn_t gfar_interrupt(int irq, void *dev_id) { -- cgit v1.2.3 From 95d21ff4c64592bdee7f1af2925145bed849c994 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 8 Nov 2006 00:11:29 -0600 Subject: [PATCH] Add support for Marvell 88e1111S and 88e1145 This patch requires the new support for configurable PHY interfaces. Changes include: * New support for 88e1145 * New support for 88e111s * Fixing 88e1101 driver to not match non-88e1101 PHYs * Increases in feature support across Marvell PHY product line * Fixes a bunch of whitespace issues found by Lindent Signed-off-by: Andrew Fleming Signed-off-by: Jeff Garzik --- drivers/net/phy/marvell.c | 156 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 144 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 0ad253282d0d..5320ab9fe018 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -43,6 +43,19 @@ #define MII_M1011_IMASK_INIT 0x6400 #define MII_M1011_IMASK_CLEAR 0x0000 +#define MII_M1011_PHY_SCR 0x10 +#define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060 + +#define MII_M1145_PHY_EXT_CR 0x14 +#define MII_M1145_RGMII_RX_DELAY 0x0080 +#define MII_M1145_RGMII_TX_DELAY 0x0002 + +#define M1145_DEV_FLAGS_RESISTANCE 0x00000001 + +#define MII_M1111_PHY_LED_CONTROL 0x18 +#define MII_M1111_PHY_LED_DIRECT 0x4100 +#define MII_M1111_PHY_LED_COMBINE 0x411c + MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); MODULE_LICENSE("GPL"); @@ -64,7 +77,7 @@ static int marvell_config_intr(struct phy_device *phydev) { int err; - if(phydev->interrupts == PHY_INTERRUPT_ENABLED) + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); else err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); @@ -104,34 +117,153 @@ static int marvell_config_aneg(struct phy_device *phydev) if (err < 0) return err; + err = phy_write(phydev, MII_M1011_PHY_SCR, + MII_M1011_PHY_SCR_AUTO_CROSS); + if (err < 0) + return err; + + err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, + MII_M1111_PHY_LED_DIRECT); + if (err < 0) + return err; err = genphy_config_aneg(phydev); return err; } +static int m88e1145_config_init(struct phy_device *phydev) +{ + int err; + + /* Take care of errata E0 & E1 */ + err = phy_write(phydev, 0x1d, 0x001b); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x418f); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x0016); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0xa2da); + if (err < 0) + return err; + + if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { + int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); + if (temp < 0) + return temp; + + temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); + + err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); + if (err < 0) + return err; + + if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { + err = phy_write(phydev, 0x1d, 0x0012); + if (err < 0) + return err; + + temp = phy_read(phydev, 0x1e); + if (temp < 0) + return temp; + + temp &= 0xf03f; + temp |= 2 << 9; /* 36 ohm */ + temp |= 2 << 6; /* 39 ohm */ + + err = phy_write(phydev, 0x1e, temp); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1d, 0x3); + if (err < 0) + return err; + + err = phy_write(phydev, 0x1e, 0x8000); + if (err < 0) + return err; + } + } + + return 0; +} static struct phy_driver m88e1101_driver = { - .phy_id = 0x01410c00, - .phy_id_mask = 0xffffff00, - .name = "Marvell 88E1101", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = { .owner = THIS_MODULE,}, + .phy_id = 0x01410c60, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1101", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, +}; + +static struct phy_driver m88e1111s_driver = { + .phy_id = 0x01410cc0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1111", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, +}; + +static struct phy_driver m88e1145_driver = { + .phy_id = 0x01410cd0, + .phy_id_mask = 0xfffffff0, + .name = "Marvell 88E1145", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_init = &m88e1145_config_init, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = {.owner = THIS_MODULE,}, }; static int __init marvell_init(void) { - return phy_driver_register(&m88e1101_driver); + int ret; + + ret = phy_driver_register(&m88e1101_driver); + if (ret) + return ret; + + ret = phy_driver_register(&m88e1111s_driver); + if (ret) + goto err1111s; + + ret = phy_driver_register(&m88e1145_driver); + if (ret) + goto err1145; + + return 0; + + err1145: + phy_driver_unregister(&m88e1111s_driver); + err1111s: + phy_driver_unregister(&m88e1101_driver); + return ret; } static void __exit marvell_exit(void) { phy_driver_unregister(&m88e1101_driver); + phy_driver_unregister(&m88e1111s_driver); + phy_driver_unregister(&m88e1145_driver); } module_init(marvell_init); -- cgit v1.2.3 From d0bb53e102e10cc90de50953531a163d95da1e07 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Tue, 14 Nov 2006 10:35:03 -0500 Subject: e1000 linkage fix ia64: drivers/built-in.o(.text+0xd9a72): In function `e1000_xmit_frame': : undefined reference to `csum_ipv6_magic' Cc: Auke Kok Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/e1000/e1000_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index a2f1464ba49d..7a0828869ecf 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -27,6 +27,7 @@ *******************************************************************************/ #include "e1000.h" +#include char e1000_driver_name[] = "e1000"; static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -- cgit v1.2.3 From 31f817e9d6f325b10a316bb84237cae3739487ed Mon Sep 17 00:00:00 2001 From: Jesse Huang Date: Wed, 8 Nov 2006 19:49:12 -0800 Subject: [PATCH] sundance: solve host error problem in low performance embedded system when continune down and up Solve host error problem in low performance embedded system when continune down and up. It will cause IP100A DMA TargetAbort. So we need more safe process to up and down IP100A with wait hardware completely stop and software cur_tx/ dirty_tx/cur_task/last_tx be clear. Signed-off-by: Jesse Huang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index fba64d39ba19..02679e688c4c 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1642,6 +1642,14 @@ static int netdev_close(struct net_device *dev) struct sk_buff *skb; int i; + /* Wait and kill tasklet */ + tasklet_kill(&np->rx_tasklet); + tasklet_kill(&np->tx_tasklet); + np->cur_tx = 0; + np->dirty_tx = 0; + np->cur_task = 0; + np->last_tx = 0; + netif_stop_queue(dev); if (netif_msg_ifdown(np)) { @@ -1662,9 +1670,20 @@ static int netdev_close(struct net_device *dev) /* Stop the chip's Tx and Rx processes. */ iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); - /* Wait and kill tasklet */ - tasklet_kill(&np->rx_tasklet); - tasklet_kill(&np->tx_tasklet); + for (i = 2000; i > 0; i--) { + if ((ioread32(ioaddr + DMACtrl) & 0xc000) == 0) + break; + mdelay(1); + } + + iowrite16(GlobalReset | DMAReset | FIFOReset | NetworkReset, + ioaddr +ASICCtrl + 2); + + for (i = 2000; i > 0; i--) { + if ((ioread16(ioaddr + ASICCtrl +2) & ResetBusy) == 0) + break; + mdelay(1); + } #ifdef __i386__ if (netif_msg_hw(np)) { @@ -1702,6 +1721,7 @@ static int netdev_close(struct net_device *dev) } } for (i = 0; i < TX_RING_SIZE; i++) { + np->tx_ring[i].next_desc = 0; skb = np->tx_skbuff[i]; if (skb) { pci_unmap_single(np->pci_dev, -- cgit v1.2.3 From 5e123b844a1cbd4ec258cd37847ce4d57fa308c1 Mon Sep 17 00:00:00 2001 From: Zang Roy-r61911 Date: Wed, 8 Nov 2006 19:49:13 -0800 Subject: [PATCH] Add tsi108/9 On Chip Ethernet device driver support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tsi108/9 on chip Ethernet controller driver support. The driver code collects the feedback of previous posting form the mailing list and gives the update. MPC7448HPC2 platform in arch/powerpc uses tsi108 bridge. The following is a brief description of the Ethernet controller: The Tsi108/9 Ethernet Controller connects Switch Fabric to two independent Gigabit Ethernet ports,E0 and E1. It uses a single Management interface to manage the two physical connection devices (PHYs). Each Ethernet port has its own statistics monitor that tracks and reports key interface statistics. Each port supports a 256-entry hash table for address filtering. In addition, each port is bridged to the Switch Fabric through a 2-Kbyte transmit FIFO and a 4-Kbyte Receive FIFO. Each Ethernet port also has a pair of internal Ethernet DMA channels to support the transmit and receive data flows. The Ethernet DMA channels use descriptors set up in memory, the memory map of the device, and access via the Switch Fabric. The Ethernet Controller’s DMA arbiter handles arbitration for the Switch Fabric. The Controller also has a register bus interface for register accesses and status monitor control. The PMD (Physical Media Device) interface operates in MII, GMII, or TBI modes. The MII mode is used for connecting with 10 or 100 Mbit/s PMDs. The GMII and TBI modes are used to connect with Gigabit PMDs. Internal data flows to and from the Ethernet Controller through the Switch Fabric. Each Ethernet port uses its transmit and receive DMA channels to manage data flows through buffer descriptors that are predefined by the system (the descriptors can exist anywhere in the system memory map). These descriptors are data structures that point to buffers filled with data ready to transmit over Ethernet, or they point to empty buffers ready to receive data from Ethernet. Signed-off-by: Alexandre Bounine Signed-off-by: Roy Zang Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 8 + drivers/net/Makefile | 1 + drivers/net/tsi108_eth.c | 1708 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/tsi108_eth.h | 365 ++++++++++ 4 files changed, 2082 insertions(+) create mode 100644 drivers/net/tsi108_eth.c create mode 100644 drivers/net/tsi108_eth.h (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 112d4cd5c66c..05167253b254 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2251,6 +2251,14 @@ config SPIDER_NET This driver supports the Gigabit Ethernet chips present on the Cell Processor-Based Blades from IBM. +config TSI108_ETH + tristate "Tundra TSI108 gigabit Ethernet support" + depends on TSI108_BRIDGE + help + This driver supports Tundra TSI108 gigabit Ethernet ports. + To compile this driver as a module, choose M here: the module + will be called tsi108_eth. + config GIANFAR tristate "Gianfar Ethernet" depends on 85xx || 83xx || PPC_86xx diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7889e4ca1844..789306ca7936 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -108,6 +108,7 @@ obj-$(CONFIG_B44) += b44.o obj-$(CONFIG_FORCEDETH) += forcedeth.o obj-$(CONFIG_NE_H8300) += ne-h8300.o +obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o obj-$(CONFIG_QLA3XXX) += qla3xxx.o diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c new file mode 100644 index 000000000000..893808ab3742 --- /dev/null +++ b/drivers/net/tsi108_eth.c @@ -0,0 +1,1708 @@ +/******************************************************************************* + + Copyright(c) 2006 Tundra Semiconductor Corporation. + + 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. + +*******************************************************************************/ + +/* This driver is based on the driver code originally developed + * for the Intel IOC80314 (ForestLake) Gigabit Ethernet by + * scott.wood@timesys.com * Copyright (C) 2003 TimeSys Corporation + * + * Currently changes from original version are: + * - porting to Tsi108-based platform and kernel 2.6 (kong.lai@tundra.com) + * - modifications to handle two ports independently and support for + * additional PHY devices (alexandre.bounine@tundra.com) + * - Get hardware information from platform device. (tie-fei.zang@freescale.com) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "tsi108_eth.h" + +#define MII_READ_DELAY 10000 /* max link wait time in msec */ + +#define TSI108_RXRING_LEN 256 + +/* NOTE: The driver currently does not support receiving packets + * larger than the buffer size, so don't decrease this (unless you + * want to add such support). + */ +#define TSI108_RXBUF_SIZE 1536 + +#define TSI108_TXRING_LEN 256 + +#define TSI108_TX_INT_FREQ 64 + +/* Check the phy status every half a second. */ +#define CHECK_PHY_INTERVAL (HZ/2) + +static int tsi108_init_one(struct platform_device *pdev); +static int tsi108_ether_remove(struct platform_device *pdev); + +struct tsi108_prv_data { + void __iomem *regs; /* Base of normal regs */ + void __iomem *phyregs; /* Base of register bank used for PHY access */ + + unsigned int phy; /* Index of PHY for this interface */ + unsigned int irq_num; + unsigned int id; + + struct timer_list timer;/* Timer that triggers the check phy function */ + unsigned int rxtail; /* Next entry in rxring to read */ + unsigned int rxhead; /* Next entry in rxring to give a new buffer */ + unsigned int rxfree; /* Number of free, allocated RX buffers */ + + unsigned int rxpending; /* Non-zero if there are still descriptors + * to be processed from a previous descriptor + * interrupt condition that has been cleared */ + + unsigned int txtail; /* Next TX descriptor to check status on */ + unsigned int txhead; /* Next TX descriptor to use */ + + /* Number of free TX descriptors. This could be calculated from + * rxhead and rxtail if one descriptor were left unused to disambiguate + * full and empty conditions, but it's simpler to just keep track + * explicitly. */ + + unsigned int txfree; + + unsigned int phy_ok; /* The PHY is currently powered on. */ + + /* PHY status (duplex is 1 for half, 2 for full, + * so that the default 0 indicates that neither has + * yet been configured). */ + + unsigned int link_up; + unsigned int speed; + unsigned int duplex; + + tx_desc *txring; + rx_desc *rxring; + struct sk_buff *txskbs[TSI108_TXRING_LEN]; + struct sk_buff *rxskbs[TSI108_RXRING_LEN]; + + dma_addr_t txdma, rxdma; + + /* txlock nests in misclock and phy_lock */ + + spinlock_t txlock, misclock; + + /* stats is used to hold the upper bits of each hardware counter, + * and tmpstats is used to hold the full values for returning + * to the caller of get_stats(). They must be separate in case + * an overflow interrupt occurs before the stats are consumed. + */ + + struct net_device_stats stats; + struct net_device_stats tmpstats; + + /* These stats are kept separate in hardware, thus require individual + * fields for handling carry. They are combined in get_stats. + */ + + unsigned long rx_fcs; /* Add to rx_frame_errors */ + unsigned long rx_short_fcs; /* Add to rx_frame_errors */ + unsigned long rx_long_fcs; /* Add to rx_frame_errors */ + unsigned long rx_underruns; /* Add to rx_length_errors */ + unsigned long rx_overruns; /* Add to rx_length_errors */ + + unsigned long tx_coll_abort; /* Add to tx_aborted_errors/collisions */ + unsigned long tx_pause_drop; /* Add to tx_aborted_errors */ + + unsigned long mc_hash[16]; + u32 msg_enable; /* debug message level */ + struct mii_if_info mii_if; + unsigned int init_media; +}; + +/* Structure for a device driver */ + +static struct platform_driver tsi_eth_driver = { + .probe = tsi108_init_one, + .remove = tsi108_ether_remove, + .driver = { + .name = "tsi-ethernet", + }, +}; + +static void tsi108_timed_checker(unsigned long dev_ptr); + +static void dump_eth_one(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + + printk("Dumping %s...\n", dev->name); + printk("intstat %x intmask %x phy_ok %d" + " link %d speed %d duplex %d\n", + TSI_READ(TSI108_EC_INTSTAT), + TSI_READ(TSI108_EC_INTMASK), data->phy_ok, + data->link_up, data->speed, data->duplex); + + printk("TX: head %d, tail %d, free %d, stat %x, estat %x, err %x\n", + data->txhead, data->txtail, data->txfree, + TSI_READ(TSI108_EC_TXSTAT), + TSI_READ(TSI108_EC_TXESTAT), + TSI_READ(TSI108_EC_TXERR)); + + printk("RX: head %d, tail %d, free %d, stat %x," + " estat %x, err %x, pending %d\n\n", + data->rxhead, data->rxtail, data->rxfree, + TSI_READ(TSI108_EC_RXSTAT), + TSI_READ(TSI108_EC_RXESTAT), + TSI_READ(TSI108_EC_RXERR), data->rxpending); +} + +/* Synchronization is needed between the thread and up/down events. + * Note that the PHY is accessed through the same registers for both + * interfaces, so this can't be made interface-specific. + */ + +static DEFINE_SPINLOCK(phy_lock); + +static int tsi108_read_mii(struct tsi108_prv_data *data, int reg) +{ + unsigned i; + + TSI_WRITE_PHY(TSI108_MAC_MII_ADDR, + (data->phy << TSI108_MAC_MII_ADDR_PHY) | + (reg << TSI108_MAC_MII_ADDR_REG)); + TSI_WRITE_PHY(TSI108_MAC_MII_CMD, 0); + TSI_WRITE_PHY(TSI108_MAC_MII_CMD, TSI108_MAC_MII_CMD_READ); + for (i = 0; i < 100; i++) { + if (!(TSI_READ_PHY(TSI108_MAC_MII_IND) & + (TSI108_MAC_MII_IND_NOTVALID | TSI108_MAC_MII_IND_BUSY))) + break; + udelay(10); + } + + if (i == 100) + return 0xffff; + else + return (TSI_READ_PHY(TSI108_MAC_MII_DATAIN)); +} + +static void tsi108_write_mii(struct tsi108_prv_data *data, + int reg, u16 val) +{ + unsigned i = 100; + TSI_WRITE_PHY(TSI108_MAC_MII_ADDR, + (data->phy << TSI108_MAC_MII_ADDR_PHY) | + (reg << TSI108_MAC_MII_ADDR_REG)); + TSI_WRITE_PHY(TSI108_MAC_MII_DATAOUT, val); + while (i--) { + if(!(TSI_READ_PHY(TSI108_MAC_MII_IND) & + TSI108_MAC_MII_IND_BUSY)) + break; + udelay(10); + } +} + +static int tsi108_mdio_read(struct net_device *dev, int addr, int reg) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + return tsi108_read_mii(data, reg); +} + +static void tsi108_mdio_write(struct net_device *dev, int addr, int reg, int val) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + tsi108_write_mii(data, reg, val); +} + +static inline void tsi108_write_tbi(struct tsi108_prv_data *data, + int reg, u16 val) +{ + unsigned i = 1000; + TSI_WRITE(TSI108_MAC_MII_ADDR, + (0x1e << TSI108_MAC_MII_ADDR_PHY) + | (reg << TSI108_MAC_MII_ADDR_REG)); + TSI_WRITE(TSI108_MAC_MII_DATAOUT, val); + while(i--) { + if(!(TSI_READ(TSI108_MAC_MII_IND) & TSI108_MAC_MII_IND_BUSY)) + return; + udelay(10); + } + printk(KERN_ERR "%s function time out \n", __FUNCTION__); +} + +static int mii_speed(struct mii_if_info *mii) +{ + int advert, lpa, val, media; + int lpa2 = 0; + int speed; + + if (!mii_link_ok(mii)) + return 0; + + val = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_BMSR); + if ((val & BMSR_ANEGCOMPLETE) == 0) + return 0; + + advert = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_ADVERTISE); + lpa = (*mii->mdio_read) (mii->dev, mii->phy_id, MII_LPA); + media = mii_nway_result(advert & lpa); + + if (mii->supports_gmii) + lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000); + + speed = lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 : + (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 100 : 10); + return speed; +} + +static void tsi108_check_phy(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 mac_cfg2_reg, portctrl_reg; + u32 duplex; + u32 speed; + unsigned long flags; + + /* Do a dummy read, as for some reason the first read + * after a link becomes up returns link down, even if + * it's been a while since the link came up. + */ + + spin_lock_irqsave(&phy_lock, flags); + + if (!data->phy_ok) + goto out; + + tsi108_read_mii(data, MII_BMSR); + + duplex = mii_check_media(&data->mii_if, netif_msg_link(data), data->init_media); + data->init_media = 0; + + if (netif_carrier_ok(dev)) { + + speed = mii_speed(&data->mii_if); + + if ((speed != data->speed) || duplex) { + + mac_cfg2_reg = TSI_READ(TSI108_MAC_CFG2); + portctrl_reg = TSI_READ(TSI108_EC_PORTCTRL); + + mac_cfg2_reg &= ~TSI108_MAC_CFG2_IFACE_MASK; + + if (speed == 1000) { + mac_cfg2_reg |= TSI108_MAC_CFG2_GIG; + portctrl_reg &= ~TSI108_EC_PORTCTRL_NOGIG; + } else { + mac_cfg2_reg |= TSI108_MAC_CFG2_NOGIG; + portctrl_reg |= TSI108_EC_PORTCTRL_NOGIG; + } + + data->speed = speed; + + if (data->mii_if.full_duplex) { + mac_cfg2_reg |= TSI108_MAC_CFG2_FULLDUPLEX; + portctrl_reg &= ~TSI108_EC_PORTCTRL_HALFDUPLEX; + data->duplex = 2; + } else { + mac_cfg2_reg &= ~TSI108_MAC_CFG2_FULLDUPLEX; + portctrl_reg |= TSI108_EC_PORTCTRL_HALFDUPLEX; + data->duplex = 1; + } + + TSI_WRITE(TSI108_MAC_CFG2, mac_cfg2_reg); + TSI_WRITE(TSI108_EC_PORTCTRL, portctrl_reg); + + if (data->link_up == 0) { + /* The manual says it can take 3-4 usecs for the speed change + * to take effect. + */ + udelay(5); + + spin_lock(&data->txlock); + if (is_valid_ether_addr(dev->dev_addr) && data->txfree) + netif_wake_queue(dev); + + data->link_up = 1; + spin_unlock(&data->txlock); + } + } + + } else { + if (data->link_up == 1) { + netif_stop_queue(dev); + data->link_up = 0; + printk(KERN_NOTICE "%s : link is down\n", dev->name); + } + + goto out; + } + + +out: + spin_unlock_irqrestore(&phy_lock, flags); +} + +static inline void +tsi108_stat_carry_one(int carry, int carry_bit, int carry_shift, + unsigned long *upper) +{ + if (carry & carry_bit) + *upper += carry_shift; +} + +static void tsi108_stat_carry(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 carry1, carry2; + + spin_lock_irq(&data->misclock); + + carry1 = TSI_READ(TSI108_STAT_CARRY1); + carry2 = TSI_READ(TSI108_STAT_CARRY2); + + TSI_WRITE(TSI108_STAT_CARRY1, carry1); + TSI_WRITE(TSI108_STAT_CARRY2, carry2); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXBYTES, + TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXPKTS, + TSI108_STAT_RXPKTS_CARRY, + &data->stats.rx_packets); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFCS, + TSI108_STAT_RXFCS_CARRY, &data->rx_fcs); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXMCAST, + TSI108_STAT_RXMCAST_CARRY, + &data->stats.multicast); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXALIGN, + TSI108_STAT_RXALIGN_CARRY, + &data->stats.rx_frame_errors); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXLENGTH, + TSI108_STAT_RXLENGTH_CARRY, + &data->stats.rx_length_errors); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXRUNT, + TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJUMBO, + TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXFRAG, + TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXJABBER, + TSI108_STAT_RXJABBER_CARRY, &data->rx_long_fcs); + + tsi108_stat_carry_one(carry1, TSI108_STAT_CARRY1_RXDROP, + TSI108_STAT_RXDROP_CARRY, + &data->stats.rx_missed_errors); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXBYTES, + TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPKTS, + TSI108_STAT_TXPKTS_CARRY, + &data->stats.tx_packets); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXDEF, + TSI108_STAT_TXEXDEF_CARRY, + &data->stats.tx_aborted_errors); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXEXCOL, + TSI108_STAT_TXEXCOL_CARRY, &data->tx_coll_abort); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXTCOL, + TSI108_STAT_TXTCOL_CARRY, + &data->stats.collisions); + + tsi108_stat_carry_one(carry2, TSI108_STAT_CARRY2_TXPAUSE, + TSI108_STAT_TXPAUSEDROP_CARRY, + &data->tx_pause_drop); + + spin_unlock_irq(&data->misclock); +} + +/* Read a stat counter atomically with respect to carries. + * data->misclock must be held. + */ +static inline unsigned long +tsi108_read_stat(struct tsi108_prv_data * data, int reg, int carry_bit, + int carry_shift, unsigned long *upper) +{ + int carryreg; + unsigned long val; + + if (reg < 0xb0) + carryreg = TSI108_STAT_CARRY1; + else + carryreg = TSI108_STAT_CARRY2; + + again: + val = TSI_READ(reg) | *upper; + + /* Check to see if it overflowed, but the interrupt hasn't + * been serviced yet. If so, handle the carry here, and + * try again. + */ + + if (unlikely(TSI_READ(carryreg) & carry_bit)) { + *upper += carry_shift; + TSI_WRITE(carryreg, carry_bit); + goto again; + } + + return val; +} + +static struct net_device_stats *tsi108_get_stats(struct net_device *dev) +{ + unsigned long excol; + + struct tsi108_prv_data *data = netdev_priv(dev); + spin_lock_irq(&data->misclock); + + data->tmpstats.rx_packets = + tsi108_read_stat(data, TSI108_STAT_RXPKTS, + TSI108_STAT_CARRY1_RXPKTS, + TSI108_STAT_RXPKTS_CARRY, &data->stats.rx_packets); + + data->tmpstats.tx_packets = + tsi108_read_stat(data, TSI108_STAT_TXPKTS, + TSI108_STAT_CARRY2_TXPKTS, + TSI108_STAT_TXPKTS_CARRY, &data->stats.tx_packets); + + data->tmpstats.rx_bytes = + tsi108_read_stat(data, TSI108_STAT_RXBYTES, + TSI108_STAT_CARRY1_RXBYTES, + TSI108_STAT_RXBYTES_CARRY, &data->stats.rx_bytes); + + data->tmpstats.tx_bytes = + tsi108_read_stat(data, TSI108_STAT_TXBYTES, + TSI108_STAT_CARRY2_TXBYTES, + TSI108_STAT_TXBYTES_CARRY, &data->stats.tx_bytes); + + data->tmpstats.multicast = + tsi108_read_stat(data, TSI108_STAT_RXMCAST, + TSI108_STAT_CARRY1_RXMCAST, + TSI108_STAT_RXMCAST_CARRY, &data->stats.multicast); + + excol = tsi108_read_stat(data, TSI108_STAT_TXEXCOL, + TSI108_STAT_CARRY2_TXEXCOL, + TSI108_STAT_TXEXCOL_CARRY, + &data->tx_coll_abort); + + data->tmpstats.collisions = + tsi108_read_stat(data, TSI108_STAT_TXTCOL, + TSI108_STAT_CARRY2_TXTCOL, + TSI108_STAT_TXTCOL_CARRY, &data->stats.collisions); + + data->tmpstats.collisions += excol; + + data->tmpstats.rx_length_errors = + tsi108_read_stat(data, TSI108_STAT_RXLENGTH, + TSI108_STAT_CARRY1_RXLENGTH, + TSI108_STAT_RXLENGTH_CARRY, + &data->stats.rx_length_errors); + + data->tmpstats.rx_length_errors += + tsi108_read_stat(data, TSI108_STAT_RXRUNT, + TSI108_STAT_CARRY1_RXRUNT, + TSI108_STAT_RXRUNT_CARRY, &data->rx_underruns); + + data->tmpstats.rx_length_errors += + tsi108_read_stat(data, TSI108_STAT_RXJUMBO, + TSI108_STAT_CARRY1_RXJUMBO, + TSI108_STAT_RXJUMBO_CARRY, &data->rx_overruns); + + data->tmpstats.rx_frame_errors = + tsi108_read_stat(data, TSI108_STAT_RXALIGN, + TSI108_STAT_CARRY1_RXALIGN, + TSI108_STAT_RXALIGN_CARRY, + &data->stats.rx_frame_errors); + + data->tmpstats.rx_frame_errors += + tsi108_read_stat(data, TSI108_STAT_RXFCS, + TSI108_STAT_CARRY1_RXFCS, TSI108_STAT_RXFCS_CARRY, + &data->rx_fcs); + + data->tmpstats.rx_frame_errors += + tsi108_read_stat(data, TSI108_STAT_RXFRAG, + TSI108_STAT_CARRY1_RXFRAG, + TSI108_STAT_RXFRAG_CARRY, &data->rx_short_fcs); + + data->tmpstats.rx_missed_errors = + tsi108_read_stat(data, TSI108_STAT_RXDROP, + TSI108_STAT_CARRY1_RXDROP, + TSI108_STAT_RXDROP_CARRY, + &data->stats.rx_missed_errors); + + /* These three are maintained by software. */ + data->tmpstats.rx_fifo_errors = data->stats.rx_fifo_errors; + data->tmpstats.rx_crc_errors = data->stats.rx_crc_errors; + + data->tmpstats.tx_aborted_errors = + tsi108_read_stat(data, TSI108_STAT_TXEXDEF, + TSI108_STAT_CARRY2_TXEXDEF, + TSI108_STAT_TXEXDEF_CARRY, + &data->stats.tx_aborted_errors); + + data->tmpstats.tx_aborted_errors += + tsi108_read_stat(data, TSI108_STAT_TXPAUSEDROP, + TSI108_STAT_CARRY2_TXPAUSE, + TSI108_STAT_TXPAUSEDROP_CARRY, + &data->tx_pause_drop); + + data->tmpstats.tx_aborted_errors += excol; + + data->tmpstats.tx_errors = data->tmpstats.tx_aborted_errors; + data->tmpstats.rx_errors = data->tmpstats.rx_length_errors + + data->tmpstats.rx_crc_errors + + data->tmpstats.rx_frame_errors + + data->tmpstats.rx_fifo_errors + data->tmpstats.rx_missed_errors; + + spin_unlock_irq(&data->misclock); + return &data->tmpstats; +} + +static void tsi108_restart_rx(struct tsi108_prv_data * data, struct net_device *dev) +{ + TSI_WRITE(TSI108_EC_RXQ_PTRHIGH, + TSI108_EC_RXQ_PTRHIGH_VALID); + + TSI_WRITE(TSI108_EC_RXCTRL, TSI108_EC_RXCTRL_GO + | TSI108_EC_RXCTRL_QUEUE0); +} + +static void tsi108_restart_tx(struct tsi108_prv_data * data) +{ + TSI_WRITE(TSI108_EC_TXQ_PTRHIGH, + TSI108_EC_TXQ_PTRHIGH_VALID); + + TSI_WRITE(TSI108_EC_TXCTRL, TSI108_EC_TXCTRL_IDLEINT | + TSI108_EC_TXCTRL_GO | TSI108_EC_TXCTRL_QUEUE0); +} + +/* txlock must be held by caller, with IRQs disabled, and + * with permission to re-enable them when the lock is dropped. + */ +static void tsi108_complete_tx(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + int tx; + struct sk_buff *skb; + int release = 0; + + while (!data->txfree || data->txhead != data->txtail) { + tx = data->txtail; + + if (data->txring[tx].misc & TSI108_TX_OWN) + break; + + skb = data->txskbs[tx]; + + if (!(data->txring[tx].misc & TSI108_TX_OK)) + printk("%s: bad tx packet, misc %x\n", + dev->name, data->txring[tx].misc); + + data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN; + data->txfree++; + + if (data->txring[tx].misc & TSI108_TX_EOF) { + dev_kfree_skb_any(skb); + release++; + } + } + + if (release) { + if (is_valid_ether_addr(dev->dev_addr) && data->link_up) + netif_wake_queue(dev); + } +} + +static int tsi108_send_packet(struct sk_buff * skb, struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + int frags = skb_shinfo(skb)->nr_frags + 1; + int i; + + if (!data->phy_ok && net_ratelimit()) + printk(KERN_ERR "%s: Transmit while PHY is down!\n", dev->name); + + if (!data->link_up) { + printk(KERN_ERR "%s: Transmit while link is down!\n", + dev->name); + netif_stop_queue(dev); + return NETDEV_TX_BUSY; + } + + if (data->txfree < MAX_SKB_FRAGS + 1) { + netif_stop_queue(dev); + + if (net_ratelimit()) + printk(KERN_ERR "%s: Transmit with full tx ring!\n", + dev->name); + return NETDEV_TX_BUSY; + } + + if (data->txfree - frags < MAX_SKB_FRAGS + 1) { + netif_stop_queue(dev); + } + + spin_lock_irq(&data->txlock); + + for (i = 0; i < frags; i++) { + int misc = 0; + int tx = data->txhead; + + /* This is done to mark every TSI108_TX_INT_FREQ tx buffers with + * the interrupt bit. TX descriptor-complete interrupts are + * enabled when the queue fills up, and masked when there is + * still free space. This way, when saturating the outbound + * link, the tx interrupts are kept to a reasonable level. + * When the queue is not full, reclamation of skbs still occurs + * as new packets are transmitted, or on a queue-empty + * interrupt. + */ + + if ((tx % TSI108_TX_INT_FREQ == 0) && + ((TSI108_TXRING_LEN - data->txfree) >= TSI108_TX_INT_FREQ)) + misc = TSI108_TX_INT; + + data->txskbs[tx] = skb; + + if (i == 0) { + data->txring[tx].buf0 = dma_map_single(NULL, skb->data, + skb->len - skb->data_len, DMA_TO_DEVICE); + data->txring[tx].len = skb->len - skb->data_len; + misc |= TSI108_TX_SOF; + } else { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i - 1]; + + data->txring[tx].buf0 = + dma_map_page(NULL, frag->page, frag->page_offset, + frag->size, DMA_TO_DEVICE); + data->txring[tx].len = frag->size; + } + + if (i == frags - 1) + misc |= TSI108_TX_EOF; + + if (netif_msg_pktdata(data)) { + int i; + printk("%s: Tx Frame contents (%d)\n", dev->name, + skb->len); + for (i = 0; i < skb->len; i++) + printk(" %2.2x", skb->data[i]); + printk(".\n"); + } + data->txring[tx].misc = misc | TSI108_TX_OWN; + + data->txhead = (data->txhead + 1) % TSI108_TXRING_LEN; + data->txfree--; + } + + tsi108_complete_tx(dev); + + /* This must be done after the check for completed tx descriptors, + * so that the tail pointer is correct. + */ + + if (!(TSI_READ(TSI108_EC_TXSTAT) & TSI108_EC_TXSTAT_QUEUE0)) + tsi108_restart_tx(data); + + spin_unlock_irq(&data->txlock); + return NETDEV_TX_OK; +} + +static int tsi108_complete_rx(struct net_device *dev, int budget) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + int done = 0; + + while (data->rxfree && done != budget) { + int rx = data->rxtail; + struct sk_buff *skb; + + if (data->rxring[rx].misc & TSI108_RX_OWN) + break; + + skb = data->rxskbs[rx]; + data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN; + data->rxfree--; + done++; + + if (data->rxring[rx].misc & TSI108_RX_BAD) { + spin_lock_irq(&data->misclock); + + if (data->rxring[rx].misc & TSI108_RX_CRC) + data->stats.rx_crc_errors++; + if (data->rxring[rx].misc & TSI108_RX_OVER) + data->stats.rx_fifo_errors++; + + spin_unlock_irq(&data->misclock); + + dev_kfree_skb_any(skb); + continue; + } + if (netif_msg_pktdata(data)) { + int i; + printk("%s: Rx Frame contents (%d)\n", + dev->name, data->rxring[rx].len); + for (i = 0; i < data->rxring[rx].len; i++) + printk(" %2.2x", skb->data[i]); + printk(".\n"); + } + + skb->dev = dev; + skb_put(skb, data->rxring[rx].len); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + dev->last_rx = jiffies; + } + + return done; +} + +static int tsi108_refill_rx(struct net_device *dev, int budget) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + int done = 0; + + while (data->rxfree != TSI108_RXRING_LEN && done != budget) { + int rx = data->rxhead; + struct sk_buff *skb; + + data->rxskbs[rx] = skb = dev_alloc_skb(TSI108_RXBUF_SIZE + 2); + if (!skb) + break; + + skb_reserve(skb, 2); /* Align the data on a 4-byte boundary. */ + + data->rxring[rx].buf0 = dma_map_single(NULL, skb->data, + TSI108_RX_SKB_SIZE, + DMA_FROM_DEVICE); + + /* Sometimes the hardware sets blen to zero after packet + * reception, even though the manual says that it's only ever + * modified by the driver. + */ + + data->rxring[rx].blen = TSI108_RX_SKB_SIZE; + data->rxring[rx].misc = TSI108_RX_OWN | TSI108_RX_INT; + + data->rxhead = (data->rxhead + 1) % TSI108_RXRING_LEN; + data->rxfree++; + done++; + } + + if (done != 0 && !(TSI_READ(TSI108_EC_RXSTAT) & + TSI108_EC_RXSTAT_QUEUE0)) + tsi108_restart_rx(data, dev); + + return done; +} + +static int tsi108_poll(struct net_device *dev, int *budget) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 estat = TSI_READ(TSI108_EC_RXESTAT); + u32 intstat = TSI_READ(TSI108_EC_INTSTAT); + int total_budget = min(*budget, dev->quota); + int num_received = 0, num_filled = 0, budget_used; + + intstat &= TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH | + TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | TSI108_INT_RXWAIT; + + TSI_WRITE(TSI108_EC_RXESTAT, estat); + TSI_WRITE(TSI108_EC_INTSTAT, intstat); + + if (data->rxpending || (estat & TSI108_EC_RXESTAT_Q0_DESCINT)) + num_received = tsi108_complete_rx(dev, total_budget); + + /* This should normally fill no more slots than the number of + * packets received in tsi108_complete_rx(). The exception + * is when we previously ran out of memory for RX SKBs. In that + * case, it's helpful to obey the budget, not only so that the + * CPU isn't hogged, but so that memory (which may still be low) + * is not hogged by one device. + * + * A work unit is considered to be two SKBs to allow us to catch + * up when the ring has shrunk due to out-of-memory but we're + * still removing the full budget's worth of packets each time. + */ + + if (data->rxfree < TSI108_RXRING_LEN) + num_filled = tsi108_refill_rx(dev, total_budget * 2); + + if (intstat & TSI108_INT_RXERROR) { + u32 err = TSI_READ(TSI108_EC_RXERR); + TSI_WRITE(TSI108_EC_RXERR, err); + + if (err) { + if (net_ratelimit()) + printk(KERN_DEBUG "%s: RX error %x\n", + dev->name, err); + + if (!(TSI_READ(TSI108_EC_RXSTAT) & + TSI108_EC_RXSTAT_QUEUE0)) + tsi108_restart_rx(data, dev); + } + } + + if (intstat & TSI108_INT_RXOVERRUN) { + spin_lock_irq(&data->misclock); + data->stats.rx_fifo_errors++; + spin_unlock_irq(&data->misclock); + } + + budget_used = max(num_received, num_filled / 2); + + *budget -= budget_used; + dev->quota -= budget_used; + + if (budget_used != total_budget) { + data->rxpending = 0; + netif_rx_complete(dev); + + TSI_WRITE(TSI108_EC_INTMASK, + TSI_READ(TSI108_EC_INTMASK) + & ~(TSI108_INT_RXQUEUE0 + | TSI108_INT_RXTHRESH | + TSI108_INT_RXOVERRUN | + TSI108_INT_RXERROR | + TSI108_INT_RXWAIT)); + + /* IRQs are level-triggered, so no need to re-check */ + return 0; + } else { + data->rxpending = 1; + } + + return 1; +} + +static void tsi108_rx_int(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + + /* A race could cause dev to already be scheduled, so it's not an + * error if that happens (and interrupts shouldn't be re-masked, + * because that can cause harmful races, if poll has already + * unmasked them but not cleared LINK_STATE_SCHED). + * + * This can happen if this code races with tsi108_poll(), which masks + * the interrupts after tsi108_irq_one() read the mask, but before + * netif_rx_schedule is called. It could also happen due to calls + * from tsi108_check_rxring(). + */ + + if (netif_rx_schedule_prep(dev)) { + /* Mask, rather than ack, the receive interrupts. The ack + * will happen in tsi108_poll(). + */ + + TSI_WRITE(TSI108_EC_INTMASK, + TSI_READ(TSI108_EC_INTMASK) | + TSI108_INT_RXQUEUE0 + | TSI108_INT_RXTHRESH | + TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR | + TSI108_INT_RXWAIT); + __netif_rx_schedule(dev); + } else { + if (!netif_running(dev)) { + /* This can happen if an interrupt occurs while the + * interface is being brought down, as the START + * bit is cleared before the stop function is called. + * + * In this case, the interrupts must be masked, or + * they will continue indefinitely. + * + * There's a race here if the interface is brought down + * and then up in rapid succession, as the device could + * be made running after the above check and before + * the masking below. This will only happen if the IRQ + * thread has a lower priority than the task brining + * up the interface. Fixing this race would likely + * require changes in generic code. + */ + + TSI_WRITE(TSI108_EC_INTMASK, + TSI_READ + (TSI108_EC_INTMASK) | + TSI108_INT_RXQUEUE0 | + TSI108_INT_RXTHRESH | + TSI108_INT_RXOVERRUN | + TSI108_INT_RXERROR | + TSI108_INT_RXWAIT); + } + } +} + +/* If the RX ring has run out of memory, try periodically + * to allocate some more, as otherwise poll would never + * get called (apart from the initial end-of-queue condition). + * + * This is called once per second (by default) from the thread. + */ + +static void tsi108_check_rxring(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + + /* A poll is scheduled, as opposed to caling tsi108_refill_rx + * directly, so as to keep the receive path single-threaded + * (and thus not needing a lock). + */ + + if (netif_running(dev) && data->rxfree < TSI108_RXRING_LEN / 4) + tsi108_rx_int(dev); +} + +static void tsi108_tx_int(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 estat = TSI_READ(TSI108_EC_TXESTAT); + + TSI_WRITE(TSI108_EC_TXESTAT, estat); + TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_TXQUEUE0 | + TSI108_INT_TXIDLE | TSI108_INT_TXERROR); + if (estat & TSI108_EC_TXESTAT_Q0_ERR) { + u32 err = TSI_READ(TSI108_EC_TXERR); + TSI_WRITE(TSI108_EC_TXERR, err); + + if (err && net_ratelimit()) + printk(KERN_ERR "%s: TX error %x\n", dev->name, err); + } + + if (estat & (TSI108_EC_TXESTAT_Q0_DESCINT | TSI108_EC_TXESTAT_Q0_EOQ)) { + spin_lock(&data->txlock); + tsi108_complete_tx(dev); + spin_unlock(&data->txlock); + } +} + + +static irqreturn_t tsi108_irq(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct tsi108_prv_data *data = netdev_priv(dev); + u32 stat = TSI_READ(TSI108_EC_INTSTAT); + + if (!(stat & TSI108_INT_ANY)) + return IRQ_NONE; /* Not our interrupt */ + + stat &= ~TSI_READ(TSI108_EC_INTMASK); + + if (stat & (TSI108_INT_TXQUEUE0 | TSI108_INT_TXIDLE | + TSI108_INT_TXERROR)) + tsi108_tx_int(dev); + if (stat & (TSI108_INT_RXQUEUE0 | TSI108_INT_RXTHRESH | + TSI108_INT_RXWAIT | TSI108_INT_RXOVERRUN | + TSI108_INT_RXERROR)) + tsi108_rx_int(dev); + + if (stat & TSI108_INT_SFN) { + if (net_ratelimit()) + printk(KERN_DEBUG "%s: SFN error\n", dev->name); + TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_SFN); + } + + if (stat & TSI108_INT_STATCARRY) { + tsi108_stat_carry(dev); + TSI_WRITE(TSI108_EC_INTSTAT, TSI108_INT_STATCARRY); + } + + return IRQ_HANDLED; +} + +static void tsi108_stop_ethernet(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + int i = 1000; + /* Disable all TX and RX queues ... */ + TSI_WRITE(TSI108_EC_TXCTRL, 0); + TSI_WRITE(TSI108_EC_RXCTRL, 0); + + /* ...and wait for them to become idle */ + while(i--) { + if(!(TSI_READ(TSI108_EC_TXSTAT) & TSI108_EC_TXSTAT_ACTIVE)) + break; + udelay(10); + } + i = 1000; + while(i--){ + if(!(TSI_READ(TSI108_EC_RXSTAT) & TSI108_EC_RXSTAT_ACTIVE)) + return; + udelay(10); + } + printk(KERN_ERR "%s function time out \n", __FUNCTION__); +} + +static void tsi108_reset_ether(struct tsi108_prv_data * data) +{ + TSI_WRITE(TSI108_MAC_CFG1, TSI108_MAC_CFG1_SOFTRST); + udelay(100); + TSI_WRITE(TSI108_MAC_CFG1, 0); + + TSI_WRITE(TSI108_EC_PORTCTRL, TSI108_EC_PORTCTRL_STATRST); + udelay(100); + TSI_WRITE(TSI108_EC_PORTCTRL, + TSI_READ(TSI108_EC_PORTCTRL) & + ~TSI108_EC_PORTCTRL_STATRST); + + TSI_WRITE(TSI108_EC_TXCFG, TSI108_EC_TXCFG_RST); + udelay(100); + TSI_WRITE(TSI108_EC_TXCFG, + TSI_READ(TSI108_EC_TXCFG) & + ~TSI108_EC_TXCFG_RST); + + TSI_WRITE(TSI108_EC_RXCFG, TSI108_EC_RXCFG_RST); + udelay(100); + TSI_WRITE(TSI108_EC_RXCFG, + TSI_READ(TSI108_EC_RXCFG) & + ~TSI108_EC_RXCFG_RST); + + TSI_WRITE(TSI108_MAC_MII_MGMT_CFG, + TSI_READ(TSI108_MAC_MII_MGMT_CFG) | + TSI108_MAC_MII_MGMT_RST); + udelay(100); + TSI_WRITE(TSI108_MAC_MII_MGMT_CFG, + (TSI_READ(TSI108_MAC_MII_MGMT_CFG) & + ~(TSI108_MAC_MII_MGMT_RST | + TSI108_MAC_MII_MGMT_CLK)) | 0x07); +} + +static int tsi108_get_mac(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 word1 = TSI_READ(TSI108_MAC_ADDR1); + u32 word2 = TSI_READ(TSI108_MAC_ADDR2); + + /* Note that the octets are reversed from what the manual says, + * producing an even weirder ordering... + */ + if (word2 == 0 && word1 == 0) { + dev->dev_addr[0] = 0x00; + dev->dev_addr[1] = 0x06; + dev->dev_addr[2] = 0xd2; + dev->dev_addr[3] = 0x00; + dev->dev_addr[4] = 0x00; + if (0x8 == data->phy) + dev->dev_addr[5] = 0x01; + else + dev->dev_addr[5] = 0x02; + + word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24); + + word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) | + (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24); + + TSI_WRITE(TSI108_MAC_ADDR1, word1); + TSI_WRITE(TSI108_MAC_ADDR2, word2); + } else { + dev->dev_addr[0] = (word2 >> 16) & 0xff; + dev->dev_addr[1] = (word2 >> 24) & 0xff; + dev->dev_addr[2] = (word1 >> 0) & 0xff; + dev->dev_addr[3] = (word1 >> 8) & 0xff; + dev->dev_addr[4] = (word1 >> 16) & 0xff; + dev->dev_addr[5] = (word1 >> 24) & 0xff; + } + + if (!is_valid_ether_addr(dev->dev_addr)) { + printk("KERN_ERR: word1: %08x, word2: %08x\n", word1, word2); + return -EINVAL; + } + + return 0; +} + +static int tsi108_set_mac(struct net_device *dev, void *addr) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 word1, word2; + int i; + + if (!is_valid_ether_addr(addr)) + return -EINVAL; + + for (i = 0; i < 6; i++) + /* +2 is for the offset of the HW addr type */ + dev->dev_addr[i] = ((unsigned char *)addr)[i + 2]; + + word2 = (dev->dev_addr[0] << 16) | (dev->dev_addr[1] << 24); + + word1 = (dev->dev_addr[2] << 0) | (dev->dev_addr[3] << 8) | + (dev->dev_addr[4] << 16) | (dev->dev_addr[5] << 24); + + spin_lock_irq(&data->misclock); + TSI_WRITE(TSI108_MAC_ADDR1, word1); + TSI_WRITE(TSI108_MAC_ADDR2, word2); + spin_lock(&data->txlock); + + if (data->txfree && data->link_up) + netif_wake_queue(dev); + + spin_unlock(&data->txlock); + spin_unlock_irq(&data->misclock); + return 0; +} + +/* Protected by dev->xmit_lock. */ +static void tsi108_set_rx_mode(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 rxcfg = TSI_READ(TSI108_EC_RXCFG); + + if (dev->flags & IFF_PROMISC) { + rxcfg &= ~(TSI108_EC_RXCFG_UC_HASH | TSI108_EC_RXCFG_MC_HASH); + rxcfg |= TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE; + goto out; + } + + rxcfg &= ~(TSI108_EC_RXCFG_UFE | TSI108_EC_RXCFG_MFE); + + if (dev->flags & IFF_ALLMULTI || dev->mc_count) { + int i; + struct dev_mc_list *mc = dev->mc_list; + rxcfg |= TSI108_EC_RXCFG_MFE | TSI108_EC_RXCFG_MC_HASH; + + memset(data->mc_hash, 0, sizeof(data->mc_hash)); + + while (mc) { + u32 hash, crc; + + if (mc->dmi_addrlen == 6) { + crc = ether_crc(6, mc->dmi_addr); + hash = crc >> 23; + + __set_bit(hash, &data->mc_hash[0]); + } else { + printk(KERN_ERR + "%s: got multicast address of length %d " + "instead of 6.\n", dev->name, + mc->dmi_addrlen); + } + + mc = mc->next; + } + + TSI_WRITE(TSI108_EC_HASHADDR, + TSI108_EC_HASHADDR_AUTOINC | + TSI108_EC_HASHADDR_MCAST); + + for (i = 0; i < 16; i++) { + /* The manual says that the hardware may drop + * back-to-back writes to the data register. + */ + udelay(1); + TSI_WRITE(TSI108_EC_HASHDATA, + data->mc_hash[i]); + } + } + + out: + TSI_WRITE(TSI108_EC_RXCFG, rxcfg); +} + +static void tsi108_init_phy(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + u32 i = 0; + u16 phyval = 0; + unsigned long flags; + + spin_lock_irqsave(&phy_lock, flags); + + tsi108_write_mii(data, MII_BMCR, BMCR_RESET); + while (i--){ + if(!(tsi108_read_mii(data, MII_BMCR) & BMCR_RESET)) + break; + udelay(10); + } + if (i == 0) + printk(KERN_ERR "%s function time out \n", __FUNCTION__); + +#if (TSI108_PHY_TYPE == PHY_BCM54XX) /* Broadcom BCM54xx PHY */ + tsi108_write_mii(data, 0x09, 0x0300); + tsi108_write_mii(data, 0x10, 0x1020); + tsi108_write_mii(data, 0x1c, 0x8c00); +#endif + + tsi108_write_mii(data, + MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); + while (tsi108_read_mii(data, MII_BMCR) & BMCR_ANRESTART) + cpu_relax(); + + /* Set G/MII mode and receive clock select in TBI control #2. The + * second port won't work if this isn't done, even though we don't + * use TBI mode. + */ + + tsi108_write_tbi(data, 0x11, 0x30); + + /* FIXME: It seems to take more than 2 back-to-back reads to the + * PHY_STAT register before the link up status bit is set. + */ + + data->link_up = 1; + + while (!((phyval = tsi108_read_mii(data, MII_BMSR)) & + BMSR_LSTATUS)) { + if (i++ > (MII_READ_DELAY / 10)) { + data->link_up = 0; + break; + } + spin_unlock_irqrestore(&phy_lock, flags); + msleep(10); + spin_lock_irqsave(&phy_lock, flags); + } + + printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval); + data->phy_ok = 1; + data->init_media = 1; + spin_unlock_irqrestore(&phy_lock, flags); +} + +static void tsi108_kill_phy(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned long flags; + + spin_lock_irqsave(&phy_lock, flags); + tsi108_write_mii(data, MII_BMCR, BMCR_PDOWN); + data->phy_ok = 0; + spin_unlock_irqrestore(&phy_lock, flags); +} + +static int tsi108_open(struct net_device *dev) +{ + int i; + struct tsi108_prv_data *data = netdev_priv(dev); + unsigned int rxring_size = TSI108_RXRING_LEN * sizeof(rx_desc); + unsigned int txring_size = TSI108_TXRING_LEN * sizeof(tx_desc); + + i = request_irq(data->irq_num, tsi108_irq, 0, dev->name, dev); + if (i != 0) { + printk(KERN_ERR "tsi108_eth%d: Could not allocate IRQ%d.\n", + data->id, data->irq_num); + return i; + } else { + dev->irq = data->irq_num; + printk(KERN_NOTICE + "tsi108_open : Port %d Assigned IRQ %d to %s\n", + data->id, dev->irq, dev->name); + } + + data->rxring = dma_alloc_coherent(NULL, rxring_size, + &data->rxdma, GFP_KERNEL); + + if (!data->rxring) { + printk(KERN_DEBUG + "TSI108_ETH: failed to allocate memory for rxring!\n"); + return -ENOMEM; + } else { + memset(data->rxring, 0, rxring_size); + } + + data->txring = dma_alloc_coherent(NULL, txring_size, + &data->txdma, GFP_KERNEL); + + if (!data->txring) { + printk(KERN_DEBUG + "TSI108_ETH: failed to allocate memory for txring!\n"); + pci_free_consistent(0, rxring_size, data->rxring, data->rxdma); + return -ENOMEM; + } else { + memset(data->txring, 0, txring_size); + } + + for (i = 0; i < TSI108_RXRING_LEN; i++) { + data->rxring[i].next0 = data->rxdma + (i + 1) * sizeof(rx_desc); + data->rxring[i].blen = TSI108_RXBUF_SIZE; + data->rxring[i].vlan = 0; + } + + data->rxring[TSI108_RXRING_LEN - 1].next0 = data->rxdma; + + data->rxtail = 0; + data->rxhead = 0; + + for (i = 0; i < TSI108_RXRING_LEN; i++) { + struct sk_buff *skb = dev_alloc_skb(TSI108_RXBUF_SIZE + NET_IP_ALIGN); + + if (!skb) { + /* Bah. No memory for now, but maybe we'll get + * some more later. + * For now, we'll live with the smaller ring. + */ + printk(KERN_WARNING + "%s: Could only allocate %d receive skb(s).\n", + dev->name, i); + data->rxhead = i; + break; + } + + data->rxskbs[i] = skb; + /* Align the payload on a 4-byte boundary */ + skb_reserve(skb, 2); + data->rxskbs[i] = skb; + data->rxring[i].buf0 = virt_to_phys(data->rxskbs[i]->data); + data->rxring[i].misc = TSI108_RX_OWN | TSI108_RX_INT; + } + + data->rxfree = i; + TSI_WRITE(TSI108_EC_RXQ_PTRLOW, data->rxdma); + + for (i = 0; i < TSI108_TXRING_LEN; i++) { + data->txring[i].next0 = data->txdma + (i + 1) * sizeof(tx_desc); + data->txring[i].misc = 0; + } + + data->txring[TSI108_TXRING_LEN - 1].next0 = data->txdma; + data->txtail = 0; + data->txhead = 0; + data->txfree = TSI108_TXRING_LEN; + TSI_WRITE(TSI108_EC_TXQ_PTRLOW, data->txdma); + tsi108_init_phy(dev); + + setup_timer(&data->timer, tsi108_timed_checker, (unsigned long)dev); + mod_timer(&data->timer, jiffies + 1); + + tsi108_restart_rx(data, dev); + + TSI_WRITE(TSI108_EC_INTSTAT, ~0); + + TSI_WRITE(TSI108_EC_INTMASK, + ~(TSI108_INT_TXQUEUE0 | TSI108_INT_RXERROR | + TSI108_INT_RXTHRESH | TSI108_INT_RXQUEUE0 | + TSI108_INT_RXOVERRUN | TSI108_INT_RXWAIT | + TSI108_INT_SFN | TSI108_INT_STATCARRY)); + + TSI_WRITE(TSI108_MAC_CFG1, + TSI108_MAC_CFG1_RXEN | TSI108_MAC_CFG1_TXEN); + netif_start_queue(dev); + return 0; +} + +static int tsi108_close(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + + netif_stop_queue(dev); + + del_timer_sync(&data->timer); + + tsi108_stop_ethernet(dev); + tsi108_kill_phy(dev); + TSI_WRITE(TSI108_EC_INTMASK, ~0); + TSI_WRITE(TSI108_MAC_CFG1, 0); + + /* Check for any pending TX packets, and drop them. */ + + while (!data->txfree || data->txhead != data->txtail) { + int tx = data->txtail; + struct sk_buff *skb; + skb = data->txskbs[tx]; + data->txtail = (data->txtail + 1) % TSI108_TXRING_LEN; + data->txfree++; + dev_kfree_skb(skb); + } + + synchronize_irq(data->irq_num); + free_irq(data->irq_num, dev); + + /* Discard the RX ring. */ + + while (data->rxfree) { + int rx = data->rxtail; + struct sk_buff *skb; + + skb = data->rxskbs[rx]; + data->rxtail = (data->rxtail + 1) % TSI108_RXRING_LEN; + data->rxfree--; + dev_kfree_skb(skb); + } + + dma_free_coherent(0, + TSI108_RXRING_LEN * sizeof(rx_desc), + data->rxring, data->rxdma); + dma_free_coherent(0, + TSI108_TXRING_LEN * sizeof(tx_desc), + data->txring, data->txdma); + + return 0; +} + +static void tsi108_init_mac(struct net_device *dev) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + + TSI_WRITE(TSI108_MAC_CFG2, TSI108_MAC_CFG2_DFLT_PREAMBLE | + TSI108_MAC_CFG2_PADCRC); + + TSI_WRITE(TSI108_EC_TXTHRESH, + (192 << TSI108_EC_TXTHRESH_STARTFILL) | + (192 << TSI108_EC_TXTHRESH_STOPFILL)); + + TSI_WRITE(TSI108_STAT_CARRYMASK1, + ~(TSI108_STAT_CARRY1_RXBYTES | + TSI108_STAT_CARRY1_RXPKTS | + TSI108_STAT_CARRY1_RXFCS | + TSI108_STAT_CARRY1_RXMCAST | + TSI108_STAT_CARRY1_RXALIGN | + TSI108_STAT_CARRY1_RXLENGTH | + TSI108_STAT_CARRY1_RXRUNT | + TSI108_STAT_CARRY1_RXJUMBO | + TSI108_STAT_CARRY1_RXFRAG | + TSI108_STAT_CARRY1_RXJABBER | + TSI108_STAT_CARRY1_RXDROP)); + + TSI_WRITE(TSI108_STAT_CARRYMASK2, + ~(TSI108_STAT_CARRY2_TXBYTES | + TSI108_STAT_CARRY2_TXPKTS | + TSI108_STAT_CARRY2_TXEXDEF | + TSI108_STAT_CARRY2_TXEXCOL | + TSI108_STAT_CARRY2_TXTCOL | + TSI108_STAT_CARRY2_TXPAUSE)); + + TSI_WRITE(TSI108_EC_PORTCTRL, TSI108_EC_PORTCTRL_STATEN); + TSI_WRITE(TSI108_MAC_CFG1, 0); + + TSI_WRITE(TSI108_EC_RXCFG, + TSI108_EC_RXCFG_SE | TSI108_EC_RXCFG_BFE); + + TSI_WRITE(TSI108_EC_TXQ_CFG, TSI108_EC_TXQ_CFG_DESC_INT | + TSI108_EC_TXQ_CFG_EOQ_OWN_INT | + TSI108_EC_TXQ_CFG_WSWP | (TSI108_PBM_PORT << + TSI108_EC_TXQ_CFG_SFNPORT)); + + TSI_WRITE(TSI108_EC_RXQ_CFG, TSI108_EC_RXQ_CFG_DESC_INT | + TSI108_EC_RXQ_CFG_EOQ_OWN_INT | + TSI108_EC_RXQ_CFG_WSWP | (TSI108_PBM_PORT << + TSI108_EC_RXQ_CFG_SFNPORT)); + + TSI_WRITE(TSI108_EC_TXQ_BUFCFG, + TSI108_EC_TXQ_BUFCFG_BURST256 | + TSI108_EC_TXQ_BUFCFG_BSWP | (TSI108_PBM_PORT << + TSI108_EC_TXQ_BUFCFG_SFNPORT)); + + TSI_WRITE(TSI108_EC_RXQ_BUFCFG, + TSI108_EC_RXQ_BUFCFG_BURST256 | + TSI108_EC_RXQ_BUFCFG_BSWP | (TSI108_PBM_PORT << + TSI108_EC_RXQ_BUFCFG_SFNPORT)); + + TSI_WRITE(TSI108_EC_INTMASK, ~0); +} + +static int tsi108_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct tsi108_prv_data *data = netdev_priv(dev); + return generic_mii_ioctl(&data->mii_if, if_mii(rq), cmd, NULL); +} + +static int +tsi108_init_one(struct platform_device *pdev) +{ + struct net_device *dev = NULL; + struct tsi108_prv_data *data = NULL; + hw_info *einfo; + int err = 0; + + einfo = pdev->dev.platform_data; + + if (NULL == einfo) { + printk(KERN_ERR "tsi-eth %d: Missing additional data!\n", + pdev->id); + return -ENODEV; + } + + /* Create an ethernet device instance */ + + dev = alloc_etherdev(sizeof(struct tsi108_prv_data)); + if (!dev) { + printk("tsi108_eth: Could not allocate a device structure\n"); + return -ENOMEM; + } + + printk("tsi108_eth%d: probe...\n", pdev->id); + data = netdev_priv(dev); + + pr_debug("tsi108_eth%d:regs:phyresgs:phy:irq_num=0x%x:0x%x:0x%x:0x%x\n", + pdev->id, einfo->regs, einfo->phyregs, + einfo->phy, einfo->irq_num); + + data->regs = ioremap(einfo->regs, 0x400); + if (NULL == data->regs) { + err = -ENOMEM; + goto regs_fail; + } + + data->phyregs = ioremap(einfo->phyregs, 0x400); + if (NULL == data->phyregs) { + err = -ENOMEM; + goto regs_fail; + } +/* MII setup */ + data->mii_if.dev = dev; + data->mii_if.mdio_read = tsi108_mdio_read; + data->mii_if.mdio_write = tsi108_mdio_write; + data->mii_if.phy_id = einfo->phy; + data->mii_if.phy_id_mask = 0x1f; + data->mii_if.reg_num_mask = 0x1f; + data->mii_if.supports_gmii = mii_check_gmii_support(&data->mii_if); + + data->phy = einfo->phy; + data->irq_num = einfo->irq_num; + data->id = pdev->id; + dev->open = tsi108_open; + dev->stop = tsi108_close; + dev->hard_start_xmit = tsi108_send_packet; + dev->set_mac_address = tsi108_set_mac; + dev->set_multicast_list = tsi108_set_rx_mode; + dev->get_stats = tsi108_get_stats; + dev->poll = tsi108_poll; + dev->do_ioctl = tsi108_do_ioctl; + dev->weight = 64; /* 64 is more suitable for GigE interface - klai */ + + /* Apparently, the Linux networking code won't use scatter-gather + * if the hardware doesn't do checksums. However, it's faster + * to checksum in place and use SG, as (among other reasons) + * the cache won't be dirtied (which then has to be flushed + * before DMA). The checksumming is done by the driver (via + * a new function skb_csum_dev() in net/core/skbuff.c). + */ + + dev->features = NETIF_F_HIGHDMA; + SET_MODULE_OWNER(dev); + + spin_lock_init(&data->txlock); + spin_lock_init(&data->misclock); + + tsi108_reset_ether(data); + tsi108_kill_phy(dev); + + if ((err = tsi108_get_mac(dev)) != 0) { + printk(KERN_ERR "%s: Invalid MAC address. Please correct.\n", + dev->name); + goto register_fail; + } + + tsi108_init_mac(dev); + err = register_netdev(dev); + if (err) { + printk(KERN_ERR "%s: Cannot register net device, aborting.\n", + dev->name); + goto register_fail; + } + + printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: " + "%02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); +#ifdef DEBUG + data->msg_enable = DEBUG; + dump_eth_one(dev); +#endif + + return 0; + +register_fail: + iounmap(data->regs); + iounmap(data->phyregs); + +regs_fail: + free_netdev(dev); + return err; +} + +/* There's no way to either get interrupts from the PHY when + * something changes, or to have the Tsi108 automatically communicate + * with the PHY to reconfigure itself. + * + * Thus, we have to do it using a timer. + */ + +static void tsi108_timed_checker(unsigned long dev_ptr) +{ + struct net_device *dev = (struct net_device *)dev_ptr; + struct tsi108_prv_data *data = netdev_priv(dev); + + tsi108_check_phy(dev); + tsi108_check_rxring(dev); + mod_timer(&data->timer, jiffies + CHECK_PHY_INTERVAL); +} + +static int tsi108_ether_init(void) +{ + int ret; + ret = platform_driver_register (&tsi_eth_driver); + if (ret < 0){ + printk("tsi108_ether_init: error initializing ethernet " + "device\n"); + return ret; + } + return 0; +} + +static int tsi108_ether_remove(struct platform_device *pdev) +{ + struct net_device *dev = platform_get_drvdata(pdev); + struct tsi108_prv_data *priv = netdev_priv(dev); + + unregister_netdev(dev); + tsi108_stop_ethernet(dev); + platform_set_drvdata(pdev, NULL); + iounmap(priv->regs); + iounmap(priv->phyregs); + free_netdev(dev); + + return 0; +} +static void tsi108_ether_exit(void) +{ + platform_driver_unregister(&tsi_eth_driver); +} + +module_init(tsi108_ether_init); +module_exit(tsi108_ether_exit); + +MODULE_AUTHOR("Tundra Semiconductor Corporation"); +MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/tsi108_eth.h b/drivers/net/tsi108_eth.h new file mode 100644 index 000000000000..77a769df228a --- /dev/null +++ b/drivers/net/tsi108_eth.h @@ -0,0 +1,365 @@ +/* + * (C) Copyright 2005 Tundra Semiconductor Corp. + * Kong Lai, + +#define TSI_WRITE(offset, val) \ + out_be32((data->regs + (offset)), val) + +#define TSI_READ(offset) \ + in_be32((data->regs + (offset))) + +#define TSI_WRITE_PHY(offset, val) \ + out_be32((data->phyregs + (offset)), val) + +#define TSI_READ_PHY(offset) \ + in_be32((data->phyregs + (offset))) + +/* + * PHY Configuration Options + * + * NOTE: Enable set of definitions corresponding to your board type + */ +#define PHY_MV88E 1 /* Marvel 88Exxxx PHY */ +#define PHY_BCM54XX 2 /* Broardcom BCM54xx PHY */ +#define TSI108_PHY_TYPE PHY_MV88E + +/* + * TSI108 GIGE port registers + */ + +#define TSI108_ETH_PORT_NUM 2 +#define TSI108_PBM_PORT 2 +#define TSI108_SDRAM_PORT 4 + +#define TSI108_MAC_CFG1 (0x000) +#define TSI108_MAC_CFG1_SOFTRST (1 << 31) +#define TSI108_MAC_CFG1_LOOPBACK (1 << 8) +#define TSI108_MAC_CFG1_RXEN (1 << 2) +#define TSI108_MAC_CFG1_TXEN (1 << 0) + +#define TSI108_MAC_CFG2 (0x004) +#define TSI108_MAC_CFG2_DFLT_PREAMBLE (7 << 12) +#define TSI108_MAC_CFG2_IFACE_MASK (3 << 8) +#define TSI108_MAC_CFG2_NOGIG (1 << 8) +#define TSI108_MAC_CFG2_GIG (2 << 8) +#define TSI108_MAC_CFG2_PADCRC (1 << 2) +#define TSI108_MAC_CFG2_FULLDUPLEX (1 << 0) + +#define TSI108_MAC_MII_MGMT_CFG (0x020) +#define TSI108_MAC_MII_MGMT_CLK (7 << 0) +#define TSI108_MAC_MII_MGMT_RST (1 << 31) + +#define TSI108_MAC_MII_CMD (0x024) +#define TSI108_MAC_MII_CMD_READ (1 << 0) + +#define TSI108_MAC_MII_ADDR (0x028) +#define TSI108_MAC_MII_ADDR_REG 0 +#define TSI108_MAC_MII_ADDR_PHY 8 + +#define TSI108_MAC_MII_DATAOUT (0x02c) +#define TSI108_MAC_MII_DATAIN (0x030) + +#define TSI108_MAC_MII_IND (0x034) +#define TSI108_MAC_MII_IND_NOTVALID (1 << 2) +#define TSI108_MAC_MII_IND_SCANNING (1 << 1) +#define TSI108_MAC_MII_IND_BUSY (1 << 0) + +#define TSI108_MAC_IFCTRL (0x038) +#define TSI108_MAC_IFCTRL_PHYMODE (1 << 24) + +#define TSI108_MAC_ADDR1 (0x040) +#define TSI108_MAC_ADDR2 (0x044) + +#define TSI108_STAT_RXBYTES (0x06c) +#define TSI108_STAT_RXBYTES_CARRY (1 << 24) + +#define TSI108_STAT_RXPKTS (0x070) +#define TSI108_STAT_RXPKTS_CARRY (1 << 18) + +#define TSI108_STAT_RXFCS (0x074) +#define TSI108_STAT_RXFCS_CARRY (1 << 12) + +#define TSI108_STAT_RXMCAST (0x078) +#define TSI108_STAT_RXMCAST_CARRY (1 << 18) + +#define TSI108_STAT_RXALIGN (0x08c) +#define TSI108_STAT_RXALIGN_CARRY (1 << 12) + +#define TSI108_STAT_RXLENGTH (0x090) +#define TSI108_STAT_RXLENGTH_CARRY (1 << 12) + +#define TSI108_STAT_RXRUNT (0x09c) +#define TSI108_STAT_RXRUNT_CARRY (1 << 12) + +#define TSI108_STAT_RXJUMBO (0x0a0) +#define TSI108_STAT_RXJUMBO_CARRY (1 << 12) + +#define TSI108_STAT_RXFRAG (0x0a4) +#define TSI108_STAT_RXFRAG_CARRY (1 << 12) + +#define TSI108_STAT_RXJABBER (0x0a8) +#define TSI108_STAT_RXJABBER_CARRY (1 << 12) + +#define TSI108_STAT_RXDROP (0x0ac) +#define TSI108_STAT_RXDROP_CARRY (1 << 12) + +#define TSI108_STAT_TXBYTES (0x0b0) +#define TSI108_STAT_TXBYTES_CARRY (1 << 24) + +#define TSI108_STAT_TXPKTS (0x0b4) +#define TSI108_STAT_TXPKTS_CARRY (1 << 18) + +#define TSI108_STAT_TXEXDEF (0x0c8) +#define TSI108_STAT_TXEXDEF_CARRY (1 << 12) + +#define TSI108_STAT_TXEXCOL (0x0d8) +#define TSI108_STAT_TXEXCOL_CARRY (1 << 12) + +#define TSI108_STAT_TXTCOL (0x0dc) +#define TSI108_STAT_TXTCOL_CARRY (1 << 13) + +#define TSI108_STAT_TXPAUSEDROP (0x0e4) +#define TSI108_STAT_TXPAUSEDROP_CARRY (1 << 12) + +#define TSI108_STAT_CARRY1 (0x100) +#define TSI108_STAT_CARRY1_RXBYTES (1 << 16) +#define TSI108_STAT_CARRY1_RXPKTS (1 << 15) +#define TSI108_STAT_CARRY1_RXFCS (1 << 14) +#define TSI108_STAT_CARRY1_RXMCAST (1 << 13) +#define TSI108_STAT_CARRY1_RXALIGN (1 << 8) +#define TSI108_STAT_CARRY1_RXLENGTH (1 << 7) +#define TSI108_STAT_CARRY1_RXRUNT (1 << 4) +#define TSI108_STAT_CARRY1_RXJUMBO (1 << 3) +#define TSI108_STAT_CARRY1_RXFRAG (1 << 2) +#define TSI108_STAT_CARRY1_RXJABBER (1 << 1) +#define TSI108_STAT_CARRY1_RXDROP (1 << 0) + +#define TSI108_STAT_CARRY2 (0x104) +#define TSI108_STAT_CARRY2_TXBYTES (1 << 13) +#define TSI108_STAT_CARRY2_TXPKTS (1 << 12) +#define TSI108_STAT_CARRY2_TXEXDEF (1 << 7) +#define TSI108_STAT_CARRY2_TXEXCOL (1 << 3) +#define TSI108_STAT_CARRY2_TXTCOL (1 << 2) +#define TSI108_STAT_CARRY2_TXPAUSE (1 << 0) + +#define TSI108_STAT_CARRYMASK1 (0x108) +#define TSI108_STAT_CARRYMASK2 (0x10c) + +#define TSI108_EC_PORTCTRL (0x200) +#define TSI108_EC_PORTCTRL_STATRST (1 << 31) +#define TSI108_EC_PORTCTRL_STATEN (1 << 28) +#define TSI108_EC_PORTCTRL_NOGIG (1 << 18) +#define TSI108_EC_PORTCTRL_HALFDUPLEX (1 << 16) + +#define TSI108_EC_INTSTAT (0x204) +#define TSI108_EC_INTMASK (0x208) + +#define TSI108_INT_ANY (1 << 31) +#define TSI108_INT_SFN (1 << 30) +#define TSI108_INT_RXIDLE (1 << 29) +#define TSI108_INT_RXABORT (1 << 28) +#define TSI108_INT_RXERROR (1 << 27) +#define TSI108_INT_RXOVERRUN (1 << 26) +#define TSI108_INT_RXTHRESH (1 << 25) +#define TSI108_INT_RXWAIT (1 << 24) +#define TSI108_INT_RXQUEUE0 (1 << 16) +#define TSI108_INT_STATCARRY (1 << 15) +#define TSI108_INT_TXIDLE (1 << 13) +#define TSI108_INT_TXABORT (1 << 12) +#define TSI108_INT_TXERROR (1 << 11) +#define TSI108_INT_TXUNDERRUN (1 << 10) +#define TSI108_INT_TXTHRESH (1 << 9) +#define TSI108_INT_TXWAIT (1 << 8) +#define TSI108_INT_TXQUEUE0 (1 << 0) + +#define TSI108_EC_TXCFG (0x220) +#define TSI108_EC_TXCFG_RST (1 << 31) + +#define TSI108_EC_TXCTRL (0x224) +#define TSI108_EC_TXCTRL_IDLEINT (1 << 31) +#define TSI108_EC_TXCTRL_ABORT (1 << 30) +#define TSI108_EC_TXCTRL_GO (1 << 15) +#define TSI108_EC_TXCTRL_QUEUE0 (1 << 0) + +#define TSI108_EC_TXSTAT (0x228) +#define TSI108_EC_TXSTAT_ACTIVE (1 << 15) +#define TSI108_EC_TXSTAT_QUEUE0 (1 << 0) + +#define TSI108_EC_TXESTAT (0x22c) +#define TSI108_EC_TXESTAT_Q0_ERR (1 << 24) +#define TSI108_EC_TXESTAT_Q0_DESCINT (1 << 16) +#define TSI108_EC_TXESTAT_Q0_EOF (1 << 8) +#define TSI108_EC_TXESTAT_Q0_EOQ (1 << 0) + +#define TSI108_EC_TXERR (0x278) + +#define TSI108_EC_TXQ_CFG (0x280) +#define TSI108_EC_TXQ_CFG_DESC_INT (1 << 20) +#define TSI108_EC_TXQ_CFG_EOQ_OWN_INT (1 << 19) +#define TSI108_EC_TXQ_CFG_WSWP (1 << 11) +#define TSI108_EC_TXQ_CFG_BSWP (1 << 10) +#define TSI108_EC_TXQ_CFG_SFNPORT 0 + +#define TSI108_EC_TXQ_BUFCFG (0x284) +#define TSI108_EC_TXQ_BUFCFG_BURST8 (0 << 8) +#define TSI108_EC_TXQ_BUFCFG_BURST32 (1 << 8) +#define TSI108_EC_TXQ_BUFCFG_BURST128 (2 << 8) +#define TSI108_EC_TXQ_BUFCFG_BURST256 (3 << 8) +#define TSI108_EC_TXQ_BUFCFG_WSWP (1 << 11) +#define TSI108_EC_TXQ_BUFCFG_BSWP (1 << 10) +#define TSI108_EC_TXQ_BUFCFG_SFNPORT 0 + +#define TSI108_EC_TXQ_PTRLOW (0x288) + +#define TSI108_EC_TXQ_PTRHIGH (0x28c) +#define TSI108_EC_TXQ_PTRHIGH_VALID (1 << 31) + +#define TSI108_EC_TXTHRESH (0x230) +#define TSI108_EC_TXTHRESH_STARTFILL 0 +#define TSI108_EC_TXTHRESH_STOPFILL 16 + +#define TSI108_EC_RXCFG (0x320) +#define TSI108_EC_RXCFG_RST (1 << 31) + +#define TSI108_EC_RXSTAT (0x328) +#define TSI108_EC_RXSTAT_ACTIVE (1 << 15) +#define TSI108_EC_RXSTAT_QUEUE0 (1 << 0) + +#define TSI108_EC_RXESTAT (0x32c) +#define TSI108_EC_RXESTAT_Q0_ERR (1 << 24) +#define TSI108_EC_RXESTAT_Q0_DESCINT (1 << 16) +#define TSI108_EC_RXESTAT_Q0_EOF (1 << 8) +#define TSI108_EC_RXESTAT_Q0_EOQ (1 << 0) + +#define TSI108_EC_HASHADDR (0x360) +#define TSI108_EC_HASHADDR_AUTOINC (1 << 31) +#define TSI108_EC_HASHADDR_DO1STREAD (1 << 30) +#define TSI108_EC_HASHADDR_UNICAST (0 << 4) +#define TSI108_EC_HASHADDR_MCAST (1 << 4) + +#define TSI108_EC_HASHDATA (0x364) + +#define TSI108_EC_RXQ_PTRLOW (0x388) + +#define TSI108_EC_RXQ_PTRHIGH (0x38c) +#define TSI108_EC_RXQ_PTRHIGH_VALID (1 << 31) + +/* Station Enable -- accept packets destined for us */ +#define TSI108_EC_RXCFG_SE (1 << 13) +/* Unicast Frame Enable -- for packets not destined for us */ +#define TSI108_EC_RXCFG_UFE (1 << 12) +/* Multicast Frame Enable */ +#define TSI108_EC_RXCFG_MFE (1 << 11) +/* Broadcast Frame Enable */ +#define TSI108_EC_RXCFG_BFE (1 << 10) +#define TSI108_EC_RXCFG_UC_HASH (1 << 9) +#define TSI108_EC_RXCFG_MC_HASH (1 << 8) + +#define TSI108_EC_RXQ_CFG (0x380) +#define TSI108_EC_RXQ_CFG_DESC_INT (1 << 20) +#define TSI108_EC_RXQ_CFG_EOQ_OWN_INT (1 << 19) +#define TSI108_EC_RXQ_CFG_WSWP (1 << 11) +#define TSI108_EC_RXQ_CFG_BSWP (1 << 10) +#define TSI108_EC_RXQ_CFG_SFNPORT 0 + +#define TSI108_EC_RXQ_BUFCFG (0x384) +#define TSI108_EC_RXQ_BUFCFG_BURST8 (0 << 8) +#define TSI108_EC_RXQ_BUFCFG_BURST32 (1 << 8) +#define TSI108_EC_RXQ_BUFCFG_BURST128 (2 << 8) +#define TSI108_EC_RXQ_BUFCFG_BURST256 (3 << 8) +#define TSI108_EC_RXQ_BUFCFG_WSWP (1 << 11) +#define TSI108_EC_RXQ_BUFCFG_BSWP (1 << 10) +#define TSI108_EC_RXQ_BUFCFG_SFNPORT 0 + +#define TSI108_EC_RXCTRL (0x324) +#define TSI108_EC_RXCTRL_ABORT (1 << 30) +#define TSI108_EC_RXCTRL_GO (1 << 15) +#define TSI108_EC_RXCTRL_QUEUE0 (1 << 0) + +#define TSI108_EC_RXERR (0x378) + +#define TSI108_TX_EOF (1 << 0) /* End of frame; last fragment of packet */ +#define TSI108_TX_SOF (1 << 1) /* Start of frame; first frag. of packet */ +#define TSI108_TX_VLAN (1 << 2) /* Per-frame VLAN: enables VLAN override */ +#define TSI108_TX_HUGE (1 << 3) /* Huge frame enable */ +#define TSI108_TX_PAD (1 << 4) /* Pad the packet if too short */ +#define TSI108_TX_CRC (1 << 5) /* Generate CRC for this packet */ +#define TSI108_TX_INT (1 << 14) /* Generate an IRQ after frag. processed */ +#define TSI108_TX_RETRY (0xf << 16) /* 4 bit field indicating num. of retries */ +#define TSI108_TX_COL (1 << 20) /* Set if a collision occured */ +#define TSI108_TX_LCOL (1 << 24) /* Set if a late collision occured */ +#define TSI108_TX_UNDER (1 << 25) /* Set if a FIFO underrun occured */ +#define TSI108_TX_RLIM (1 << 26) /* Set if the retry limit was reached */ +#define TSI108_TX_OK (1 << 30) /* Set if the frame TX was successful */ +#define TSI108_TX_OWN (1 << 31) /* Set if the device owns the descriptor */ + +/* Note: the descriptor layouts assume big-endian byte order. */ +typedef struct { + u32 buf0; + u32 buf1; /* Base address of buffer */ + u32 next0; /* Address of next descriptor, if any */ + u32 next1; + u16 vlan; /* VLAN, if override enabled for this packet */ + u16 len; /* Length of buffer in bytes */ + u32 misc; /* See TSI108_TX_* above */ + u32 reserved0; /*reserved0 and reserved1 are added to make the desc */ + u32 reserved1; /* 32-byte aligned */ +} __attribute__ ((aligned(32))) tx_desc; + +#define TSI108_RX_EOF (1 << 0) /* End of frame; last fragment of packet */ +#define TSI108_RX_SOF (1 << 1) /* Start of frame; first frag. of packet */ +#define TSI108_RX_VLAN (1 << 2) /* Set on SOF if packet has a VLAN */ +#define TSI108_RX_FTYPE (1 << 3) /* Length/Type field is type, not length */ +#define TSI108_RX_RUNT (1 << 4)/* Packet is less than minimum size */ +#define TSI108_RX_HASH (1 << 7)/* Hash table match */ +#define TSI108_RX_BAD (1 << 8) /* Bad frame */ +#define TSI108_RX_OVER (1 << 9) /* FIFO overrun occured */ +#define TSI108_RX_TRUNC (1 << 11) /* Packet truncated due to excess length */ +#define TSI108_RX_CRC (1 << 12) /* Packet had a CRC error */ +#define TSI108_RX_INT (1 << 13) /* Generate an IRQ after frag. processed */ +#define TSI108_RX_OWN (1 << 15) /* Set if the device owns the descriptor */ + +#define TSI108_RX_SKB_SIZE 1536 /* The RX skb length */ + +typedef struct { + u32 buf0; /* Base address of buffer */ + u32 buf1; /* Base address of buffer */ + u32 next0; /* Address of next descriptor, if any */ + u32 next1; /* Address of next descriptor, if any */ + u16 vlan; /* VLAN of received packet, first frag only */ + u16 len; /* Length of received fragment in bytes */ + u16 blen; /* Length of buffer in bytes */ + u16 misc; /* See TSI108_RX_* above */ + u32 reserved0; /* reserved0 and reserved1 are added to make the desc */ + u32 reserved1; /* 32-byte aligned */ +} __attribute__ ((aligned(32))) rx_desc; + +#endif /* __TSI108_ETH_H */ -- cgit v1.2.3 From b690bdef7c4523bf55103b7a841c454d4674b315 Mon Sep 17 00:00:00 2001 From: Krzysztof Halasa Date: Mon, 13 Nov 2006 19:48:54 +0100 Subject: [PATCH] WAN: DSCC4 driver requires generic HDLC Another thing, reported recently to me by several people - DSCC4 WAN driver now (and perhaps for the last couple of years+) requires the generic HDLC. I've fixed the Kconfig and moved the DSCC4 option under CONFIG_HDLC so it's consistent visually. Signed-off-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/wan/Kconfig | 76 ++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index b5d0d7fb647a..d5ab9cf13257 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -57,44 +57,6 @@ config COSA The driver will be compiled as a module: the module will be called cosa. -config DSCC4 - tristate "Etinc PCISYNC serial board support" - depends on WAN && PCI && m - help - Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens) - DSCC4 chipset. - - This is supposed to work with the four port card. Take a look at - for further information about the - driver. - - To compile this driver as a module, choose M here: the - module will be called dscc4. - -config DSCC4_PCISYNC - bool "Etinc PCISYNC features" - depends on DSCC4 - help - Due to Etinc's design choice for its PCISYNC cards, some operations - are only allowed on specific ports of the DSCC4. This option is the - only way for the driver to know that it shouldn't return a success - code for these operations. - - Please say Y if your card is an Etinc's PCISYNC. - -config DSCC4_PCI_RST - bool "Hard reset support" - depends on DSCC4 - help - Various DSCC4 bugs forbid any reliable software reset of the ASIC. - As a replacement, some vendors provide a way to assert the PCI #RST - pin of DSCC4 through the GPIO port of the card. If you choose Y, - the driver will make use of this feature before module removal - (i.e. rmmod). The feature is known to be available on Commtech's - cards. Contact your manufacturer for details. - - Say Y if your card supports this feature. - # # Lan Media's board. Currently 1000, 1200, 5200, 5245 # @@ -323,6 +285,44 @@ config FARSYNC To compile this driver as a module, choose M here: the module will be called farsync. +config DSCC4 + tristate "Etinc PCISYNC serial board support" + depends on HDLC && PCI && m + help + Driver for Etinc PCISYNC boards based on the Infineon (ex. Siemens) + DSCC4 chipset. + + This is supposed to work with the four port card. Take a look at + for further information about the + driver. + + To compile this driver as a module, choose M here: the + module will be called dscc4. + +config DSCC4_PCISYNC + bool "Etinc PCISYNC features" + depends on DSCC4 + help + Due to Etinc's design choice for its PCISYNC cards, some operations + are only allowed on specific ports of the DSCC4. This option is the + only way for the driver to know that it shouldn't return a success + code for these operations. + + Please say Y if your card is an Etinc's PCISYNC. + +config DSCC4_PCI_RST + bool "Hard reset support" + depends on DSCC4 + help + Various DSCC4 bugs forbid any reliable software reset of the ASIC. + As a replacement, some vendors provide a way to assert the PCI #RST + pin of DSCC4 through the GPIO port of the card. If you choose Y, + the driver will make use of this feature before module removal + (i.e. rmmod). The feature is known to be available on Commtech's + cards. Contact your manufacturer for details. + + Say Y if your card supports this feature. + config DLCI tristate "Frame Relay DLCI support" depends on WAN -- cgit v1.2.3 From 89e5785fc8a6b9eafd37f2318a9a76d479c796be Mon Sep 17 00:00:00 2001 From: Haavard Skinnemoen Date: Thu, 9 Nov 2006 14:51:17 +0100 Subject: [PATCH] Atmel MACB ethernet driver Driver for the Atmel MACB on-chip ethernet module. Tested on AVR32/AT32AP7000/ATSTK1000. I've heard rumours that it works with AT91SAM9260 as well, and it may be possible to share some code with the at91_ether driver for AT91RM9200. Hardware documentation can be found in the AT32AP7000 data sheet, which can be downloaded from http://www.atmel.com/dyn/products/datasheets.asp?family_id=682 Changes since previous version: * Probe for PHY ID instead of depending on it being provided through platform_data. * Grab initial ethernet address from the MACB registers instead of depending on platform_data. * Set MII/RMII mode correctly. These changes are mostly about making the driver more compatible with the at91 infrastructure. Signed-off-by: Haavard Skinnemoen Signed-off-by: Jeff Garzik --- MAINTAINERS | 7 + drivers/net/Kconfig | 11 + drivers/net/Makefile | 2 + drivers/net/macb.c | 1210 ++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/macb.h | 387 ++++++++++++++++ 5 files changed, 1617 insertions(+) create mode 100644 drivers/net/macb.c create mode 100644 drivers/net/macb.h (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 0e174320726f..45df5d4e2ab3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -432,6 +432,13 @@ L: linux-atm-general@lists.sourceforge.net (subscribers-only) W: http://linux-atm.sourceforge.net S: Maintained +ATMEL MACB ETHERNET DRIVER +P: Atmel AVR32 Support Team +M: avr32@atmel.com +P: Haavard Skinnemoen +M: hskinnemoen@atmel.com +S: Supported + ATMEL WIRELESS DRIVER P: Simon Kelley M: simon@thekelleys.org.uk diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 05167253b254..10ac1c763f33 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -188,6 +188,17 @@ config MII or internal device. It is safe to say Y or M here even if your ethernet card lack MII. +config MACB + tristate "Atmel MACB support" + depends on NET_ETHERNET && AVR32 + select MII + help + The Atmel MACB ethernet interface is found on many AT32 and AT91 + parts. Say Y to include support for the MACB chip. + + To compile this driver as a module, choose M here: the module + will be called macb. + source "drivers/net/arm/Kconfig" config MACE diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 789306ca7936..4c0d4e5ce42b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -197,6 +197,8 @@ obj-$(CONFIG_SMC911X) += smc911x.o obj-$(CONFIG_DM9000) += dm9000.o obj-$(CONFIG_FEC_8XX) += fec_8xx/ +obj-$(CONFIG_MACB) += macb.o + obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_DEV_APPLETALK) += appletalk/ obj-$(CONFIG_TR) += tokenring/ diff --git a/drivers/net/macb.c b/drivers/net/macb.c new file mode 100644 index 000000000000..bd0ce98c939c --- /dev/null +++ b/drivers/net/macb.c @@ -0,0 +1,1210 @@ +/* + * Atmel MACB Ethernet Controller driver + * + * Copyright (C) 2004-2006 Atmel Corporation + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "macb.h" + +#define to_net_dev(class) container_of(class, struct net_device, class_dev) + +#define RX_BUFFER_SIZE 128 +#define RX_RING_SIZE 512 +#define RX_RING_BYTES (sizeof(struct dma_desc) * RX_RING_SIZE) + +/* Make the IP header word-aligned (the ethernet header is 14 bytes) */ +#define RX_OFFSET 2 + +#define TX_RING_SIZE 128 +#define DEF_TX_RING_PENDING (TX_RING_SIZE - 1) +#define TX_RING_BYTES (sizeof(struct dma_desc) * TX_RING_SIZE) + +#define TX_RING_GAP(bp) \ + (TX_RING_SIZE - (bp)->tx_pending) +#define TX_BUFFS_AVAIL(bp) \ + (((bp)->tx_tail <= (bp)->tx_head) ? \ + (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head : \ + (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp)) +#define NEXT_TX(n) (((n) + 1) & (TX_RING_SIZE - 1)) + +#define NEXT_RX(n) (((n) + 1) & (RX_RING_SIZE - 1)) + +/* minimum number of free TX descriptors before waking up TX process */ +#define MACB_TX_WAKEUP_THRESH (TX_RING_SIZE / 4) + +#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \ + | MACB_BIT(ISR_ROVR)) + +static void __macb_set_hwaddr(struct macb *bp) +{ + u32 bottom; + u16 top; + + bottom = cpu_to_le32(*((u32 *)bp->dev->dev_addr)); + macb_writel(bp, SA1B, bottom); + top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4))); + macb_writel(bp, SA1T, top); +} + +static void __init macb_get_hwaddr(struct macb *bp) +{ + u32 bottom; + u16 top; + u8 addr[6]; + + bottom = macb_readl(bp, SA1B); + top = macb_readl(bp, SA1T); + + addr[0] = bottom & 0xff; + addr[1] = (bottom >> 8) & 0xff; + addr[2] = (bottom >> 16) & 0xff; + addr[3] = (bottom >> 24) & 0xff; + addr[4] = top & 0xff; + addr[5] = (top >> 8) & 0xff; + + if (is_valid_ether_addr(addr)) + memcpy(bp->dev->dev_addr, addr, sizeof(addr)); +} + +static void macb_enable_mdio(struct macb *bp) +{ + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&bp->lock, flags); + reg = macb_readl(bp, NCR); + reg |= MACB_BIT(MPE); + macb_writel(bp, NCR, reg); + macb_writel(bp, IER, MACB_BIT(MFD)); + spin_unlock_irqrestore(&bp->lock, flags); +} + +static void macb_disable_mdio(struct macb *bp) +{ + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&bp->lock, flags); + reg = macb_readl(bp, NCR); + reg &= ~MACB_BIT(MPE); + macb_writel(bp, NCR, reg); + macb_writel(bp, IDR, MACB_BIT(MFD)); + spin_unlock_irqrestore(&bp->lock, flags); +} + +static int macb_mdio_read(struct net_device *dev, int phy_id, int location) +{ + struct macb *bp = netdev_priv(dev); + int value; + + mutex_lock(&bp->mdio_mutex); + + macb_enable_mdio(bp); + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) + | MACB_BF(RW, MACB_MAN_READ) + | MACB_BF(PHYA, phy_id) + | MACB_BF(REGA, location) + | MACB_BF(CODE, MACB_MAN_CODE))); + + wait_for_completion(&bp->mdio_complete); + + value = MACB_BFEXT(DATA, macb_readl(bp, MAN)); + macb_disable_mdio(bp); + mutex_unlock(&bp->mdio_mutex); + + return value; +} + +static void macb_mdio_write(struct net_device *dev, int phy_id, + int location, int val) +{ + struct macb *bp = netdev_priv(dev); + + dev_dbg(&bp->pdev->dev, "mdio_write %02x:%02x <- %04x\n", + phy_id, location, val); + + mutex_lock(&bp->mdio_mutex); + macb_enable_mdio(bp); + + macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF) + | MACB_BF(RW, MACB_MAN_WRITE) + | MACB_BF(PHYA, phy_id) + | MACB_BF(REGA, location) + | MACB_BF(CODE, MACB_MAN_CODE) + | MACB_BF(DATA, val))); + + wait_for_completion(&bp->mdio_complete); + + macb_disable_mdio(bp); + mutex_unlock(&bp->mdio_mutex); +} + +static int macb_phy_probe(struct macb *bp) +{ + int phy_address; + u16 phyid1, phyid2; + + for (phy_address = 0; phy_address < 32; phy_address++) { + phyid1 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID1); + phyid2 = macb_mdio_read(bp->dev, phy_address, MII_PHYSID2); + + if (phyid1 != 0xffff && phyid1 != 0x0000 + && phyid2 != 0xffff && phyid2 != 0x0000) + break; + } + + if (phy_address == 32) + return -ENODEV; + + dev_info(&bp->pdev->dev, + "detected PHY at address %d (ID %04x:%04x)\n", + phy_address, phyid1, phyid2); + + bp->mii.phy_id = phy_address; + return 0; +} + +static void macb_set_media(struct macb *bp, int media) +{ + u32 reg; + + spin_lock_irq(&bp->lock); + reg = macb_readl(bp, NCFGR); + reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD)); + if (media & (ADVERTISE_100HALF | ADVERTISE_100FULL)) + reg |= MACB_BIT(SPD); + if (media & ADVERTISE_FULL) + reg |= MACB_BIT(FD); + macb_writel(bp, NCFGR, reg); + spin_unlock_irq(&bp->lock); +} + +static void macb_check_media(struct macb *bp, int ok_to_print, int init_media) +{ + struct mii_if_info *mii = &bp->mii; + unsigned int old_carrier, new_carrier; + int advertise, lpa, media, duplex; + + /* if forced media, go no further */ + if (mii->force_media) + return; + + /* check current and old link status */ + old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; + new_carrier = (unsigned int) mii_link_ok(mii); + + /* if carrier state did not change, assume nothing else did */ + if (!init_media && old_carrier == new_carrier) + return; + + /* no carrier, nothing much to do */ + if (!new_carrier) { + netif_carrier_off(mii->dev); + printk(KERN_INFO "%s: link down\n", mii->dev->name); + return; + } + + /* + * we have carrier, see who's on the other end + */ + netif_carrier_on(mii->dev); + + /* get MII advertise and LPA values */ + if (!init_media && mii->advertising) { + advertise = mii->advertising; + } else { + advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); + mii->advertising = advertise; + } + lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); + + /* figure out media and duplex from advertise and LPA values */ + media = mii_nway_result(lpa & advertise); + duplex = (media & ADVERTISE_FULL) ? 1 : 0; + + if (ok_to_print) + printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n", + mii->dev->name, + media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10", + duplex ? "full" : "half", lpa); + + mii->full_duplex = duplex; + + /* Let the MAC know about the new link state */ + macb_set_media(bp, media); +} + +static void macb_update_stats(struct macb *bp) +{ + u32 __iomem *reg = bp->regs + MACB_PFR; + u32 *p = &bp->hw_stats.rx_pause_frames; + u32 *end = &bp->hw_stats.tx_pause_frames + 1; + + WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4); + + for(; p < end; p++, reg++) + *p += readl(reg); +} + +static void macb_periodic_task(void *arg) +{ + struct macb *bp = arg; + + macb_update_stats(bp); + macb_check_media(bp, 1, 0); + + schedule_delayed_work(&bp->periodic_task, HZ); +} + +static void macb_tx(struct macb *bp) +{ + unsigned int tail; + unsigned int head; + u32 status; + + status = macb_readl(bp, TSR); + macb_writel(bp, TSR, status); + + dev_dbg(&bp->pdev->dev, "macb_tx status = %02lx\n", + (unsigned long)status); + + if (status & MACB_BIT(UND)) { + printk(KERN_ERR "%s: TX underrun, resetting buffers\n", + bp->dev->name); + bp->tx_head = bp->tx_tail = 0; + } + + if (!(status & MACB_BIT(COMP))) + /* + * This may happen when a buffer becomes complete + * between reading the ISR and scanning the + * descriptors. Nothing to worry about. + */ + return; + + head = bp->tx_head; + for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) { + struct ring_info *rp = &bp->tx_skb[tail]; + struct sk_buff *skb = rp->skb; + u32 bufstat; + + BUG_ON(skb == NULL); + + rmb(); + bufstat = bp->tx_ring[tail].ctrl; + + if (!(bufstat & MACB_BIT(TX_USED))) + break; + + dev_dbg(&bp->pdev->dev, "skb %u (data %p) TX complete\n", + tail, skb->data); + dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len, + DMA_TO_DEVICE); + bp->stats.tx_packets++; + bp->stats.tx_bytes += skb->len; + rp->skb = NULL; + dev_kfree_skb_irq(skb); + } + + bp->tx_tail = tail; + if (netif_queue_stopped(bp->dev) && + TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH) + netif_wake_queue(bp->dev); +} + +static int macb_rx_frame(struct macb *bp, unsigned int first_frag, + unsigned int last_frag) +{ + unsigned int len; + unsigned int frag; + unsigned int offset = 0; + struct sk_buff *skb; + + len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl); + + dev_dbg(&bp->pdev->dev, "macb_rx_frame frags %u - %u (len %u)\n", + first_frag, last_frag, len); + + skb = dev_alloc_skb(len + RX_OFFSET); + if (!skb) { + bp->stats.rx_dropped++; + for (frag = first_frag; ; frag = NEXT_RX(frag)) { + bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); + if (frag == last_frag) + break; + } + wmb(); + return 1; + } + + skb_reserve(skb, RX_OFFSET); + skb->dev = bp->dev; + skb->ip_summed = CHECKSUM_NONE; + skb_put(skb, len); + + for (frag = first_frag; ; frag = NEXT_RX(frag)) { + unsigned int frag_len = RX_BUFFER_SIZE; + + if (offset + frag_len > len) { + BUG_ON(frag != last_frag); + frag_len = len - offset; + } + memcpy(skb->data + offset, + bp->rx_buffers + (RX_BUFFER_SIZE * frag), + frag_len); + offset += RX_BUFFER_SIZE; + bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); + wmb(); + + if (frag == last_frag) + break; + } + + skb->protocol = eth_type_trans(skb, bp->dev); + + bp->stats.rx_packets++; + bp->stats.rx_bytes += len; + bp->dev->last_rx = jiffies; + dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n", + skb->len, skb->csum); + netif_receive_skb(skb); + + return 0; +} + +/* Mark DMA descriptors from begin up to and not including end as unused */ +static void discard_partial_frame(struct macb *bp, unsigned int begin, + unsigned int end) +{ + unsigned int frag; + + for (frag = begin; frag != end; frag = NEXT_RX(frag)) + bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED); + wmb(); + + /* + * When this happens, the hardware stats registers for + * whatever caused this is updated, so we don't have to record + * anything. + */ +} + +static int macb_rx(struct macb *bp, int budget) +{ + int received = 0; + unsigned int tail = bp->rx_tail; + int first_frag = -1; + + for (; budget > 0; tail = NEXT_RX(tail)) { + u32 addr, ctrl; + + rmb(); + addr = bp->rx_ring[tail].addr; + ctrl = bp->rx_ring[tail].ctrl; + + if (!(addr & MACB_BIT(RX_USED))) + break; + + if (ctrl & MACB_BIT(RX_SOF)) { + if (first_frag != -1) + discard_partial_frame(bp, first_frag, tail); + first_frag = tail; + } + + if (ctrl & MACB_BIT(RX_EOF)) { + int dropped; + BUG_ON(first_frag == -1); + + dropped = macb_rx_frame(bp, first_frag, tail); + first_frag = -1; + if (!dropped) { + received++; + budget--; + } + } + } + + if (first_frag != -1) + bp->rx_tail = first_frag; + else + bp->rx_tail = tail; + + return received; +} + +static int macb_poll(struct net_device *dev, int *budget) +{ + struct macb *bp = netdev_priv(dev); + int orig_budget, work_done, retval = 0; + u32 status; + + status = macb_readl(bp, RSR); + macb_writel(bp, RSR, status); + + if (!status) { + /* + * This may happen if an interrupt was pending before + * this function was called last time, and no packets + * have been received since. + */ + netif_rx_complete(dev); + goto out; + } + + dev_dbg(&bp->pdev->dev, "poll: status = %08lx, budget = %d\n", + (unsigned long)status, *budget); + + if (!(status & MACB_BIT(REC))) { + dev_warn(&bp->pdev->dev, + "No RX buffers complete, status = %02lx\n", + (unsigned long)status); + netif_rx_complete(dev); + goto out; + } + + orig_budget = *budget; + if (orig_budget > dev->quota) + orig_budget = dev->quota; + + work_done = macb_rx(bp, orig_budget); + if (work_done < orig_budget) { + netif_rx_complete(dev); + retval = 0; + } else { + retval = 1; + } + + /* + * We've done what we can to clean the buffers. Make sure we + * get notified when new packets arrive. + */ +out: + macb_writel(bp, IER, MACB_RX_INT_FLAGS); + + /* TODO: Handle errors */ + + return retval; +} + +static irqreturn_t macb_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct macb *bp = netdev_priv(dev); + u32 status; + + status = macb_readl(bp, ISR); + + if (unlikely(!status)) + return IRQ_NONE; + + spin_lock(&bp->lock); + + while (status) { + if (status & MACB_BIT(MFD)) + complete(&bp->mdio_complete); + + /* close possible race with dev_close */ + if (unlikely(!netif_running(dev))) { + macb_writel(bp, IDR, ~0UL); + break; + } + + if (status & MACB_RX_INT_FLAGS) { + if (netif_rx_schedule_prep(dev)) { + /* + * There's no point taking any more interrupts + * until we have processed the buffers + */ + macb_writel(bp, IDR, MACB_RX_INT_FLAGS); + dev_dbg(&bp->pdev->dev, "scheduling RX softirq\n"); + __netif_rx_schedule(dev); + } + } + + if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND))) + macb_tx(bp); + + /* + * Link change detection isn't possible with RMII, so we'll + * add that if/when we get our hands on a full-blown MII PHY. + */ + + if (status & MACB_BIT(HRESP)) { + /* + * TODO: Reset the hardware, and maybe move the printk + * to a lower-priority context as well (work queue?) + */ + printk(KERN_ERR "%s: DMA bus error: HRESP not OK\n", + dev->name); + } + + status = macb_readl(bp, ISR); + } + + spin_unlock(&bp->lock); + + return IRQ_HANDLED; +} + +static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + dma_addr_t mapping; + unsigned int len, entry; + u32 ctrl; + +#ifdef DEBUG + int i; + dev_dbg(&bp->pdev->dev, + "start_xmit: len %u head %p data %p tail %p end %p\n", + skb->len, skb->head, skb->data, skb->tail, skb->end); + dev_dbg(&bp->pdev->dev, + "data:"); + for (i = 0; i < 16; i++) + printk(" %02x", (unsigned int)skb->data[i]); + printk("\n"); +#endif + + len = skb->len; + spin_lock_irq(&bp->lock); + + /* This is a hard error, log it. */ + if (TX_BUFFS_AVAIL(bp) < 1) { + netif_stop_queue(dev); + spin_unlock_irq(&bp->lock); + dev_err(&bp->pdev->dev, + "BUG! Tx Ring full when queue awake!\n"); + dev_dbg(&bp->pdev->dev, "tx_head = %u, tx_tail = %u\n", + bp->tx_head, bp->tx_tail); + return 1; + } + + entry = bp->tx_head; + dev_dbg(&bp->pdev->dev, "Allocated ring entry %u\n", entry); + mapping = dma_map_single(&bp->pdev->dev, skb->data, + len, DMA_TO_DEVICE); + bp->tx_skb[entry].skb = skb; + bp->tx_skb[entry].mapping = mapping; + dev_dbg(&bp->pdev->dev, "Mapped skb data %p to DMA addr %08lx\n", + skb->data, (unsigned long)mapping); + + ctrl = MACB_BF(TX_FRMLEN, len); + ctrl |= MACB_BIT(TX_LAST); + if (entry == (TX_RING_SIZE - 1)) + ctrl |= MACB_BIT(TX_WRAP); + + bp->tx_ring[entry].addr = mapping; + bp->tx_ring[entry].ctrl = ctrl; + wmb(); + + entry = NEXT_TX(entry); + bp->tx_head = entry; + + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); + + if (TX_BUFFS_AVAIL(bp) < 1) + netif_stop_queue(dev); + + spin_unlock_irq(&bp->lock); + + dev->trans_start = jiffies; + + return 0; +} + +static void macb_free_consistent(struct macb *bp) +{ + if (bp->tx_skb) { + kfree(bp->tx_skb); + bp->tx_skb = NULL; + } + if (bp->rx_ring) { + dma_free_coherent(&bp->pdev->dev, RX_RING_BYTES, + bp->rx_ring, bp->rx_ring_dma); + bp->rx_ring = NULL; + } + if (bp->tx_ring) { + dma_free_coherent(&bp->pdev->dev, TX_RING_BYTES, + bp->tx_ring, bp->tx_ring_dma); + bp->tx_ring = NULL; + } + if (bp->rx_buffers) { + dma_free_coherent(&bp->pdev->dev, + RX_RING_SIZE * RX_BUFFER_SIZE, + bp->rx_buffers, bp->rx_buffers_dma); + bp->rx_buffers = NULL; + } +} + +static int macb_alloc_consistent(struct macb *bp) +{ + int size; + + size = TX_RING_SIZE * sizeof(struct ring_info); + bp->tx_skb = kmalloc(size, GFP_KERNEL); + if (!bp->tx_skb) + goto out_err; + + size = RX_RING_BYTES; + bp->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size, + &bp->rx_ring_dma, GFP_KERNEL); + if (!bp->rx_ring) + goto out_err; + dev_dbg(&bp->pdev->dev, + "Allocated RX ring of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_ring_dma, bp->rx_ring); + + size = TX_RING_BYTES; + bp->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, + &bp->tx_ring_dma, GFP_KERNEL); + if (!bp->tx_ring) + goto out_err; + dev_dbg(&bp->pdev->dev, + "Allocated TX ring of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->tx_ring_dma, bp->tx_ring); + + size = RX_RING_SIZE * RX_BUFFER_SIZE; + bp->rx_buffers = dma_alloc_coherent(&bp->pdev->dev, size, + &bp->rx_buffers_dma, GFP_KERNEL); + if (!bp->rx_buffers) + goto out_err; + dev_dbg(&bp->pdev->dev, + "Allocated RX buffers of %d bytes at %08lx (mapped %p)\n", + size, (unsigned long)bp->rx_buffers_dma, bp->rx_buffers); + + return 0; + +out_err: + macb_free_consistent(bp); + return -ENOMEM; +} + +static void macb_init_rings(struct macb *bp) +{ + int i; + dma_addr_t addr; + + addr = bp->rx_buffers_dma; + for (i = 0; i < RX_RING_SIZE; i++) { + bp->rx_ring[i].addr = addr; + bp->rx_ring[i].ctrl = 0; + addr += RX_BUFFER_SIZE; + } + bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + + for (i = 0; i < TX_RING_SIZE; i++) { + bp->tx_ring[i].addr = 0; + bp->tx_ring[i].ctrl = MACB_BIT(TX_USED); + } + bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); + + bp->rx_tail = bp->tx_head = bp->tx_tail = 0; +} + +static void macb_reset_hw(struct macb *bp) +{ + /* Make sure we have the write buffer for ourselves */ + wmb(); + + /* + * Disable RX and TX (XXX: Should we halt the transmission + * more gracefully?) + */ + macb_writel(bp, NCR, 0); + + /* Clear the stats registers (XXX: Update stats first?) */ + macb_writel(bp, NCR, MACB_BIT(CLRSTAT)); + + /* Clear all status flags */ + macb_writel(bp, TSR, ~0UL); + macb_writel(bp, RSR, ~0UL); + + /* Disable all interrupts */ + macb_writel(bp, IDR, ~0UL); + macb_readl(bp, ISR); +} + +static void macb_init_hw(struct macb *bp) +{ + u32 config; + + macb_reset_hw(bp); + __macb_set_hwaddr(bp); + + config = macb_readl(bp, NCFGR) & MACB_BF(CLK, -1L); + config |= MACB_BIT(PAE); /* PAuse Enable */ + config |= MACB_BIT(DRFCS); /* Discard Rx FCS */ + if (bp->dev->flags & IFF_PROMISC) + config |= MACB_BIT(CAF); /* Copy All Frames */ + if (!(bp->dev->flags & IFF_BROADCAST)) + config |= MACB_BIT(NBC); /* No BroadCast */ + macb_writel(bp, NCFGR, config); + + /* Initialize TX and RX buffers */ + macb_writel(bp, RBQP, bp->rx_ring_dma); + macb_writel(bp, TBQP, bp->tx_ring_dma); + + /* Enable TX and RX */ + macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE)); + + /* Enable interrupts */ + macb_writel(bp, IER, (MACB_BIT(RCOMP) + | MACB_BIT(RXUBR) + | MACB_BIT(ISR_TUND) + | MACB_BIT(ISR_RLE) + | MACB_BIT(TXERR) + | MACB_BIT(TCOMP) + | MACB_BIT(ISR_ROVR) + | MACB_BIT(HRESP))); +} + +static void macb_init_phy(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + + /* Set some reasonable default settings */ + macb_mdio_write(dev, bp->mii.phy_id, MII_ADVERTISE, + ADVERTISE_CSMA | ADVERTISE_ALL); + macb_mdio_write(dev, bp->mii.phy_id, MII_BMCR, + (BMCR_SPEED100 | BMCR_ANENABLE + | BMCR_ANRESTART | BMCR_FULLDPLX)); +} + +static int macb_open(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + int err; + + dev_dbg(&bp->pdev->dev, "open\n"); + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + err = macb_alloc_consistent(bp); + if (err) { + printk(KERN_ERR + "%s: Unable to allocate DMA memory (error %d)\n", + dev->name, err); + return err; + } + + macb_init_rings(bp); + macb_init_hw(bp); + macb_init_phy(dev); + + macb_check_media(bp, 1, 1); + netif_start_queue(dev); + + schedule_delayed_work(&bp->periodic_task, HZ); + + return 0; +} + +static int macb_close(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + unsigned long flags; + + cancel_rearming_delayed_work(&bp->periodic_task); + + netif_stop_queue(dev); + + spin_lock_irqsave(&bp->lock, flags); + macb_reset_hw(bp); + netif_carrier_off(dev); + spin_unlock_irqrestore(&bp->lock, flags); + + macb_free_consistent(bp); + + return 0; +} + +static struct net_device_stats *macb_get_stats(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + struct net_device_stats *nstat = &bp->stats; + struct macb_stats *hwstat = &bp->hw_stats; + + /* Convert HW stats into netdevice stats */ + nstat->rx_errors = (hwstat->rx_fcs_errors + + hwstat->rx_align_errors + + hwstat->rx_resource_errors + + hwstat->rx_overruns + + hwstat->rx_oversize_pkts + + hwstat->rx_jabbers + + hwstat->rx_undersize_pkts + + hwstat->sqe_test_errors + + hwstat->rx_length_mismatch); + nstat->tx_errors = (hwstat->tx_late_cols + + hwstat->tx_excessive_cols + + hwstat->tx_underruns + + hwstat->tx_carrier_errors); + nstat->collisions = (hwstat->tx_single_cols + + hwstat->tx_multiple_cols + + hwstat->tx_excessive_cols); + nstat->rx_length_errors = (hwstat->rx_oversize_pkts + + hwstat->rx_jabbers + + hwstat->rx_undersize_pkts + + hwstat->rx_length_mismatch); + nstat->rx_over_errors = hwstat->rx_resource_errors; + nstat->rx_crc_errors = hwstat->rx_fcs_errors; + nstat->rx_frame_errors = hwstat->rx_align_errors; + nstat->rx_fifo_errors = hwstat->rx_overruns; + /* XXX: What does "missed" mean? */ + nstat->tx_aborted_errors = hwstat->tx_excessive_cols; + nstat->tx_carrier_errors = hwstat->tx_carrier_errors; + nstat->tx_fifo_errors = hwstat->tx_underruns; + /* Don't know about heartbeat or window errors... */ + + return nstat; +} + +static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct macb *bp = netdev_priv(dev); + int ret; + unsigned long flags; + + spin_lock_irqsave(&bp->lock, flags); + ret = mii_ethtool_gset(&bp->mii, cmd); + spin_unlock_irqrestore(&bp->lock, flags); + + return ret; +} + +static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct macb *bp = netdev_priv(dev); + int ret; + unsigned long flags; + + spin_lock_irqsave(&bp->lock, flags); + ret = mii_ethtool_sset(&bp->mii, cmd); + spin_unlock_irqrestore(&bp->lock, flags); + + return ret; +} + +static void macb_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct macb *bp = netdev_priv(dev); + + strcpy(info->driver, bp->pdev->dev.driver->name); + strcpy(info->version, "$Revision: 1.14 $"); + strcpy(info->bus_info, bp->pdev->dev.bus_id); +} + +static int macb_nway_reset(struct net_device *dev) +{ + struct macb *bp = netdev_priv(dev); + return mii_nway_restart(&bp->mii); +} + +static struct ethtool_ops macb_ethtool_ops = { + .get_settings = macb_get_settings, + .set_settings = macb_set_settings, + .get_drvinfo = macb_get_drvinfo, + .nway_reset = macb_nway_reset, + .get_link = ethtool_op_get_link, +}; + +static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct macb *bp = netdev_priv(dev); + int ret; + unsigned long flags; + + if (!netif_running(dev)) + return -EINVAL; + + spin_lock_irqsave(&bp->lock, flags); + ret = generic_mii_ioctl(&bp->mii, if_mii(rq), cmd, NULL); + spin_unlock_irqrestore(&bp->lock, flags); + + return ret; +} + +static ssize_t macb_mii_show(const struct class_device *cd, char *buf, + unsigned long addr) +{ + struct net_device *dev = to_net_dev(cd); + struct macb *bp = netdev_priv(dev); + ssize_t ret = -EINVAL; + + if (netif_running(dev)) { + int value; + value = macb_mdio_read(dev, bp->mii.phy_id, addr); + ret = sprintf(buf, "0x%04x\n", (uint16_t)value); + } + + return ret; +} + +#define MII_ENTRY(name, addr) \ +static ssize_t show_##name(struct class_device *cd, char *buf) \ +{ \ + return macb_mii_show(cd, buf, addr); \ +} \ +static CLASS_DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) + +MII_ENTRY(bmcr, MII_BMCR); +MII_ENTRY(bmsr, MII_BMSR); +MII_ENTRY(physid1, MII_PHYSID1); +MII_ENTRY(physid2, MII_PHYSID2); +MII_ENTRY(advertise, MII_ADVERTISE); +MII_ENTRY(lpa, MII_LPA); +MII_ENTRY(expansion, MII_EXPANSION); + +static struct attribute *macb_mii_attrs[] = { + &class_device_attr_bmcr.attr, + &class_device_attr_bmsr.attr, + &class_device_attr_physid1.attr, + &class_device_attr_physid2.attr, + &class_device_attr_advertise.attr, + &class_device_attr_lpa.attr, + &class_device_attr_expansion.attr, + NULL, +}; + +static struct attribute_group macb_mii_group = { + .name = "mii", + .attrs = macb_mii_attrs, +}; + +static void macb_unregister_sysfs(struct net_device *net) +{ + struct class_device *class_dev = &net->class_dev; + + sysfs_remove_group(&class_dev->kobj, &macb_mii_group); +} + +static int macb_register_sysfs(struct net_device *net) +{ + struct class_device *class_dev = &net->class_dev; + int ret; + + ret = sysfs_create_group(&class_dev->kobj, &macb_mii_group); + if (ret) + printk(KERN_WARNING + "%s: sysfs mii attribute registration failed: %d\n", + net->name, ret); + return ret; +} +static int __devinit macb_probe(struct platform_device *pdev) +{ + struct eth_platform_data *pdata; + struct resource *regs; + struct net_device *dev; + struct macb *bp; + unsigned long pclk_hz; + u32 config; + int err = -ENXIO; + + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "no mmio resource defined\n"); + goto err_out; + } + + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) { + dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + goto err_out; + } + + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + + /* TODO: Actually, we have some interesting features... */ + dev->features |= 0; + + bp = netdev_priv(dev); + bp->pdev = pdev; + bp->dev = dev; + + spin_lock_init(&bp->lock); + + bp->pclk = clk_get(&pdev->dev, "pclk"); + if (IS_ERR(bp->pclk)) { + dev_err(&pdev->dev, "failed to get pclk\n"); + goto err_out_free_dev; + } + bp->hclk = clk_get(&pdev->dev, "hclk"); + if (IS_ERR(bp->hclk)) { + dev_err(&pdev->dev, "failed to get hclk\n"); + goto err_out_put_pclk; + } + + clk_enable(bp->pclk); + clk_enable(bp->hclk); + + bp->regs = ioremap(regs->start, regs->end - regs->start + 1); + if (!bp->regs) { + dev_err(&pdev->dev, "failed to map registers, aborting.\n"); + err = -ENOMEM; + goto err_out_disable_clocks; + } + + dev->irq = platform_get_irq(pdev, 0); + err = request_irq(dev->irq, macb_interrupt, SA_SAMPLE_RANDOM, + dev->name, dev); + if (err) { + printk(KERN_ERR + "%s: Unable to request IRQ %d (error %d)\n", + dev->name, dev->irq, err); + goto err_out_iounmap; + } + + dev->open = macb_open; + dev->stop = macb_close; + dev->hard_start_xmit = macb_start_xmit; + dev->get_stats = macb_get_stats; + dev->do_ioctl = macb_ioctl; + dev->poll = macb_poll; + dev->weight = 64; + dev->ethtool_ops = &macb_ethtool_ops; + + dev->base_addr = regs->start; + + INIT_WORK(&bp->periodic_task, macb_periodic_task, bp); + mutex_init(&bp->mdio_mutex); + init_completion(&bp->mdio_complete); + + /* Set MII management clock divider */ + pclk_hz = clk_get_rate(bp->pclk); + if (pclk_hz <= 20000000) + config = MACB_BF(CLK, MACB_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = MACB_BF(CLK, MACB_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = MACB_BF(CLK, MACB_CLK_DIV32); + else + config = MACB_BF(CLK, MACB_CLK_DIV64); + macb_writel(bp, NCFGR, config); + + bp->mii.dev = dev; + bp->mii.mdio_read = macb_mdio_read; + bp->mii.mdio_write = macb_mdio_write; + bp->mii.phy_id_mask = 0x1f; + bp->mii.reg_num_mask = 0x1f; + + macb_get_hwaddr(bp); + err = macb_phy_probe(bp); + if (err) { + dev_err(&pdev->dev, "Failed to detect PHY, aborting.\n"); + goto err_out_free_irq; + } + + pdata = pdev->dev.platform_data; + if (pdata && pdata->is_rmii) + macb_writel(bp, USRIO, 0); + else + macb_writel(bp, USRIO, MACB_BIT(MII)); + + bp->tx_pending = DEF_TX_RING_PENDING; + + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); + goto err_out_free_irq; + } + + platform_set_drvdata(pdev, dev); + + macb_register_sysfs(dev); + + printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d " + "(%02x:%02x:%02x:%02x:%02x:%02x)\n", + dev->name, dev->base_addr, dev->irq, + dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], + dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); + + return 0; + +err_out_free_irq: + free_irq(dev->irq, dev); +err_out_iounmap: + iounmap(bp->regs); +err_out_disable_clocks: + clk_disable(bp->hclk); + clk_disable(bp->pclk); + clk_put(bp->hclk); +err_out_put_pclk: + clk_put(bp->pclk); +err_out_free_dev: + free_netdev(dev); +err_out: + platform_set_drvdata(pdev, NULL); + return err; +} + +static int __devexit macb_remove(struct platform_device *pdev) +{ + struct net_device *dev; + struct macb *bp; + + dev = platform_get_drvdata(pdev); + + if (dev) { + bp = netdev_priv(dev); + macb_unregister_sysfs(dev); + unregister_netdev(dev); + free_irq(dev->irq, dev); + iounmap(bp->regs); + clk_disable(bp->hclk); + clk_disable(bp->pclk); + clk_put(bp->hclk); + clk_put(bp->pclk); + free_netdev(dev); + platform_set_drvdata(pdev, NULL); + } + + return 0; +} + +static struct platform_driver macb_driver = { + .probe = macb_probe, + .remove = __devexit_p(macb_remove), + .driver = { + .name = "macb", + }, +}; + +static int __init macb_init(void) +{ + return platform_driver_register(&macb_driver); +} + +static void __exit macb_exit(void) +{ + platform_driver_unregister(&macb_driver); +} + +module_init(macb_init); +module_exit(macb_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); +MODULE_AUTHOR("Haavard Skinnemoen "); diff --git a/drivers/net/macb.h b/drivers/net/macb.h new file mode 100644 index 000000000000..8c253db69881 --- /dev/null +++ b/drivers/net/macb.h @@ -0,0 +1,387 @@ +/* + * Atmel MACB Ethernet Controller driver + * + * Copyright (C) 2004-2006 Atmel Corporation + * + * 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. + */ +#ifndef _MACB_H +#define _MACB_H + +/* MACB register offsets */ +#define MACB_NCR 0x0000 +#define MACB_NCFGR 0x0004 +#define MACB_NSR 0x0008 +#define MACB_TSR 0x0014 +#define MACB_RBQP 0x0018 +#define MACB_TBQP 0x001c +#define MACB_RSR 0x0020 +#define MACB_ISR 0x0024 +#define MACB_IER 0x0028 +#define MACB_IDR 0x002c +#define MACB_IMR 0x0030 +#define MACB_MAN 0x0034 +#define MACB_PTR 0x0038 +#define MACB_PFR 0x003c +#define MACB_FTO 0x0040 +#define MACB_SCF 0x0044 +#define MACB_MCF 0x0048 +#define MACB_FRO 0x004c +#define MACB_FCSE 0x0050 +#define MACB_ALE 0x0054 +#define MACB_DTF 0x0058 +#define MACB_LCOL 0x005c +#define MACB_EXCOL 0x0060 +#define MACB_TUND 0x0064 +#define MACB_CSE 0x0068 +#define MACB_RRE 0x006c +#define MACB_ROVR 0x0070 +#define MACB_RSE 0x0074 +#define MACB_ELE 0x0078 +#define MACB_RJA 0x007c +#define MACB_USF 0x0080 +#define MACB_STE 0x0084 +#define MACB_RLE 0x0088 +#define MACB_TPF 0x008c +#define MACB_HRB 0x0090 +#define MACB_HRT 0x0094 +#define MACB_SA1B 0x0098 +#define MACB_SA1T 0x009c +#define MACB_SA2B 0x00a0 +#define MACB_SA2T 0x00a4 +#define MACB_SA3B 0x00a8 +#define MACB_SA3T 0x00ac +#define MACB_SA4B 0x00b0 +#define MACB_SA4T 0x00b4 +#define MACB_TID 0x00b8 +#define MACB_TPQ 0x00bc +#define MACB_USRIO 0x00c0 +#define MACB_WOL 0x00c4 + +/* Bitfields in NCR */ +#define MACB_LB_OFFSET 0 +#define MACB_LB_SIZE 1 +#define MACB_LLB_OFFSET 1 +#define MACB_LLB_SIZE 1 +#define MACB_RE_OFFSET 2 +#define MACB_RE_SIZE 1 +#define MACB_TE_OFFSET 3 +#define MACB_TE_SIZE 1 +#define MACB_MPE_OFFSET 4 +#define MACB_MPE_SIZE 1 +#define MACB_CLRSTAT_OFFSET 5 +#define MACB_CLRSTAT_SIZE 1 +#define MACB_INCSTAT_OFFSET 6 +#define MACB_INCSTAT_SIZE 1 +#define MACB_WESTAT_OFFSET 7 +#define MACB_WESTAT_SIZE 1 +#define MACB_BP_OFFSET 8 +#define MACB_BP_SIZE 1 +#define MACB_TSTART_OFFSET 9 +#define MACB_TSTART_SIZE 1 +#define MACB_THALT_OFFSET 10 +#define MACB_THALT_SIZE 1 +#define MACB_NCR_TPF_OFFSET 11 +#define MACB_NCR_TPF_SIZE 1 +#define MACB_TZQ_OFFSET 12 +#define MACB_TZQ_SIZE 1 + +/* Bitfields in NCFGR */ +#define MACB_SPD_OFFSET 0 +#define MACB_SPD_SIZE 1 +#define MACB_FD_OFFSET 1 +#define MACB_FD_SIZE 1 +#define MACB_BIT_RATE_OFFSET 2 +#define MACB_BIT_RATE_SIZE 1 +#define MACB_JFRAME_OFFSET 3 +#define MACB_JFRAME_SIZE 1 +#define MACB_CAF_OFFSET 4 +#define MACB_CAF_SIZE 1 +#define MACB_NBC_OFFSET 5 +#define MACB_NBC_SIZE 1 +#define MACB_NCFGR_MTI_OFFSET 6 +#define MACB_NCFGR_MTI_SIZE 1 +#define MACB_UNI_OFFSET 7 +#define MACB_UNI_SIZE 1 +#define MACB_BIG_OFFSET 8 +#define MACB_BIG_SIZE 1 +#define MACB_EAE_OFFSET 9 +#define MACB_EAE_SIZE 1 +#define MACB_CLK_OFFSET 10 +#define MACB_CLK_SIZE 2 +#define MACB_RTY_OFFSET 12 +#define MACB_RTY_SIZE 1 +#define MACB_PAE_OFFSET 13 +#define MACB_PAE_SIZE 1 +#define MACB_RBOF_OFFSET 14 +#define MACB_RBOF_SIZE 2 +#define MACB_RLCE_OFFSET 16 +#define MACB_RLCE_SIZE 1 +#define MACB_DRFCS_OFFSET 17 +#define MACB_DRFCS_SIZE 1 +#define MACB_EFRHD_OFFSET 18 +#define MACB_EFRHD_SIZE 1 +#define MACB_IRXFCS_OFFSET 19 +#define MACB_IRXFCS_SIZE 1 + +/* Bitfields in NSR */ +#define MACB_NSR_LINK_OFFSET 0 +#define MACB_NSR_LINK_SIZE 1 +#define MACB_MDIO_OFFSET 1 +#define MACB_MDIO_SIZE 1 +#define MACB_IDLE_OFFSET 2 +#define MACB_IDLE_SIZE 1 + +/* Bitfields in TSR */ +#define MACB_UBR_OFFSET 0 +#define MACB_UBR_SIZE 1 +#define MACB_COL_OFFSET 1 +#define MACB_COL_SIZE 1 +#define MACB_TSR_RLE_OFFSET 2 +#define MACB_TSR_RLE_SIZE 1 +#define MACB_TGO_OFFSET 3 +#define MACB_TGO_SIZE 1 +#define MACB_BEX_OFFSET 4 +#define MACB_BEX_SIZE 1 +#define MACB_COMP_OFFSET 5 +#define MACB_COMP_SIZE 1 +#define MACB_UND_OFFSET 6 +#define MACB_UND_SIZE 1 + +/* Bitfields in RSR */ +#define MACB_BNA_OFFSET 0 +#define MACB_BNA_SIZE 1 +#define MACB_REC_OFFSET 1 +#define MACB_REC_SIZE 1 +#define MACB_OVR_OFFSET 2 +#define MACB_OVR_SIZE 1 + +/* Bitfields in ISR/IER/IDR/IMR */ +#define MACB_MFD_OFFSET 0 +#define MACB_MFD_SIZE 1 +#define MACB_RCOMP_OFFSET 1 +#define MACB_RCOMP_SIZE 1 +#define MACB_RXUBR_OFFSET 2 +#define MACB_RXUBR_SIZE 1 +#define MACB_TXUBR_OFFSET 3 +#define MACB_TXUBR_SIZE 1 +#define MACB_ISR_TUND_OFFSET 4 +#define MACB_ISR_TUND_SIZE 1 +#define MACB_ISR_RLE_OFFSET 5 +#define MACB_ISR_RLE_SIZE 1 +#define MACB_TXERR_OFFSET 6 +#define MACB_TXERR_SIZE 1 +#define MACB_TCOMP_OFFSET 7 +#define MACB_TCOMP_SIZE 1 +#define MACB_ISR_LINK_OFFSET 9 +#define MACB_ISR_LINK_SIZE 1 +#define MACB_ISR_ROVR_OFFSET 10 +#define MACB_ISR_ROVR_SIZE 1 +#define MACB_HRESP_OFFSET 11 +#define MACB_HRESP_SIZE 1 +#define MACB_PFR_OFFSET 12 +#define MACB_PFR_SIZE 1 +#define MACB_PTZ_OFFSET 13 +#define MACB_PTZ_SIZE 1 + +/* Bitfields in MAN */ +#define MACB_DATA_OFFSET 0 +#define MACB_DATA_SIZE 16 +#define MACB_CODE_OFFSET 16 +#define MACB_CODE_SIZE 2 +#define MACB_REGA_OFFSET 18 +#define MACB_REGA_SIZE 5 +#define MACB_PHYA_OFFSET 23 +#define MACB_PHYA_SIZE 5 +#define MACB_RW_OFFSET 28 +#define MACB_RW_SIZE 2 +#define MACB_SOF_OFFSET 30 +#define MACB_SOF_SIZE 2 + +/* Bitfields in USRIO */ +#define MACB_MII_OFFSET 0 +#define MACB_MII_SIZE 1 +#define MACB_EAM_OFFSET 1 +#define MACB_EAM_SIZE 1 +#define MACB_TX_PAUSE_OFFSET 2 +#define MACB_TX_PAUSE_SIZE 1 +#define MACB_TX_PAUSE_ZERO_OFFSET 3 +#define MACB_TX_PAUSE_ZERO_SIZE 1 + +/* Bitfields in WOL */ +#define MACB_IP_OFFSET 0 +#define MACB_IP_SIZE 16 +#define MACB_MAG_OFFSET 16 +#define MACB_MAG_SIZE 1 +#define MACB_ARP_OFFSET 17 +#define MACB_ARP_SIZE 1 +#define MACB_SA1_OFFSET 18 +#define MACB_SA1_SIZE 1 +#define MACB_WOL_MTI_OFFSET 19 +#define MACB_WOL_MTI_SIZE 1 + +/* Constants for CLK */ +#define MACB_CLK_DIV8 0 +#define MACB_CLK_DIV16 1 +#define MACB_CLK_DIV32 2 +#define MACB_CLK_DIV64 3 + +/* Constants for MAN register */ +#define MACB_MAN_SOF 1 +#define MACB_MAN_WRITE 1 +#define MACB_MAN_READ 2 +#define MACB_MAN_CODE 2 + +/* Bit manipulation macros */ +#define MACB_BIT(name) \ + (1 << MACB_##name##_OFFSET) +#define MACB_BF(name,value) \ + (((value) & ((1 << MACB_##name##_SIZE) - 1)) \ + << MACB_##name##_OFFSET) +#define MACB_BFEXT(name,value)\ + (((value) >> MACB_##name##_OFFSET) \ + & ((1 << MACB_##name##_SIZE) - 1)) +#define MACB_BFINS(name,value,old) \ + (((old) & ~(((1 << MACB_##name##_SIZE) - 1) \ + << MACB_##name##_OFFSET)) \ + | MACB_BF(name,value)) + +/* Register access macros */ +#define macb_readl(port,reg) \ + readl((port)->regs + MACB_##reg) +#define macb_writel(port,reg,value) \ + writel((value), (port)->regs + MACB_##reg) + +struct dma_desc { + u32 addr; + u32 ctrl; +}; + +/* DMA descriptor bitfields */ +#define MACB_RX_USED_OFFSET 0 +#define MACB_RX_USED_SIZE 1 +#define MACB_RX_WRAP_OFFSET 1 +#define MACB_RX_WRAP_SIZE 1 +#define MACB_RX_WADDR_OFFSET 2 +#define MACB_RX_WADDR_SIZE 30 + +#define MACB_RX_FRMLEN_OFFSET 0 +#define MACB_RX_FRMLEN_SIZE 12 +#define MACB_RX_OFFSET_OFFSET 12 +#define MACB_RX_OFFSET_SIZE 2 +#define MACB_RX_SOF_OFFSET 14 +#define MACB_RX_SOF_SIZE 1 +#define MACB_RX_EOF_OFFSET 15 +#define MACB_RX_EOF_SIZE 1 +#define MACB_RX_CFI_OFFSET 16 +#define MACB_RX_CFI_SIZE 1 +#define MACB_RX_VLAN_PRI_OFFSET 17 +#define MACB_RX_VLAN_PRI_SIZE 3 +#define MACB_RX_PRI_TAG_OFFSET 20 +#define MACB_RX_PRI_TAG_SIZE 1 +#define MACB_RX_VLAN_TAG_OFFSET 21 +#define MACB_RX_VLAN_TAG_SIZE 1 +#define MACB_RX_TYPEID_MATCH_OFFSET 22 +#define MACB_RX_TYPEID_MATCH_SIZE 1 +#define MACB_RX_SA4_MATCH_OFFSET 23 +#define MACB_RX_SA4_MATCH_SIZE 1 +#define MACB_RX_SA3_MATCH_OFFSET 24 +#define MACB_RX_SA3_MATCH_SIZE 1 +#define MACB_RX_SA2_MATCH_OFFSET 25 +#define MACB_RX_SA2_MATCH_SIZE 1 +#define MACB_RX_SA1_MATCH_OFFSET 26 +#define MACB_RX_SA1_MATCH_SIZE 1 +#define MACB_RX_EXT_MATCH_OFFSET 28 +#define MACB_RX_EXT_MATCH_SIZE 1 +#define MACB_RX_UHASH_MATCH_OFFSET 29 +#define MACB_RX_UHASH_MATCH_SIZE 1 +#define MACB_RX_MHASH_MATCH_OFFSET 30 +#define MACB_RX_MHASH_MATCH_SIZE 1 +#define MACB_RX_BROADCAST_OFFSET 31 +#define MACB_RX_BROADCAST_SIZE 1 + +#define MACB_TX_FRMLEN_OFFSET 0 +#define MACB_TX_FRMLEN_SIZE 11 +#define MACB_TX_LAST_OFFSET 15 +#define MACB_TX_LAST_SIZE 1 +#define MACB_TX_NOCRC_OFFSET 16 +#define MACB_TX_NOCRC_SIZE 1 +#define MACB_TX_BUF_EXHAUSTED_OFFSET 27 +#define MACB_TX_BUF_EXHAUSTED_SIZE 1 +#define MACB_TX_UNDERRUN_OFFSET 28 +#define MACB_TX_UNDERRUN_SIZE 1 +#define MACB_TX_ERROR_OFFSET 29 +#define MACB_TX_ERROR_SIZE 1 +#define MACB_TX_WRAP_OFFSET 30 +#define MACB_TX_WRAP_SIZE 1 +#define MACB_TX_USED_OFFSET 31 +#define MACB_TX_USED_SIZE 1 + +struct ring_info { + struct sk_buff *skb; + dma_addr_t mapping; +}; + +/* + * Hardware-collected statistics. Used when updating the network + * device stats by a periodic timer. + */ +struct macb_stats { + u32 rx_pause_frames; + u32 tx_ok; + u32 tx_single_cols; + u32 tx_multiple_cols; + u32 rx_ok; + u32 rx_fcs_errors; + u32 rx_align_errors; + u32 tx_deferred; + u32 tx_late_cols; + u32 tx_excessive_cols; + u32 tx_underruns; + u32 tx_carrier_errors; + u32 rx_resource_errors; + u32 rx_overruns; + u32 rx_symbol_errors; + u32 rx_oversize_pkts; + u32 rx_jabbers; + u32 rx_undersize_pkts; + u32 sqe_test_errors; + u32 rx_length_mismatch; + u32 tx_pause_frames; +}; + +struct macb { + void __iomem *regs; + + unsigned int rx_tail; + struct dma_desc *rx_ring; + void *rx_buffers; + + unsigned int tx_head, tx_tail; + struct dma_desc *tx_ring; + struct ring_info *tx_skb; + + spinlock_t lock; + struct platform_device *pdev; + struct clk *pclk; + struct clk *hclk; + struct net_device *dev; + struct net_device_stats stats; + struct macb_stats hw_stats; + + dma_addr_t rx_ring_dma; + dma_addr_t tx_ring_dma; + dma_addr_t rx_buffers_dma; + + unsigned int rx_pending, tx_pending; + + struct work_struct periodic_task; + + struct mutex mdio_mutex; + struct completion mdio_complete; + struct mii_if_info mii; +}; + +#endif /* _MACB_H */ -- cgit v1.2.3 From cefd9f7f1281c1ead03236f227dad4b163619705 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 14 Nov 2006 11:46:41 -0500 Subject: Revert "[PATCH] Add support for Marvell 88e1111S and 88e1145" This reverts commit 477c517903d57047150b01608149e02c6e9d83dd. This patch depended on something that was not yet committed. --- drivers/net/phy/marvell.c | 156 ++++------------------------------------------ 1 file changed, 12 insertions(+), 144 deletions(-) (limited to 'drivers') diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5320ab9fe018..0ad253282d0d 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -43,19 +43,6 @@ #define MII_M1011_IMASK_INIT 0x6400 #define MII_M1011_IMASK_CLEAR 0x0000 -#define MII_M1011_PHY_SCR 0x10 -#define MII_M1011_PHY_SCR_AUTO_CROSS 0x0060 - -#define MII_M1145_PHY_EXT_CR 0x14 -#define MII_M1145_RGMII_RX_DELAY 0x0080 -#define MII_M1145_RGMII_TX_DELAY 0x0002 - -#define M1145_DEV_FLAGS_RESISTANCE 0x00000001 - -#define MII_M1111_PHY_LED_CONTROL 0x18 -#define MII_M1111_PHY_LED_DIRECT 0x4100 -#define MII_M1111_PHY_LED_COMBINE 0x411c - MODULE_DESCRIPTION("Marvell PHY driver"); MODULE_AUTHOR("Andy Fleming"); MODULE_LICENSE("GPL"); @@ -77,7 +64,7 @@ static int marvell_config_intr(struct phy_device *phydev) { int err; - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + if(phydev->interrupts == PHY_INTERRUPT_ENABLED) err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_INIT); else err = phy_write(phydev, MII_M1011_IMASK, MII_M1011_IMASK_CLEAR); @@ -117,153 +104,34 @@ static int marvell_config_aneg(struct phy_device *phydev) if (err < 0) return err; - err = phy_write(phydev, MII_M1011_PHY_SCR, - MII_M1011_PHY_SCR_AUTO_CROSS); - if (err < 0) - return err; - - err = phy_write(phydev, MII_M1111_PHY_LED_CONTROL, - MII_M1111_PHY_LED_DIRECT); - if (err < 0) - return err; err = genphy_config_aneg(phydev); return err; } -static int m88e1145_config_init(struct phy_device *phydev) -{ - int err; - - /* Take care of errata E0 & E1 */ - err = phy_write(phydev, 0x1d, 0x001b); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x418f); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x0016); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0xa2da); - if (err < 0) - return err; - - if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { - int temp = phy_read(phydev, MII_M1145_PHY_EXT_CR); - if (temp < 0) - return temp; - - temp |= (MII_M1145_RGMII_RX_DELAY | MII_M1145_RGMII_TX_DELAY); - - err = phy_write(phydev, MII_M1145_PHY_EXT_CR, temp); - if (err < 0) - return err; - - if (phydev->dev_flags & M1145_DEV_FLAGS_RESISTANCE) { - err = phy_write(phydev, 0x1d, 0x0012); - if (err < 0) - return err; - - temp = phy_read(phydev, 0x1e); - if (temp < 0) - return temp; - - temp &= 0xf03f; - temp |= 2 << 9; /* 36 ohm */ - temp |= 2 << 6; /* 39 ohm */ - - err = phy_write(phydev, 0x1e, temp); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1d, 0x3); - if (err < 0) - return err; - - err = phy_write(phydev, 0x1e, 0x8000); - if (err < 0) - return err; - } - } - - return 0; -} static struct phy_driver m88e1101_driver = { - .phy_id = 0x01410c60, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1101", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1111s_driver = { - .phy_id = 0x01410cc0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1111", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, -}; - -static struct phy_driver m88e1145_driver = { - .phy_id = 0x01410cd0, - .phy_id_mask = 0xfffffff0, - .name = "Marvell 88E1145", - .features = PHY_GBIT_FEATURES, - .flags = PHY_HAS_INTERRUPT, - .config_init = &m88e1145_config_init, - .config_aneg = &marvell_config_aneg, - .read_status = &genphy_read_status, - .ack_interrupt = &marvell_ack_interrupt, - .config_intr = &marvell_config_intr, - .driver = {.owner = THIS_MODULE,}, + .phy_id = 0x01410c00, + .phy_id_mask = 0xffffff00, + .name = "Marvell 88E1101", + .features = PHY_GBIT_FEATURES, + .flags = PHY_HAS_INTERRUPT, + .config_aneg = &marvell_config_aneg, + .read_status = &genphy_read_status, + .ack_interrupt = &marvell_ack_interrupt, + .config_intr = &marvell_config_intr, + .driver = { .owner = THIS_MODULE,}, }; static int __init marvell_init(void) { - int ret; - - ret = phy_driver_register(&m88e1101_driver); - if (ret) - return ret; - - ret = phy_driver_register(&m88e1111s_driver); - if (ret) - goto err1111s; - - ret = phy_driver_register(&m88e1145_driver); - if (ret) - goto err1145; - - return 0; - - err1145: - phy_driver_unregister(&m88e1111s_driver); - err1111s: - phy_driver_unregister(&m88e1101_driver); - return ret; + return phy_driver_register(&m88e1101_driver); } static void __exit marvell_exit(void) { phy_driver_unregister(&m88e1101_driver); - phy_driver_unregister(&m88e1111s_driver); - phy_driver_unregister(&m88e1145_driver); } module_init(marvell_init); -- cgit v1.2.3 From b6d2b1db0637ff35127f3cc38c04f289a0ee0579 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 8 Nov 2006 11:04:49 -0600 Subject: [PATCH] bcm43xx: correct "Move IV/ICV stripping into ieee80211_rx" In the patch sent by Daniel Drake under the title "[PATCH] ieee80211: Move IV/ICV stripping into ieee80211_rx", a needed line was accidentally removed. (NOTE: I'm pretty sure this was my fault, not Daniel's. -- JWL) Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c index a957bc861382..3e2462671690 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c @@ -543,6 +543,7 @@ int bcm43xx_rx(struct bcm43xx_private *bcm, break; } + frame_ctl = le16_to_cpu(wlhdr->frame_ctl); switch (WLAN_FC_GET_TYPE(frame_ctl)) { case IEEE80211_FTYPE_MGMT: ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); -- cgit v1.2.3 From e72ba2d328331e9687f0105a7937ea1b1969246c Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 14 Nov 2006 20:08:53 -0500 Subject: [PATCH] prism54: correct overly aggressive check of return from pci_set_mwi Failure of pci_set_mwi should not be considered a fatal error. Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_hotplug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index e0bca3abdf68..58257b40c043 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -170,8 +170,8 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); /* enable MWI */ - if (pci_set_mwi(pdev)) - goto do_pci_release_regions; + if (!pci_set_mwi(pdev)) + printk(KERN_INFO "%s: pci_set_mwi(pdev) succeeded\n", DRV_NAME); /* setup the network device interface and its structure */ if (!(ndev = islpci_setup(pdev))) { -- cgit v1.2.3 From 229782a336ab21b8eb7aa91dcb0dbdf728e95aef Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 17 Nov 2006 00:13:48 +0000 Subject: [PATCH] zd1211rw: Add ID for Planex GW-US54Mini zd1211 chip 14ea:ab13 v4330 high 00-90-cc AL2230_RF pa0 g--- Tested by Tetsuya Yatagai. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 7917153a92e9..ca54830dfdb5 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -51,6 +51,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 }, { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, + { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, /* ZD1211B */ { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, -- cgit v1.2.3 From 8e87295b9578fa46b5f325a7dc42ddbbdad6e0d0 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 17 Nov 2006 00:26:40 +0000 Subject: [PATCH] zd1211rw: Add ID for Belkin F5D7050 v4000 zd1211b chip 050d:705c v4810 high 00-17-3f AL2230_RF pa0 g--N Tested by Bryan Barnard Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index ca54830dfdb5..34524b73324f 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -57,6 +57,7 @@ static struct usb_device_id usb_ids[] = { { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, + { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B }, /* "Driverless" devices that need ejecting */ { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, {} -- cgit v1.2.3 From 84bc715c465f76584fc5127955fca0c61592e04b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 00:05:30 +0000 Subject: [PATCH] zd1211rw: Remove IW_FREQ_AUTO support http://bugzilla.kernel.org/show_bug.cgi?id=7399 zd1211rw's support for IW_FREQ_AUTO is broken: when specified, the driver tries to change to a channel specified in an uninitialized integer. As IW_FREQ_AUTO is hard to implement properly, the solution (at least for now) is to drop support for it and start ignoring the flags like all other wireless drivers do. This has the added advantage that kismet also starts working with zd1211rw, even though kismet requesting IW_FREQ_AUTO is also a bug (fixed in their svn) Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_ieee80211.c | 3 --- drivers/net/wireless/zd1211rw/zd_mac.c | 17 ++++------------- drivers/net/wireless/zd1211rw/zd_mac.h | 6 +----- drivers/net/wireless/zd1211rw/zd_netdev.c | 13 +------------ 4 files changed, 6 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c index 66905f7b61ff..1b215a099745 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c @@ -133,9 +133,6 @@ int zd_find_channel(u8 *channel, const struct iw_freq *freq) int i, r; u32 mhz; - if (!(freq->flags & IW_FREQ_FIXED)) - return 0; - if (freq->m < 1000) { if (freq->m > NUM_CHANNELS || freq->m == 0) return -EINVAL; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index e5fedf968c19..7845b6dac832 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -317,21 +317,12 @@ int zd_mac_request_channel(struct zd_mac *mac, u8 channel) return 0; } -int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags) +u8 zd_mac_get_channel(struct zd_mac *mac) { - struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac); + u8 channel = zd_chip_get_channel(&mac->chip); - *channel = zd_chip_get_channel(&mac->chip); - if (ieee->iw_mode != IW_MODE_INFRA) { - spin_lock_irq(&mac->lock); - *flags = *channel == mac->requested_channel ? - MAC_FIXED_CHANNEL : 0; - spin_unlock(&mac->lock); - } else { - *flags = 0; - } - dev_dbg_f(zd_mac_dev(mac), "channel %u flags %u\n", *channel, *flags); - return 0; + dev_dbg_f(zd_mac_dev(mac), "channel %u\n", channel); + return channel; } /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index e4dd40a6fec3..3feb292651df 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -116,10 +116,6 @@ struct rx_status { #define ZD_RX_CRC16_ERROR 0x40 #define ZD_RX_ERROR 0x80 -enum mac_flags { - MAC_FIXED_CHANNEL = 0x01, -}; - struct housekeeping { struct work_struct link_led_work; }; @@ -180,7 +176,7 @@ int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain); u8 zd_mac_get_regdomain(struct zd_mac *zd_mac); int zd_mac_request_channel(struct zd_mac *mac, u8 channel); -int zd_mac_get_channel(struct zd_mac *mac, u8 *channel, u8 *flags); +u8 zd_mac_get_channel(struct zd_mac *mac); int zd_mac_set_mode(struct zd_mac *mac, u32 mode); int zd_mac_get_mode(struct zd_mac *mac, u32 *mode); diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c index af3a7b36d078..60f1b0f6d45b 100644 --- a/drivers/net/wireless/zd1211rw/zd_netdev.c +++ b/drivers/net/wireless/zd1211rw/zd_netdev.c @@ -107,21 +107,10 @@ static int iw_get_freq(struct net_device *netdev, struct iw_request_info *info, union iwreq_data *req, char *extra) { - int r; struct zd_mac *mac = zd_netdev_mac(netdev); struct iw_freq *freq = &req->freq; - u8 channel; - u8 flags; - - r = zd_mac_get_channel(mac, &channel, &flags); - if (r) - return r; - freq->flags = (flags & MAC_FIXED_CHANNEL) ? - IW_FREQ_FIXED : IW_FREQ_AUTO; - dev_dbg_f(zd_mac_dev(mac), "channel %s\n", - (flags & MAC_FIXED_CHANNEL) ? "fixed" : "auto"); - return zd_channel_to_freq(freq, channel); + return zd_channel_to_freq(freq, zd_mac_get_channel(mac)); } static int iw_set_mode(struct net_device *netdev, -- cgit v1.2.3 From 741fec53f268b691b869ffc70023319406e0cc97 Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Wed, 22 Nov 2006 00:05:53 +0000 Subject: [PATCH] zd1211rw: cleanups Bit-field constants in zd_chip.h are now defined using a shift expression. The value 0x08 is now (1 << 3). The fix is intended to improve readability. Remove misleading comment in zd_mac.c: The function already returns -EPERM in managed mode (IW_MODE_INFRA). Remove unused code in zd_mac.c: The unused code intended for debugging rx_status values is no longer useful. Added dump_stack() to ZD_ASSERT macro: Output of the stack helps to debug assertions. Keep in mind that the ZD_ASSERT() macro only results in code, if DEBUG is defined. Improved comments for filter_rx() zd_usb.c: Added driver name to module init and exit functions Signed-off-by: Ulrich Kunitz Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.h | 80 ++++++++++++++++----------------- drivers/net/wireless/zd1211rw/zd_def.h | 1 + drivers/net/wireless/zd1211rw/zd_mac.c | 71 +++-------------------------- drivers/net/wireless/zd1211rw/zd_usb.c | 11 ++--- 4 files changed, 53 insertions(+), 110 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index ae59597ce4e1..f441cf40f74b 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -337,24 +337,24 @@ #define CR_MAC_PS_STATE CTL_REG(0x050C) #define CR_INTERRUPT CTL_REG(0x0510) -#define INT_TX_COMPLETE 0x00000001 -#define INT_RX_COMPLETE 0x00000002 -#define INT_RETRY_FAIL 0x00000004 -#define INT_WAKEUP 0x00000008 -#define INT_DTIM_NOTIFY 0x00000020 -#define INT_CFG_NEXT_BCN 0x00000040 -#define INT_BUS_ABORT 0x00000080 -#define INT_TX_FIFO_READY 0x00000100 -#define INT_UART 0x00000200 -#define INT_TX_COMPLETE_EN 0x00010000 -#define INT_RX_COMPLETE_EN 0x00020000 -#define INT_RETRY_FAIL_EN 0x00040000 -#define INT_WAKEUP_EN 0x00080000 -#define INT_DTIM_NOTIFY_EN 0x00200000 -#define INT_CFG_NEXT_BCN_EN 0x00400000 -#define INT_BUS_ABORT_EN 0x00800000 -#define INT_TX_FIFO_READY_EN 0x01000000 -#define INT_UART_EN 0x02000000 +#define INT_TX_COMPLETE (1 << 0) +#define INT_RX_COMPLETE (1 << 1) +#define INT_RETRY_FAIL (1 << 2) +#define INT_WAKEUP (1 << 3) +#define INT_DTIM_NOTIFY (1 << 5) +#define INT_CFG_NEXT_BCN (1 << 6) +#define INT_BUS_ABORT (1 << 7) +#define INT_TX_FIFO_READY (1 << 8) +#define INT_UART (1 << 9) +#define INT_TX_COMPLETE_EN (1 << 16) +#define INT_RX_COMPLETE_EN (1 << 17) +#define INT_RETRY_FAIL_EN (1 << 18) +#define INT_WAKEUP_EN (1 << 19) +#define INT_DTIM_NOTIFY_EN (1 << 21) +#define INT_CFG_NEXT_BCN_EN (1 << 22) +#define INT_BUS_ABORT_EN (1 << 23) +#define INT_TX_FIFO_READY_EN (1 << 24) +#define INT_UART_EN (1 << 25) #define CR_TSF_LOW_PART CTL_REG(0x0514) #define CR_TSF_HIGH_PART CTL_REG(0x0518) @@ -398,18 +398,18 @@ * device will use a rate in this table that is less than or equal to the rate * of the incoming frame which prompted the response */ #define CR_BASIC_RATE_TBL CTL_REG(0x0630) -#define CR_RATE_1M 0x0001 /* 802.11b */ -#define CR_RATE_2M 0x0002 /* 802.11b */ -#define CR_RATE_5_5M 0x0004 /* 802.11b */ -#define CR_RATE_11M 0x0008 /* 802.11b */ -#define CR_RATE_6M 0x0100 /* 802.11g */ -#define CR_RATE_9M 0x0200 /* 802.11g */ -#define CR_RATE_12M 0x0400 /* 802.11g */ -#define CR_RATE_18M 0x0800 /* 802.11g */ -#define CR_RATE_24M 0x1000 /* 802.11g */ -#define CR_RATE_36M 0x2000 /* 802.11g */ -#define CR_RATE_48M 0x4000 /* 802.11g */ -#define CR_RATE_54M 0x8000 /* 802.11g */ +#define CR_RATE_1M (1 << 0) /* 802.11b */ +#define CR_RATE_2M (1 << 1) /* 802.11b */ +#define CR_RATE_5_5M (1 << 2) /* 802.11b */ +#define CR_RATE_11M (1 << 3) /* 802.11b */ +#define CR_RATE_6M (1 << 8) /* 802.11g */ +#define CR_RATE_9M (1 << 9) /* 802.11g */ +#define CR_RATE_12M (1 << 10) /* 802.11g */ +#define CR_RATE_18M (1 << 11) /* 802.11g */ +#define CR_RATE_24M (1 << 12) /* 802.11g */ +#define CR_RATE_36M (1 << 13) /* 802.11g */ +#define CR_RATE_48M (1 << 14) /* 802.11g */ +#define CR_RATE_54M (1 << 15) /* 802.11g */ #define CR_RATES_80211G 0xff00 #define CR_RATES_80211B 0x000f @@ -426,9 +426,9 @@ /* register for controlling the LEDS */ #define CR_LED CTL_REG(0x0644) /* masks for controlling LEDs */ -#define LED1 0x0100 -#define LED2 0x0200 -#define LED_SW 0x0400 +#define LED1 (1 << 8) +#define LED2 (1 << 9) +#define LED_SW (1 << 10) /* Seems to indicate that the configuration is over. */ @@ -455,18 +455,18 @@ * registers, so one could argue it is a LOCK bit. But calling it * LOCK_PHY_REGS makes it confusing. */ -#define UNLOCK_PHY_REGS 0x0080 +#define UNLOCK_PHY_REGS (1 << 7) #define CR_DEVICE_STATE CTL_REG(0x0684) #define CR_UNDERRUN_CNT CTL_REG(0x0688) #define CR_RX_FILTER CTL_REG(0x068c) -#define RX_FILTER_ASSOC_RESPONSE 0x0002 -#define RX_FILTER_REASSOC_RESPONSE 0x0008 -#define RX_FILTER_PROBE_RESPONSE 0x0020 -#define RX_FILTER_BEACON 0x0100 -#define RX_FILTER_DISASSOC 0x0400 -#define RX_FILTER_AUTH 0x0800 +#define RX_FILTER_ASSOC_RESPONSE (1 << 1) +#define RX_FILTER_REASSOC_RESPONSE (1 << 3) +#define RX_FILTER_PROBE_RESPONSE (1 << 5) +#define RX_FILTER_BEACON (1 << 8) +#define RX_FILTER_DISASSOC (1 << 10) +#define RX_FILTER_AUTH (1 << 11) #define AP_RX_FILTER 0x0400feff #define STA_RX_FILTER 0x0000ffff diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h index a13ec72eb304..fb22f62cf1f3 100644 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ b/drivers/net/wireless/zd1211rw/zd_def.h @@ -39,6 +39,7 @@ do { \ if (!(x)) { \ pr_debug("%s:%d ASSERT %s VIOLATED!\n", \ __FILE__, __LINE__, __stringify(x)); \ + dump_stack(); \ } \ } while (0) #else diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 7845b6dac832..0bb53f0b8bdd 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -295,7 +295,6 @@ static void set_channel(struct net_device *netdev, u8 channel) zd_chip_set_channel(&mac->chip, channel); } -/* TODO: Should not work in Managed mode. */ int zd_mac_request_channel(struct zd_mac *mac, u8 channel) { unsigned long lock_flags; @@ -773,9 +772,11 @@ static int is_data_packet_for_us(struct ieee80211_device *ieee, (netdev->flags & IFF_PROMISC); } -/* Filters receiving packets. If it returns 1 send it to ieee80211_rx, if 0 - * return. If an error is detected -EINVAL is returned. ieee80211_rx_mgt() is - * called here. +/* Filters received packets. The function returns 1 if the packet should be + * forwarded to ieee80211_rx(). If the packet should be ignored the function + * returns 0. If an invalid packet is found the function returns -EINVAL. + * + * The function calls ieee80211_rx_mgt() directly. * * It has been based on ieee80211_rx_any. */ @@ -801,9 +802,9 @@ static int filter_rx(struct ieee80211_device *ieee, ieee80211_rx_mgt(ieee, hdr, stats); return 0; case IEEE80211_FTYPE_CTL: - /* Ignore invalid short buffers */ return 0; case IEEE80211_FTYPE_DATA: + /* Ignore invalid short buffers */ if (length < sizeof(struct ieee80211_hdr_3addr)) return -EINVAL; return is_data_packet_for_us(ieee, hdr); @@ -1019,66 +1020,6 @@ struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) return iw_stats; } -#ifdef DEBUG -static const char* decryption_types[] = { - [ZD_RX_NO_WEP] = "none", - [ZD_RX_WEP64] = "WEP64", - [ZD_RX_TKIP] = "TKIP", - [ZD_RX_AES] = "AES", - [ZD_RX_WEP128] = "WEP128", - [ZD_RX_WEP256] = "WEP256", -}; - -static const char *decryption_type_string(u8 type) -{ - const char *s; - - if (type < ARRAY_SIZE(decryption_types)) { - s = decryption_types[type]; - } else { - s = NULL; - } - return s ? s : "unknown"; -} - -static int is_ofdm(u8 frame_status) -{ - return (frame_status & ZD_RX_OFDM); -} - -void zd_dump_rx_status(const struct rx_status *status) -{ - const char* modulation; - u8 quality; - - if (is_ofdm(status->frame_status)) { - modulation = "ofdm"; - quality = status->signal_quality_ofdm; - } else { - modulation = "cck"; - quality = status->signal_quality_cck; - } - pr_debug("rx status %s strength %#04x qual %#04x decryption %s\n", - modulation, status->signal_strength, quality, - decryption_type_string(status->decryption_type)); - if (status->frame_status & ZD_RX_ERROR) { - pr_debug("rx error %s%s%s%s%s%s\n", - (status->frame_status & ZD_RX_TIMEOUT_ERROR) ? - "timeout " : "", - (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR) ? - "fifo " : "", - (status->frame_status & ZD_RX_DECRYPTION_ERROR) ? - "decryption " : "", - (status->frame_status & ZD_RX_CRC32_ERROR) ? - "crc32 " : "", - (status->frame_status & ZD_RX_NO_ADDR1_MATCH_ERROR) ? - "addr1 " : "", - (status->frame_status & ZD_RX_CRC16_ERROR) ? - "crc16" : ""); - } -} -#endif /* DEBUG */ - #define LINK_LED_WORK_DELAY HZ static void link_led_handler(void *p) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 34524b73324f..c3449cfae7e8 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -1116,27 +1116,28 @@ static int __init usb_init(void) { int r; - pr_debug("usb_init()\n"); + pr_debug("%s usb_init()\n", driver.name); zd_workqueue = create_singlethread_workqueue(driver.name); if (zd_workqueue == NULL) { - printk(KERN_ERR "%s: couldn't create workqueue\n", driver.name); + printk(KERN_ERR "%s couldn't create workqueue\n", driver.name); return -ENOMEM; } r = usb_register(&driver); if (r) { - printk(KERN_ERR "usb_register() failed. Error number %d\n", r); + printk(KERN_ERR "%s usb_register() failed. Error number %d\n", + driver.name, r); return r; } - pr_debug("zd1211rw initialized\n"); + pr_debug("%s initialized\n", driver.name); return 0; } static void __exit usb_exit(void) { - pr_debug("usb_exit()\n"); + pr_debug("%s usb_exit()\n", driver.name); usb_deregister(&driver); destroy_workqueue(zd_workqueue); } -- cgit v1.2.3 From 850c211ce6948bcd71e505be22b7ead99a425bfa Mon Sep 17 00:00:00 2001 From: Ulrich Kunitz Date: Wed, 22 Nov 2006 00:06:19 +0000 Subject: [PATCH] zd1211rw: Optimized handling of zero length entries in length info There are a high number of split USB transactions, which contain only one packet but have a length info field. This patch optimizes this code by stopping parsing the length info structure if a zero length field is encountered. Signed-off-by: Ulrich Kunitz Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index c3449cfae7e8..aa782e88754b 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -593,6 +593,8 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, unsigned int l, k, n; for (i = 0, l = 0;; i++) { k = le16_to_cpu(get_unaligned(&length_info->length[i])); + if (k == 0) + return; n = l+k; if (n > length) return; -- cgit v1.2.3 From 35f2c7c0ce8eb09d19fb50ed2cd29b6dbea9cd86 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 00:06:32 +0000 Subject: [PATCH] zd1211rw: Allow channels 1-13 in Japan Eric Goff found that he could not use his ZD1211 device which is programmed for the Japan regulatory domain. It turns out that ZyDAS deviate from the spec here: they do not use the newer Japan region code (0x41) but their drivers do operate as if the newer Japan legal frequency range is in effect. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_ieee80211.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c index 1b215a099745..189160efd2ae 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c @@ -37,7 +37,12 @@ static const struct channel_range channel_ranges[] = { [ZD_REGDOMAIN_JAPAN] = { 1, 14}, [ZD_REGDOMAIN_SPAIN] = { 1, 14}, [ZD_REGDOMAIN_FRANCE] = { 1, 14}, - [ZD_REGDOMAIN_JAPAN_ADD] = {14, 15}, + + /* Japan originally only had channel 14 available (see CHNL_ID 0x40 in + * 802.11). However, in 2001 the range was extended to include channels + * 1-13. The ZyDAS devices still use the old region code but are + * designed to allow the extra channel access in Japan. */ + [ZD_REGDOMAIN_JAPAN_ADD] = { 1, 15}, }; const struct channel_range *zd_channel_range(u8 regdomain) -- cgit v1.2.3 From b1cd84167b92de0f9fc7aad9cf272261496f4d0b Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 00:06:38 +0000 Subject: [PATCH] zd1211rw: Rename cs_rate to zd_rate These controlset rate constants are also applicable in places outside the controlset, such as in the RTS/CTS control register. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_ieee80211.h | 1 + drivers/net/wireless/zd1211rw/zd_mac.c | 56 ++++++++++++++-------------- drivers/net/wireless/zd1211rw/zd_mac.h | 9 +++-- 3 files changed, 34 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h index 36329890dfec..26b8298dff8c 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h @@ -50,6 +50,7 @@ static inline u8 zd_ofdm_plcp_header_rate( return header->prefix[0] & 0xf; } +/* These are referred to as zd_rates */ #define ZD_OFDM_RATE_6M 0xb #define ZD_OFDM_RATE_9M 0xf #define ZD_OFDM_RATE_12M 0xa diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 0bb53f0b8bdd..e6af18304bac 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -325,13 +325,13 @@ u8 zd_mac_get_channel(struct zd_mac *mac) } /* If wrong rate is given, we are falling back to the slowest rate: 1MBit/s */ -static u8 cs_typed_rate(u8 cs_rate) +static u8 zd_rate_typed(u8 zd_rate) { static const u8 typed_rates[16] = { - [ZD_CS_CCK_RATE_1M] = ZD_CS_CCK|ZD_CS_CCK_RATE_1M, - [ZD_CS_CCK_RATE_2M] = ZD_CS_CCK|ZD_CS_CCK_RATE_2M, - [ZD_CS_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CS_CCK_RATE_5_5M, - [ZD_CS_CCK_RATE_11M] = ZD_CS_CCK|ZD_CS_CCK_RATE_11M, + [ZD_CCK_RATE_1M] = ZD_CS_CCK|ZD_CCK_RATE_1M, + [ZD_CCK_RATE_2M] = ZD_CS_CCK|ZD_CCK_RATE_2M, + [ZD_CCK_RATE_5_5M] = ZD_CS_CCK|ZD_CCK_RATE_5_5M, + [ZD_CCK_RATE_11M] = ZD_CS_CCK|ZD_CCK_RATE_11M, [ZD_OFDM_RATE_6M] = ZD_CS_OFDM|ZD_OFDM_RATE_6M, [ZD_OFDM_RATE_9M] = ZD_CS_OFDM|ZD_OFDM_RATE_9M, [ZD_OFDM_RATE_12M] = ZD_CS_OFDM|ZD_OFDM_RATE_12M, @@ -343,19 +343,19 @@ static u8 cs_typed_rate(u8 cs_rate) }; ZD_ASSERT(ZD_CS_RATE_MASK == 0x0f); - return typed_rates[cs_rate & ZD_CS_RATE_MASK]; + return typed_rates[zd_rate & ZD_CS_RATE_MASK]; } /* Fallback to lowest rate, if rate is unknown. */ -static u8 rate_to_cs_rate(u8 rate) +static u8 rate_to_zd_rate(u8 rate) { switch (rate) { case IEEE80211_CCK_RATE_2MB: - return ZD_CS_CCK_RATE_2M; + return ZD_CCK_RATE_2M; case IEEE80211_CCK_RATE_5MB: - return ZD_CS_CCK_RATE_5_5M; + return ZD_CCK_RATE_5_5M; case IEEE80211_CCK_RATE_11MB: - return ZD_CS_CCK_RATE_11M; + return ZD_CCK_RATE_11M; case IEEE80211_OFDM_RATE_6MB: return ZD_OFDM_RATE_6M; case IEEE80211_OFDM_RATE_9MB: @@ -373,7 +373,7 @@ static u8 rate_to_cs_rate(u8 rate) case IEEE80211_OFDM_RATE_54MB: return ZD_OFDM_RATE_54M; } - return ZD_CS_CCK_RATE_1M; + return ZD_CCK_RATE_1M; } int zd_mac_set_mode(struct zd_mac *mac, u32 mode) @@ -474,13 +474,13 @@ int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range) return 0; } -static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) +static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) { static const u8 rate_divisor[] = { - [ZD_CS_CCK_RATE_1M] = 1, - [ZD_CS_CCK_RATE_2M] = 2, - [ZD_CS_CCK_RATE_5_5M] = 11, /* bits must be doubled */ - [ZD_CS_CCK_RATE_11M] = 11, + [ZD_CCK_RATE_1M] = 1, + [ZD_CCK_RATE_2M] = 2, + [ZD_CCK_RATE_5_5M] = 11, /* bits must be doubled */ + [ZD_CCK_RATE_11M] = 11, [ZD_OFDM_RATE_6M] = 6, [ZD_OFDM_RATE_9M] = 9, [ZD_OFDM_RATE_12M] = 12, @@ -494,15 +494,15 @@ static int zd_calc_tx_length_us(u8 *service, u8 cs_rate, u16 tx_length) u32 bits = (u32)tx_length * 8; u32 divisor; - divisor = rate_divisor[cs_rate]; + divisor = rate_divisor[zd_rate]; if (divisor == 0) return -EINVAL; - switch (cs_rate) { - case ZD_CS_CCK_RATE_5_5M: + switch (zd_rate) { + case ZD_CCK_RATE_5_5M: bits = (2*bits) + 10; /* round up to the next integer */ break; - case ZD_CS_CCK_RATE_11M: + case ZD_CCK_RATE_11M: if (service) { u32 t = bits % 11; *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; @@ -522,16 +522,16 @@ enum { R2M_11A = 0x02, }; -static u8 cs_rate_to_modulation(u8 cs_rate, int flags) +static u8 zd_rate_to_modulation(u8 zd_rate, int flags) { u8 modulation; - modulation = cs_typed_rate(cs_rate); + modulation = zd_rate_typed(zd_rate); if (flags & R2M_SHORT_PREAMBLE) { switch (ZD_CS_RATE(modulation)) { - case ZD_CS_CCK_RATE_2M: - case ZD_CS_CCK_RATE_5_5M: - case ZD_CS_CCK_RATE_11M: + case ZD_CCK_RATE_2M: + case ZD_CCK_RATE_5_5M: + case ZD_CCK_RATE_11M: modulation |= ZD_CS_CCK_PREA_SHORT; return modulation; } @@ -548,15 +548,15 @@ static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, { struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); - u8 rate, cs_rate; + u8 rate, zd_rate; int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; /* FIXME: 802.11a? short preamble? */ rate = ieee80211softmac_suggest_txrate(softmac, is_multicast_ether_addr(hdr->addr1), is_mgt); - cs_rate = rate_to_cs_rate(rate); - cs->modulation = cs_rate_to_modulation(cs_rate, 0); + zd_rate = rate_to_zd_rate(rate); + cs->modulation = zd_rate_to_modulation(zd_rate, 0); } static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 3feb292651df..3c86578150b3 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -48,10 +48,11 @@ struct zd_ctrlset { #define ZD_CS_CCK 0x00 #define ZD_CS_OFDM 0x10 -#define ZD_CS_CCK_RATE_1M 0x00 -#define ZD_CS_CCK_RATE_2M 0x01 -#define ZD_CS_CCK_RATE_5_5M 0x02 -#define ZD_CS_CCK_RATE_11M 0x03 +/* These are referred to as zd_rates */ +#define ZD_CCK_RATE_1M 0x00 +#define ZD_CCK_RATE_2M 0x01 +#define ZD_CCK_RATE_5_5M 0x02 +#define ZD_CCK_RATE_11M 0x03 /* The rates for OFDM are encoded as in the PLCP header. Use ZD_OFDM_RATE_*. */ -- cgit v1.2.3 From b1382edef9c06eca337e8982e6040e0699abab82 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 00:06:48 +0000 Subject: [PATCH] zd1211rw: Use softmac ERP handling functionality This adds zd1211rw driver support for the softmac functionality I added a while back. We now obey changes in basic rates, use short preamble if it is available (but long if the AP says it's not), and send self-CTS in the proper situations. Locking fixed and improved by Ulrich Kunitz. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 38 +++-- drivers/net/wireless/zd1211rw/zd_chip.h | 24 ++- drivers/net/wireless/zd1211rw/zd_mac.c | 270 +++++++++++++++++++++++++------- drivers/net/wireless/zd1211rw/zd_mac.h | 19 +++ 4 files changed, 286 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index aa661b2b76c7..8be99ebbe1cd 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -1076,6 +1076,31 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std) return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); } +int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, + u8 rts_rate, int preamble) +{ + int rts_mod = ZD_RX_CCK; + u32 value = 0; + + /* Modulation bit */ + if (ZD_CS_TYPE(rts_rate) == ZD_CS_OFDM) + rts_mod = ZD_RX_OFDM; + + dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n", + rts_rate, preamble); + + value |= rts_rate << RTSCTS_SH_RTS_RATE; + value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE; + value |= preamble << RTSCTS_SH_RTS_PMB_TYPE; + value |= preamble << RTSCTS_SH_CTS_PMB_TYPE; + + /* We always send 11M self-CTS messages, like the vendor driver. */ + value |= ZD_CCK_RATE_11M << RTSCTS_SH_CTS_RATE; + value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE; + + return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE); +} + int zd_chip_enable_hwint(struct zd_chip *chip) { int r; @@ -1355,17 +1380,12 @@ out: return r; } -int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) +int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates) { - int r; - - if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) - return -EINVAL; + ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0); + dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates); - mutex_lock(&chip->mutex); - r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); - mutex_unlock(&chip->mutex); - return r; + return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); } static int ofdm_qual_db(u8 status_quality, u8 rate, unsigned int size) diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index f441cf40f74b..ca892b9a6448 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -420,6 +420,15 @@ #define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) #define CR_RTS_CTS_RATE CTL_REG(0x0638) +/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */ +#define RTSCTS_SH_RTS_RATE 0 +#define RTSCTS_SH_EXP_CTS_RATE 4 +#define RTSCTS_SH_RTS_MOD_TYPE 8 +#define RTSCTS_SH_RTS_PMB_TYPE 9 +#define RTSCTS_SH_CTS_RATE 16 +#define RTSCTS_SH_CTS_MOD_TYPE 24 +#define RTSCTS_SH_CTS_PMB_TYPE 25 + #define CR_WEP_PROTECT CTL_REG(0x063C) #define CR_RX_THRESHOLD CTL_REG(0x0640) @@ -794,6 +803,9 @@ void zd_chip_disable_rx(struct zd_chip *chip); int zd_chip_enable_hwint(struct zd_chip *chip); int zd_chip_disable_hwint(struct zd_chip *chip); +int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, + u8 rts_rate, int preamble); + static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) { return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); @@ -809,7 +821,17 @@ static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); } -int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); +int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates); + +static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) +{ + int r; + + mutex_lock(&chip->mutex); + r = zd_chip_set_basic_rates_locked(chip, cr_rates); + mutex_unlock(&chip->mutex); + return r; +} static inline int zd_chip_set_rx_filter(struct zd_chip *chip, u32 filter) { diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index e6af18304bac..2696f95b9278 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -32,6 +32,8 @@ static void ieee_init(struct ieee80211_device *ieee); static void softmac_init(struct ieee80211softmac_device *sm); +static void set_rts_cts_work(void *d); +static void set_basic_rates_work(void *d); static void housekeeping_init(struct zd_mac *mac); static void housekeeping_enable(struct zd_mac *mac); @@ -46,6 +48,8 @@ int zd_mac_init(struct zd_mac *mac, memset(mac, 0, sizeof(*mac)); spin_lock_init(&mac->lock); mac->netdev = netdev; + INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work, mac); + INIT_WORK(&mac->set_basic_rates_work, set_basic_rates_work, mac); ieee_init(ieee); softmac_init(ieee80211_priv(netdev)); @@ -213,6 +217,13 @@ int zd_mac_stop(struct net_device *netdev) housekeeping_disable(mac); ieee80211softmac_stop(netdev); + /* Ensure no work items are running or queued from this point */ + cancel_delayed_work(&mac->set_rts_cts_work); + cancel_delayed_work(&mac->set_basic_rates_work); + flush_workqueue(zd_workqueue); + mac->updating_rts_rate = 0; + mac->updating_basic_rates = 0; + zd_chip_disable_hwint(chip); zd_chip_switch_radio_off(chip); zd_chip_disable_int(chip); @@ -286,6 +297,186 @@ u8 zd_mac_get_regdomain(struct zd_mac *mac) return regdomain; } +/* Fallback to lowest rate, if rate is unknown. */ +static u8 rate_to_zd_rate(u8 rate) +{ + switch (rate) { + case IEEE80211_CCK_RATE_2MB: + return ZD_CCK_RATE_2M; + case IEEE80211_CCK_RATE_5MB: + return ZD_CCK_RATE_5_5M; + case IEEE80211_CCK_RATE_11MB: + return ZD_CCK_RATE_11M; + case IEEE80211_OFDM_RATE_6MB: + return ZD_OFDM_RATE_6M; + case IEEE80211_OFDM_RATE_9MB: + return ZD_OFDM_RATE_9M; + case IEEE80211_OFDM_RATE_12MB: + return ZD_OFDM_RATE_12M; + case IEEE80211_OFDM_RATE_18MB: + return ZD_OFDM_RATE_18M; + case IEEE80211_OFDM_RATE_24MB: + return ZD_OFDM_RATE_24M; + case IEEE80211_OFDM_RATE_36MB: + return ZD_OFDM_RATE_36M; + case IEEE80211_OFDM_RATE_48MB: + return ZD_OFDM_RATE_48M; + case IEEE80211_OFDM_RATE_54MB: + return ZD_OFDM_RATE_54M; + } + return ZD_CCK_RATE_1M; +} + +static u16 rate_to_cr_rate(u8 rate) +{ + switch (rate) { + case IEEE80211_CCK_RATE_2MB: + return CR_RATE_1M; + case IEEE80211_CCK_RATE_5MB: + return CR_RATE_5_5M; + case IEEE80211_CCK_RATE_11MB: + return CR_RATE_11M; + case IEEE80211_OFDM_RATE_6MB: + return CR_RATE_6M; + case IEEE80211_OFDM_RATE_9MB: + return CR_RATE_9M; + case IEEE80211_OFDM_RATE_12MB: + return CR_RATE_12M; + case IEEE80211_OFDM_RATE_18MB: + return CR_RATE_18M; + case IEEE80211_OFDM_RATE_24MB: + return CR_RATE_24M; + case IEEE80211_OFDM_RATE_36MB: + return CR_RATE_36M; + case IEEE80211_OFDM_RATE_48MB: + return CR_RATE_48M; + case IEEE80211_OFDM_RATE_54MB: + return CR_RATE_54M; + } + return CR_RATE_1M; +} + +static void try_enable_tx(struct zd_mac *mac) +{ + unsigned long flags; + + spin_lock_irqsave(&mac->lock, flags); + if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0) + netif_wake_queue(mac->netdev); + spin_unlock_irqrestore(&mac->lock, flags); +} + +static void set_rts_cts_work(void *d) +{ + struct zd_mac *mac = d; + unsigned long flags; + u8 rts_rate; + unsigned int short_preamble; + + mutex_lock(&mac->chip.mutex); + + spin_lock_irqsave(&mac->lock, flags); + mac->updating_rts_rate = 0; + rts_rate = mac->rts_rate; + short_preamble = mac->short_preamble; + spin_unlock_irqrestore(&mac->lock, flags); + + zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble); + mutex_unlock(&mac->chip.mutex); + + try_enable_tx(mac); +} + +static void set_basic_rates_work(void *d) +{ + struct zd_mac *mac = d; + unsigned long flags; + u16 basic_rates; + + mutex_lock(&mac->chip.mutex); + + spin_lock_irqsave(&mac->lock, flags); + mac->updating_basic_rates = 0; + basic_rates = mac->basic_rates; + spin_unlock_irqrestore(&mac->lock, flags); + + zd_chip_set_basic_rates_locked(&mac->chip, basic_rates); + mutex_unlock(&mac->chip.mutex); + + try_enable_tx(mac); +} + +static void bssinfo_change(struct net_device *netdev, u32 changes) +{ + struct zd_mac *mac = zd_netdev_mac(netdev); + struct ieee80211softmac_device *softmac = ieee80211_priv(netdev); + struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo; + int need_set_rts_cts = 0; + int need_set_rates = 0; + u16 basic_rates; + unsigned long flags; + + dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); + + if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) { + spin_lock_irqsave(&mac->lock, flags); + mac->short_preamble = bssinfo->short_preamble; + spin_unlock_irqrestore(&mac->lock, flags); + need_set_rts_cts = 1; + } + + if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) { + /* Set RTS rate to highest available basic rate */ + u8 rate = ieee80211softmac_highest_supported_rate(softmac, + &bssinfo->supported_rates, 1); + rate = rate_to_zd_rate(rate); + + spin_lock_irqsave(&mac->lock, flags); + if (rate != mac->rts_rate) { + mac->rts_rate = rate; + need_set_rts_cts = 1; + } + spin_unlock_irqrestore(&mac->lock, flags); + + /* Set basic rates */ + need_set_rates = 1; + if (bssinfo->supported_rates.count == 0) { + /* Allow the device to be flexible */ + basic_rates = CR_RATES_80211B | CR_RATES_80211G; + } else { + int i = 0; + basic_rates = 0; + + for (i = 0; i < bssinfo->supported_rates.count; i++) { + u16 rate = bssinfo->supported_rates.rates[i]; + if ((rate & IEEE80211_BASIC_RATE_MASK) == 0) + continue; + + rate &= ~IEEE80211_BASIC_RATE_MASK; + basic_rates |= rate_to_cr_rate(rate); + } + } + spin_lock_irqsave(&mac->lock, flags); + mac->basic_rates = basic_rates; + spin_unlock_irqrestore(&mac->lock, flags); + } + + /* Schedule any changes we made above */ + + spin_lock_irqsave(&mac->lock, flags); + if (need_set_rts_cts && !mac->updating_rts_rate) { + mac->updating_rts_rate = 1; + netif_stop_queue(mac->netdev); + queue_work(zd_workqueue, &mac->set_rts_cts_work); + } + if (need_set_rates && !mac->updating_basic_rates) { + mac->updating_basic_rates = 1; + netif_stop_queue(mac->netdev); + queue_work(zd_workqueue, &mac->set_basic_rates_work); + } + spin_unlock_irqrestore(&mac->lock, flags); +} + static void set_channel(struct net_device *netdev, u8 channel) { struct zd_mac *mac = zd_netdev_mac(netdev); @@ -346,36 +537,6 @@ static u8 zd_rate_typed(u8 zd_rate) return typed_rates[zd_rate & ZD_CS_RATE_MASK]; } -/* Fallback to lowest rate, if rate is unknown. */ -static u8 rate_to_zd_rate(u8 rate) -{ - switch (rate) { - case IEEE80211_CCK_RATE_2MB: - return ZD_CCK_RATE_2M; - case IEEE80211_CCK_RATE_5MB: - return ZD_CCK_RATE_5_5M; - case IEEE80211_CCK_RATE_11MB: - return ZD_CCK_RATE_11M; - case IEEE80211_OFDM_RATE_6MB: - return ZD_OFDM_RATE_6M; - case IEEE80211_OFDM_RATE_9MB: - return ZD_OFDM_RATE_9M; - case IEEE80211_OFDM_RATE_12MB: - return ZD_OFDM_RATE_12M; - case IEEE80211_OFDM_RATE_18MB: - return ZD_OFDM_RATE_18M; - case IEEE80211_OFDM_RATE_24MB: - return ZD_OFDM_RATE_24M; - case IEEE80211_OFDM_RATE_36MB: - return ZD_OFDM_RATE_36M; - case IEEE80211_OFDM_RATE_48MB: - return ZD_OFDM_RATE_48M; - case IEEE80211_OFDM_RATE_54MB: - return ZD_OFDM_RATE_54M; - } - return ZD_CCK_RATE_1M; -} - int zd_mac_set_mode(struct zd_mac *mac, u32 mode) { struct ieee80211_device *ieee; @@ -550,37 +711,34 @@ static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs, u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl)); u8 rate, zd_rate; int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0; + int is_multicast = is_multicast_ether_addr(hdr->addr1); + int short_preamble = ieee80211softmac_short_preamble_ok(softmac, + is_multicast, is_mgt); + int flags = 0; - /* FIXME: 802.11a? short preamble? */ - rate = ieee80211softmac_suggest_txrate(softmac, - is_multicast_ether_addr(hdr->addr1), is_mgt); + /* FIXME: 802.11a? */ + rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt); + + if (short_preamble) + flags |= R2M_SHORT_PREAMBLE; zd_rate = rate_to_zd_rate(rate); - cs->modulation = zd_rate_to_modulation(zd_rate, 0); + cs->modulation = zd_rate_to_modulation(zd_rate, flags); } static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, struct ieee80211_hdr_4addr *header) { + struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev); unsigned int tx_length = le16_to_cpu(cs->tx_length); u16 fctl = le16_to_cpu(header->frame_ctl); u16 ftype = WLAN_FC_GET_TYPE(fctl); u16 stype = WLAN_FC_GET_STYPE(fctl); /* - * CONTROL: - * - start at 0x00 - * - if fragment 0, enable bit 0 + * CONTROL TODO: * - if backoff needed, enable bit 0 * - if burst (backoff not needed) disable bit 0 - * - if multicast, enable bit 1 - * - if PS-POLL frame, enable bit 2 - * - if in INDEPENDENT_BSS mode and zd1205_DestPowerSave, then enable - * bit 4 (FIXME: wtf) - * - if frag_len > RTS threshold, set bit 5 as long if it isnt - * multicast or mgt - * - if bit 5 is set, and we are in OFDM mode, unset bit 5 and set bit - * 7 */ cs->control = 0; @@ -597,17 +755,18 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, if (stype == IEEE80211_STYPE_PSPOLL) cs->control |= ZD_CS_PS_POLL_FRAME; + /* Unicast data frames over the threshold should have RTS */ if (!is_multicast_ether_addr(header->addr1) && - ftype != IEEE80211_FTYPE_MGMT && - tx_length > zd_netdev_ieee80211(mac->netdev)->rts) - { - /* FIXME: check the logic */ - if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM) { - /* 802.11g */ - cs->control |= ZD_CS_SELF_CTS; - } else { /* 802.11b */ - cs->control |= ZD_CS_RTS; - } + ftype != IEEE80211_FTYPE_MGMT && + tx_length > zd_netdev_ieee80211(mac->netdev)->rts) + cs->control |= ZD_CS_RTS; + + /* Use CTS-to-self protection if required */ + if (ZD_CS_TYPE(cs->modulation) == ZD_CS_OFDM && + ieee80211softmac_protection_needed(softmac)) { + /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */ + cs->control &= ~ZD_CS_RTS; + cs->control |= ZD_CS_SELF_CTS; } /* FIXME: Management frame? */ @@ -985,6 +1144,7 @@ static void ieee_init(struct ieee80211_device *ieee) static void softmac_init(struct ieee80211softmac_device *sm) { sm->set_channel = set_channel; + sm->bssinfo_change = bssinfo_change; } struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 3c86578150b3..5dcfb251f02e 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -127,15 +128,33 @@ struct zd_mac { struct zd_chip chip; spinlock_t lock; struct net_device *netdev; + /* Unlocked reading possible */ struct iw_statistics iw_stats; + struct housekeeping housekeeping; + struct work_struct set_rts_cts_work; + struct work_struct set_basic_rates_work; + unsigned int stats_count; u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE]; u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE]; u8 regdomain; u8 default_regdomain; u8 requested_channel; + + /* A bitpattern of cr_rates */ + u16 basic_rates; + + /* A zd_rate */ + u8 rts_rate; + + /* Short preamble (used for RTS/CTS) */ + unsigned int short_preamble:1; + + /* flags to indicate update in progress */ + unsigned int updating_rts_rate:1; + unsigned int updating_basic_rates:1; }; static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac) -- cgit v1.2.3 From 718cc4ca2bfb3263c7ea3ceba9c194f9cd7292e2 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Wed, 22 Nov 2006 03:15:46 +0000 Subject: [PATCH] ieee80211: Provide generic get_stats implementation bcm43xx and ipw2100 currently duplicate the same simplistic get_stats handler. Additionally, zd1211rw requires the same handler to fix a bug where all stats are reported as 0. This patch adds a generic implementation to the ieee80211 layer, which drivers are free to override. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 6 ------ drivers/net/wireless/ipw2100.c | 14 -------------- net/ieee80211/ieee80211_module.c | 11 +++++++++++ 3 files changed, 11 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index 60a97450a6ed..5b3c27359a18 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -4013,11 +4013,6 @@ static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, return NETDEV_TX_OK; } -static struct net_device_stats * bcm43xx_net_get_stats(struct net_device *net_dev) -{ - return &(bcm43xx_priv(net_dev)->ieee->stats); -} - static void bcm43xx_net_tx_timeout(struct net_device *net_dev) { struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); @@ -4131,7 +4126,6 @@ static int __devinit bcm43xx_init_one(struct pci_dev *pdev, net_dev->open = bcm43xx_net_open; net_dev->stop = bcm43xx_net_stop; - net_dev->get_stats = bcm43xx_net_get_stats; net_dev->tx_timeout = bcm43xx_net_tx_timeout; #ifdef CONFIG_NET_POLL_CONTROLLER net_dev->poll_controller = bcm43xx_net_poll_controller; diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index 3bc6be9d20f8..79607b8b877c 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -5827,19 +5827,6 @@ static void ipw2100_tx_timeout(struct net_device *dev) schedule_reset(priv); } -/* - * TODO: reimplement it so that it reads statistics - * from the adapter using ordinal tables - * instead of/in addition to collecting them - * in the driver - */ -static struct net_device_stats *ipw2100_stats(struct net_device *dev) -{ - struct ipw2100_priv *priv = ieee80211_priv(dev); - - return &priv->ieee->stats; -} - static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) { /* This is called when wpa_supplicant loads and closes the driver @@ -6022,7 +6009,6 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, dev->open = ipw2100_open; dev->stop = ipw2100_close; dev->init = ipw2100_net_init; - dev->get_stats = ipw2100_stats; dev->ethtool_ops = &ipw2100_ethtool_ops; dev->tx_timeout = ipw2100_tx_timeout; dev->wireless_handlers = &ipw2100_wx_handler_def; diff --git a/net/ieee80211/ieee80211_module.c b/net/ieee80211/ieee80211_module.c index f16e60ee9ce9..b1c6d1f717d9 100644 --- a/net/ieee80211/ieee80211_module.c +++ b/net/ieee80211/ieee80211_module.c @@ -123,6 +123,13 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } +static struct net_device_stats *ieee80211_generic_get_stats( + struct net_device *dev) +{ + struct ieee80211_device *ieee = netdev_priv(dev); + return &ieee->stats; +} + struct net_device *alloc_ieee80211(int sizeof_priv) { struct ieee80211_device *ieee; @@ -140,6 +147,10 @@ struct net_device *alloc_ieee80211(int sizeof_priv) dev->hard_start_xmit = ieee80211_xmit; dev->change_mtu = ieee80211_change_mtu; + /* Drivers are free to override this if the generic implementation + * does not meet their needs. */ + dev->get_stats = ieee80211_generic_get_stats; + ieee->dev = dev; err = ieee80211_networks_allocate(ieee); -- cgit v1.2.3 From edf901638144525a140c68be01be1b22e6041a6d Mon Sep 17 00:00:00 2001 From: "Amit S. Kale" Date: Wed, 29 Nov 2006 08:58:11 -0800 Subject: [PATCH] NetXen: Fixed /sys mapping between device and driver Signed-off-by: Amit S. Kale netxen_nic_main.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletion(-) Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 145bf47f0a8d..ffd272c93a6b 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -273,6 +273,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } SET_MODULE_OWNER(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); port = netdev_priv(netdev); port->netdev = netdev; @@ -1043,7 +1044,7 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget) netxen_nic_enable_int(adapter); } - return (done ? 0 : 1); + return !done; } #ifdef CONFIG_NET_POLL_CONTROLLER -- cgit v1.2.3 From cb8011ad53e0855ef088e0e5a4bcb98fa90c70b6 Mon Sep 17 00:00:00 2001 From: "Amit S. Kale" Date: Wed, 29 Nov 2006 09:00:10 -0800 Subject: [PATCH] NetXen: temp monitoring, newer firmware support, mm footprint reduction NetXen: 1G/10G Ethernet Driver updates - Temparature monitoring and device control - Memory footprint reduction - Driver changes to support newer version of firmware Signed-off-by: Amit S. Kale netxen_nic.h | 165 ++++++++++++++++++++++++++++++++-- netxen_nic_ethtool.c | 89 ++++++++++++------ netxen_nic_hdr.h | 71 +++++++++++++- netxen_nic_hw.c | 206 +++++++++++++++++++++++++++++-------------- netxen_nic_hw.h | 8 + netxen_nic_init.c | 239 +++++++++++++++++++++++++++++++++++++++++--------- netxen_nic_ioctl.h | 12 +- netxen_nic_isr.c | 54 +++++------ netxen_nic_main.c | 121 +++++++++++++++++-------- netxen_nic_niu.c | 172 +++++++++++++++++++++++++++-------- netxen_nic_phan_reg.h | 24 ++++- 11 files changed, 891 insertions(+), 270 deletions(-) Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 165 +++++++++++++++++++-- drivers/net/netxen/netxen_nic_ethtool.c | 89 ++++++++---- drivers/net/netxen/netxen_nic_hdr.h | 71 ++++++++- drivers/net/netxen/netxen_nic_hw.c | 206 +++++++++++++++++--------- drivers/net/netxen/netxen_nic_hw.h | 8 +- drivers/net/netxen/netxen_nic_init.c | 239 ++++++++++++++++++++++++++----- drivers/net/netxen/netxen_nic_ioctl.h | 12 +- drivers/net/netxen/netxen_nic_isr.c | 54 ++++--- drivers/net/netxen/netxen_nic_main.c | 121 +++++++++++----- drivers/net/netxen/netxen_nic_niu.c | 172 +++++++++++++++++----- drivers/net/netxen/netxen_nic_phan_reg.h | 24 +++- 11 files changed, 891 insertions(+), 270 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 0458db45e700..1bee560d7d0a 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -63,12 +63,12 @@ #include "netxen_nic_hw.h" -#define NETXEN_NIC_BUILD_NO "232" +#define NETXEN_NIC_BUILD_NO "5" #define _NETXEN_NIC_LINUX_MAJOR 2 #define _NETXEN_NIC_LINUX_MINOR 3 -#define _NETXEN_NIC_LINUX_SUBVERSION 57 -#define NETXEN_NIC_LINUX_VERSIONID "2.3.57" -#define NETXEN_NIC_FW_VERSIONID "2.3.57" +#define _NETXEN_NIC_LINUX_SUBVERSION 59 +#define NETXEN_NIC_LINUX_VERSIONID "2.3.59" "-" NETXEN_NIC_BUILD_NO +#define NETXEN_NIC_FW_VERSIONID "2.3.59" #define RCV_DESC_RINGSIZE \ (sizeof(struct rcv_desc) * adapter->max_rx_desc_count) @@ -89,9 +89,24 @@ * normalize a 64MB crb address to 32MB PCI window * To use NETXEN_CRB_NORMALIZE, window _must_ be set to 1 */ +#define NETXEN_CRB_NORMAL(reg) \ + (reg) - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST + #define NETXEN_CRB_NORMALIZE(adapter, reg) \ - ((adapter)->ahw.pci_base + (reg) \ - - NETXEN_CRB_PCIX_HOST2 + NETXEN_CRB_PCIX_HOST) + pci_base_offset(adapter, NETXEN_CRB_NORMAL(reg)) + +#define FIRST_PAGE_GROUP_START 0 +#define FIRST_PAGE_GROUP_END 0x400000 + +#define SECOND_PAGE_GROUP_START 0x4000000 +#define SECOND_PAGE_GROUP_END 0x66BC000 + +#define THIRD_PAGE_GROUP_START 0x70E4000 +#define THIRD_PAGE_GROUP_END 0x8000000 + +#define FIRST_PAGE_GROUP_SIZE FIRST_PAGE_GROUP_END - FIRST_PAGE_GROUP_START +#define SECOND_PAGE_GROUP_SIZE SECOND_PAGE_GROUP_END - SECOND_PAGE_GROUP_START +#define THIRD_PAGE_GROUP_SIZE THIRD_PAGE_GROUP_END - THIRD_PAGE_GROUP_START #define MAX_RX_BUFFER_LENGTH 2000 #define MAX_RX_JUMBO_BUFFER_LENGTH 9046 @@ -328,6 +343,7 @@ typedef enum { NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e, NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f } netxen_brdtype_t; +#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(netxen_brdinfo_t)) typedef enum { NETXEN_BRDMFG_INVENTEC = 1 @@ -615,15 +631,23 @@ struct netxen_rx_buffer { */ struct netxen_hardware_context { struct pci_dev *pdev; - void __iomem *pci_base; /* base of mapped phantom memory */ + void __iomem *pci_base0; + void __iomem *pci_base1; + void __iomem *pci_base2; + u8 revision_id; u16 board_type; u16 max_ports; struct netxen_board_info boardcfg; u32 xg_linkup; + u32 qg_linksup; /* Address of cmd ring in Phantom */ struct cmd_desc_type0 *cmd_desc_head; + char *pauseaddr; + struct pci_dev *cmd_desc_pdev; dma_addr_t cmd_desc_phys_addr; + dma_addr_t pause_physaddr; + struct pci_dev *pause_pdev; struct netxen_adapter *adapter; }; @@ -654,6 +678,7 @@ struct netxen_rcv_desc_ctx { u32 rcv_pending; /* Num of bufs posted in phantom */ u32 rcv_free; /* Num of bufs in free list */ dma_addr_t phys_addr; + struct pci_dev *phys_pdev; struct rcv_desc *desc_head; /* address of rx ring in Phantom */ u32 max_rx_desc_count; u32 dma_size; @@ -673,6 +698,7 @@ struct netxen_recv_context { u32 status_rx_producer; u32 status_rx_consumer; dma_addr_t rcv_status_desc_phys_addr; + struct pci_dev *rcv_status_desc_pdev; struct status_desc *rcv_status_desc_head; }; @@ -708,6 +734,7 @@ struct netxen_adapter { u32 flags; u32 irq; int driver_mismatch; + u32 temp; struct netxen_adapter_stats stats; @@ -766,6 +793,43 @@ struct netxen_port { struct netxen_port_stats stats; }; +#define PCI_OFFSET_FIRST_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base0 + (off)) +#define PCI_OFFSET_SECOND_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) +#define PCI_OFFSET_THIRD_RANGE(adapter, off) \ + ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) + +static inline void __iomem *pci_base_offset(struct netxen_adapter *adapter, + unsigned long off) +{ + if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { + return (adapter->ahw.pci_base0 + off); + } else if ((off < SECOND_PAGE_GROUP_END) && + (off >= SECOND_PAGE_GROUP_START)) { + return (adapter->ahw.pci_base1 + off - SECOND_PAGE_GROUP_START); + } else if ((off < THIRD_PAGE_GROUP_END) && + (off >= THIRD_PAGE_GROUP_START)) { + return (adapter->ahw.pci_base2 + off - THIRD_PAGE_GROUP_START); + } + return NULL; +} + +static inline void __iomem *pci_base(struct netxen_adapter *adapter, + unsigned long off) +{ + if ((off < FIRST_PAGE_GROUP_END) && (off >= FIRST_PAGE_GROUP_START)) { + return adapter->ahw.pci_base0; + } else if ((off < SECOND_PAGE_GROUP_END) && + (off >= SECOND_PAGE_GROUP_START)) { + return adapter->ahw.pci_base1; + } else if ((off < THIRD_PAGE_GROUP_END) && + (off >= THIRD_PAGE_GROUP_START)) { + return adapter->ahw.pci_base2; + } + return NULL; +} + struct netxen_drvops { int (*enable_phy_interrupts) (struct netxen_adapter *, int); int (*disable_phy_interrupts) (struct netxen_adapter *, int); @@ -809,7 +873,6 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, long phy, long reg, __le32 val); /* Functions available from netxen_nic_hw.c */ -int netxen_niu_xginit(struct netxen_adapter *); int netxen_nic_set_mtu_xgb(struct netxen_port *port, int new_mtu); int netxen_nic_set_mtu_gb(struct netxen_port *port, int new_mtu); void netxen_nic_init_niu_gb(struct netxen_adapter *adapter); @@ -828,10 +891,13 @@ void netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, int data); /* Functions from netxen_nic_init.c */ -void netxen_phantom_init(struct netxen_adapter *adapter); +void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val); void netxen_load_firmware(struct netxen_adapter *adapter); int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose); int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); +int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data); +int netxen_rom_se(struct netxen_adapter *adapter, int addr); +int netxen_do_rom_se(struct netxen_adapter *adapter, int addr); /* Functions from netxen_nic_isr.c */ void netxen_nic_isr_other(struct netxen_adapter *adapter); @@ -842,6 +908,8 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 port, void netxen_nic_stop_all_ports(struct netxen_adapter *adapter); void netxen_initialize_adapter_sw(struct netxen_adapter *adapter); void netxen_initialize_adapter_hw(struct netxen_adapter *adapter); +void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr, + struct pci_dev **used_dev); void netxen_initialize_adapter_ops(struct netxen_adapter *adapter); int netxen_init_firmware(struct netxen_adapter *adapter); void netxen_free_hw_resources(struct netxen_adapter *adapter); @@ -869,7 +937,10 @@ static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) /* * ISR_INT_MASK: Can be read from window 0 or 1. */ - writel(0x7ff, (void __iomem *)(adapter->ahw.pci_base + ISR_INT_MASK)); + writel(0x7ff, + (void __iomem + *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); + } static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) @@ -888,13 +959,83 @@ static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) break; } - writel(mask, (void __iomem *)(adapter->ahw.pci_base + ISR_INT_MASK)); + writel(mask, + (void __iomem + *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { mask = 0xbff; writel(mask, (void __iomem *) - (adapter->ahw.pci_base + ISR_INT_TARGET_MASK)); + (PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK))); + } +} + +/* + * NetXen Board information + */ + +#define NETXEN_MAX_SHORT_NAME 16 +typedef struct { + netxen_brdtype_t brdtype; /* type of board */ + long ports; /* max no of physical ports */ + char short_name[NETXEN_MAX_SHORT_NAME]; +} netxen_brdinfo_t; + +static const netxen_brdinfo_t netxen_boards[] = { + {NETXEN_BRDTYPE_P2_SB31_10G_CX4, 1, "XGb CX4"}, + {NETXEN_BRDTYPE_P2_SB31_10G_HMEZ, 1, "XGb HMEZ"}, + {NETXEN_BRDTYPE_P2_SB31_10G_IMEZ, 2, "XGb IMEZ"}, + {NETXEN_BRDTYPE_P2_SB31_10G, 1, "XGb XFP"}, + {NETXEN_BRDTYPE_P2_SB35_4G, 4, "Quad Gb"}, + {NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"}, +}; + +#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(netxen_brdinfo_t)) + +static inline void get_brd_ports_name_by_type(u32 type, int *ports, char *name) +{ + int i, found = 0; + for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { + if (netxen_boards[i].brdtype == type) { + *ports = netxen_boards[i].ports; + strcpy(name, netxen_boards[i].short_name); + found = 1; + break; + } + } + if (!found) { + *ports = 0; + name = "Unknown"; + } +} + +static inline void get_brd_port_by_type(u32 type, int *ports) +{ + int i, found = 0; + for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { + if (netxen_boards[i].brdtype == type) { + *ports = netxen_boards[i].ports; + found = 1; + break; + } + } + if (!found) + *ports = 0; +} + +static inline void get_brd_name_by_type(u32 type, char *name) +{ + int i, found = 0; + for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { + if (netxen_boards[i].brdtype == type) { + strcpy(name, netxen_boards[i].short_name); + found = 1; + break; + } + } + if (!found) + name = "Unknown"; } int netxen_is_flash_supported(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index caf6cc15b241..f3fc35cf8af7 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -53,6 +53,9 @@ struct netxen_nic_stats { #define NETXEN_NIC_STAT(m) sizeof(((struct netxen_port *)0)->m), \ offsetof(struct netxen_port, m) +#define NETXEN_NIC_PORT_WINDOW 0x10000 +#define NETXEN_NIC_INVALID_DATA 0xDEADBEEF + static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = { {"rcvd_bad_skb", NETXEN_NIC_STAT(stats.rcvdbadskb)}, {"xmit_called", NETXEN_NIC_STAT(stats.xmitcalled)}, @@ -111,9 +114,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; - uint32_t fw_major = 0; - uint32_t fw_minor = 0; - uint32_t fw_build = 0; + u32 fw_major = 0; + u32 fw_minor = 0; + u32 fw_build = 0; strncpy(drvinfo->driver, "netxen_nic", 32); strncpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID, 32); @@ -136,6 +139,8 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; + struct netxen_board_info *boardinfo; + boardinfo = &adapter->ahw.boardcfg; /* read which mode */ if (adapter->ahw.board_type == NETXEN_NIC_GBE) { @@ -144,16 +149,12 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full | - SUPPORTED_TP | - SUPPORTED_MII | SUPPORTED_Autoneg); + SUPPORTED_1000baseT_Full); ecmd->advertising = (ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_TP | - ADVERTISED_MII | ADVERTISED_Autoneg); + ADVERTISED_1000baseT_Full); ecmd->port = PORT_TP; @@ -162,16 +163,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->duplex = port->link_duplex; } else return -EIO; /* link absent */ - - ecmd->phy_address = port->portnum; - ecmd->transceiver = XCVR_EXTERNAL; - - /* get autoneg settings */ - ecmd->autoneg = port->link_autoneg; - return 0; - } - - if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { + } else if (adapter->ahw.board_type == NETXEN_NIC_XGBE) { ecmd->supported = (SUPPORTED_TP | SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full); @@ -182,13 +174,47 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->speed = SPEED_10000; ecmd->duplex = DUPLEX_FULL; - ecmd->phy_address = port->portnum; - ecmd->transceiver = XCVR_EXTERNAL; ecmd->autoneg = AUTONEG_DISABLE; - return 0; + } else + return -EIO; + + ecmd->phy_address = port->portnum; + ecmd->transceiver = XCVR_EXTERNAL; + + switch ((netxen_brdtype_t) boardinfo->board_type) { + case NETXEN_BRDTYPE_P2_SB35_4G: + case NETXEN_BRDTYPE_P2_SB31_2G: + ecmd->supported |= SUPPORTED_Autoneg; + ecmd->advertising |= ADVERTISED_Autoneg; + case NETXEN_BRDTYPE_P2_SB31_10G_CX4: + ecmd->supported |= SUPPORTED_TP; + ecmd->advertising |= ADVERTISED_TP; + ecmd->port = PORT_TP; + ecmd->autoneg = (boardinfo->board_type == + NETXEN_BRDTYPE_P2_SB31_10G_CX4) ? + (AUTONEG_DISABLE) : (port->link_autoneg); + break; + case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: + case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: + ecmd->supported |= SUPPORTED_MII; + ecmd->advertising |= ADVERTISED_MII; + ecmd->port = PORT_FIBRE; + ecmd->autoneg = AUTONEG_DISABLE; + break; + case NETXEN_BRDTYPE_P2_SB31_10G: + ecmd->supported |= SUPPORTED_FIBRE; + ecmd->advertising |= ADVERTISED_FIBRE; + ecmd->port = PORT_FIBRE; + ecmd->autoneg = AUTONEG_DISABLE; + break; + default: + printk("ERROR: Unsupported board model %d\n", + (netxen_brdtype_t) boardinfo->board_type); + return -EIO; + } - return -EIO; + return 0; } static int @@ -371,7 +397,7 @@ netxen_nic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) for (i = 3; niu_registers[mode].reg[i - 3] != -1; i++) { /* GB: port specific registers */ if (mode == 0 && i >= 19) - window = port->portnum * 0x10000; + window = port->portnum * NETXEN_NIC_PORT_WINDOW; NETXEN_NIC_LOCKED_READ_REG(niu_registers[mode]. reg[i - 3] + window, @@ -385,7 +411,8 @@ static void netxen_nic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; - wol->wolopts = 0; /* options can be added depending upon the mode */ + /* options can be added depending upon the mode */ + wol->wolopts = 0; } static u32 netxen_nic_get_link(struct net_device *dev) @@ -531,9 +558,9 @@ static int netxen_nic_reg_test(struct net_device *dev) save = data_read; if (data_read) - data_written = data_read & 0xDEADBEEF; + data_written = data_read & NETXEN_NIC_INVALID_DATA; else - data_written = 0xDEADBEEF; + data_written = NETXEN_NIC_INVALID_DATA; netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MII_MGMT_STATUS(port-> portnum), @@ -559,9 +586,9 @@ static int netxen_nic_reg_test(struct net_device *dev) save = data_read; if (data_read) - data_written = data_read & 0xDEADBEEF; + data_written = data_read & NETXEN_NIC_INVALID_DATA; else - data_written = 0xDEADBEEF; + data_written = NETXEN_NIC_INVALID_DATA; netxen_nic_write_w0(adapter, NETXEN_NIU_GB_MII_MGMT_INDICATE(port-> portnum), @@ -587,9 +614,9 @@ static int netxen_nic_reg_test(struct net_device *dev) save = data_read; if (data_read) - data_written = data_read & 0xDEADBEEF; + data_written = data_read & NETXEN_NIC_INVALID_DATA; else - data_written = 0xDEADBEEF; + data_written = NETXEN_NIC_INVALID_DATA; netxen_nic_write_w0(adapter, NETXEN_NIU_GB_INTERFACE_STATUS(port-> portnum), diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index 83bf28b372a4..72c6ec4ee2a0 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -6,12 +6,12 @@ * 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, @@ -397,6 +397,7 @@ enum { #define NETXEN_ROMUSB_ROM_INSTR_OPCODE (ROMUSB_ROM + 0x0004) #define NETXEN_ROMUSB_ROM_ADDRESS (ROMUSB_ROM + 0x0008) +#define NETXEN_ROMUSB_ROM_WDATA (ROMUSB_ROM + 0x000c) #define NETXEN_ROMUSB_ROM_ABYTE_CNT (ROMUSB_ROM + 0x0010) #define NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) #define NETXEN_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) @@ -404,7 +405,29 @@ enum { /* Lock IDs for ROM lock */ #define ROM_LOCK_DRIVER 0x0d417340 -#define NETXEN_PCI_CRB_WINDOWSIZE 0x00100000 /* all are 1MB windows */ +/****************************************************************************** +* +* Definitions specific to M25P flash +* +******************************************************************************* +* Instructions +*/ +#define M25P_INSTR_WREN 0x06 +#define M25P_INSTR_WRDI 0x04 +#define M25P_INSTR_RDID 0x9f +#define M25P_INSTR_RDSR 0x05 +#define M25P_INSTR_WRSR 0x01 +#define M25P_INSTR_READ 0x03 +#define M25P_INSTR_FAST_READ 0x0b +#define M25P_INSTR_PP 0x02 +#define M25P_INSTR_SE 0xd8 +#define M25P_INSTR_BE 0xc7 +#define M25P_INSTR_DP 0xb9 +#define M25P_INSTR_RES 0xab + +/* all are 1MB windows */ + +#define NETXEN_PCI_CRB_WINDOWSIZE 0x00100000 #define NETXEN_PCI_CRB_WINDOW(A) \ (NETXEN_PCI_CRBSPACE + (A)*NETXEN_PCI_CRB_WINDOWSIZE) @@ -505,6 +528,12 @@ enum { #define NETXEN_NIU_XG_PAUSE_LEVEL (NETXEN_CRB_NIU + 0x000dc) #define NETXEN_NIU_XG_SEL (NETXEN_CRB_NIU + 0x00128) +#define NETXEN_NIU_FULL_LEVEL_XG (NETXEN_CRB_NIU + 0x00450) + +#define NETXEN_NIU_XG1_RESET (NETXEN_CRB_NIU + 0x0011c) +#define NETXEN_NIU_XG1_POWER_DOWN (NETXEN_CRB_NIU + 0x00120) +#define NETXEN_NIU_XG1_RESET_PLL (NETXEN_CRB_NIU + 0x00124) + #define NETXEN_MAC_ADDR_CNTL_REG (NETXEN_CRB_NIU + 0x1000) #define NETXEN_MULTICAST_ADDR_HI_0 (NETXEN_CRB_NIU + 0x1010) @@ -568,6 +597,29 @@ enum { #define NETXEN_NIU_XGE_REMOTE_ERROR_CNT (NETXEN_CRB_NIU + 0x70050) #define NETXEN_NIU_XGE_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x70054) #define NETXEN_NIU_XGE_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x70058) +#define NETXEN_NIU_XG1_CONFIG_0 (NETXEN_CRB_NIU + 0x80000) +#define NETXEN_NIU_XG1_CONFIG_1 (NETXEN_CRB_NIU + 0x80004) +#define NETXEN_NIU_XG1_IPG (NETXEN_CRB_NIU + 0x80008) +#define NETXEN_NIU_XG1_STATION_ADDR_0_HI (NETXEN_CRB_NIU + 0x8000c) +#define NETXEN_NIU_XG1_STATION_ADDR_0_1 (NETXEN_CRB_NIU + 0x80010) +#define NETXEN_NIU_XG1_STATION_ADDR_1_LO (NETXEN_CRB_NIU + 0x80014) +#define NETXEN_NIU_XG1_STATUS (NETXEN_CRB_NIU + 0x80018) +#define NETXEN_NIU_XG1_MAX_FRAME_SIZE (NETXEN_CRB_NIU + 0x8001c) +#define NETXEN_NIU_XG1_PAUSE_FRAME_VALUE (NETXEN_CRB_NIU + 0x80020) +#define NETXEN_NIU_XG1_TX_BYTE_CNT (NETXEN_CRB_NIU + 0x80024) +#define NETXEN_NIU_XG1_TX_FRAME_CNT (NETXEN_CRB_NIU + 0x80028) +#define NETXEN_NIU_XG1_RX_BYTE_CNT (NETXEN_CRB_NIU + 0x8002c) +#define NETXEN_NIU_XG1_RX_FRAME_CNT (NETXEN_CRB_NIU + 0x80030) +#define NETXEN_NIU_XG1_AGGR_ERROR_CNT (NETXEN_CRB_NIU + 0x80034) +#define NETXEN_NIU_XG1_MULTICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x80038) +#define NETXEN_NIU_XG1_UNICAST_FRAME_CNT (NETXEN_CRB_NIU + 0x8003c) +#define NETXEN_NIU_XG1_CRC_ERROR_CNT (NETXEN_CRB_NIU + 0x80040) +#define NETXEN_NIU_XG1_OVERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x80044) +#define NETXEN_NIU_XG1_UNDERSIZE_FRAME_ERR (NETXEN_CRB_NIU + 0x80048) +#define NETXEN_NIU_XG1_LOCAL_ERROR_CNT (NETXEN_CRB_NIU + 0x8004c) +#define NETXEN_NIU_XG1_REMOTE_ERROR_CNT (NETXEN_CRB_NIU + 0x80050) +#define NETXEN_NIU_XG1_CONTROL_CHAR_CNT (NETXEN_CRB_NIU + 0x80054) +#define NETXEN_NIU_XG1_PAUSE_FRAME_CNT (NETXEN_CRB_NIU + 0x80058) /* XG Link status */ #define XG_LINK_UP 0x10 @@ -580,8 +632,15 @@ enum { #define NETXEN_FW_VERSION_SUB (NETXEN_CAM_RAM(0x158)) #define NETXEN_ROM_LOCK_ID (NETXEN_CAM_RAM(0x100)) -#define PCIX_PS_OP_ADDR_LO (0x10000) /* Used for PS PCI Memory access */ -#define PCIX_PS_OP_ADDR_HI (0x10004) /* via CRB (PS side only) */ +#define NETXEN_PHY_LOCK_ID (NETXEN_CAM_RAM(0x120)) + +/* Lock IDs for PHY lock */ +#define PHY_LOCK_DRIVER 0x44524956 + +/* Used for PS PCI Memory access */ +#define PCIX_PS_OP_ADDR_LO (0x10000) +/* via CRB (PS side only) */ +#define PCIX_PS_OP_ADDR_HI (0x10004) #define PCIX_INT_VECTOR (0x10100) #define PCIX_INT_MASK (0x10104) @@ -609,6 +668,8 @@ enum { #define PCIE_SEM2_LOCK (0x1c010) /* Flash lock */ #define PCIE_SEM2_UNLOCK (0x1c014) /* Flash unlock */ +#define PCIE_SEM3_LOCK (0x1c018) /* Phy lock */ +#define PCIE_SEM3_UNLOCK (0x1c01c) /* Phy unlock */ #define PCIE_TGT_SPLIT_CHICKEN (0x12080) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9603c635b054..99e647a5ae76 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -6,12 +6,12 @@ * 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, @@ -43,15 +43,26 @@ #define NETXEN_FLASH_BASE (BOOTLD_START) #define NETXEN_PHANTOM_MEM_BASE (NETXEN_FLASH_BASE) #define NETXEN_MAX_MTU 8000 -#define NETXEN_MIN_MTU 64 +#define NETXEN_MIN_MTU 64 #define NETXEN_ETH_FCS_SIZE 4 #define NETXEN_ENET_HEADER_SIZE 14 -#define NETXEN_WINDOW_ONE 0x2000000 /* CRB Window: bit 25 of CRB address */ +#define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ #define NETXEN_FIRMWARE_LEN ((16 * 1024) / 4) #define NETXEN_NIU_HDRSIZE (0x1 << 6) #define NETXEN_NIU_TLRSIZE (0x1 << 5) -unsigned long netxen_nic_pci_set_window(void __iomem * pci_base, +#define lower32(x) ((u32)((x) & 0xffffffff)) +#define upper32(x) \ + ((u32)(((unsigned long long)(x) >> 32) & 0xffffffff)) + +#define NETXEN_NIC_ZERO_PAUSE_ADDR 0ULL +#define NETXEN_NIC_UNIT_PAUSE_ADDR 0x200ULL +#define NETXEN_NIC_EPG_PAUSE_ADDR1 0x2200010000c28001ULL +#define NETXEN_NIC_EPG_PAUSE_ADDR2 0x0100088866554433ULL + +#define NETXEN_NIC_WINDOW_MARGIN 0x100000 + +unsigned long netxen_nic_pci_set_window(struct netxen_adapter *adapter, unsigned long long addr); void netxen_free_hw_resources(struct netxen_adapter *adapter); @@ -93,7 +104,9 @@ void netxen_nic_set_multi(struct net_device *netdev) port->portnum, NETXEN_NIU_PROMISC_MODE); } else { - if (adapter->ops->unset_promisc) + if (adapter->ops->unset_promisc && + adapter->ahw.boardcfg.board_type + != NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) adapter->ops->unset_promisc(adapter, port->portnum, NETXEN_NIU_NON_PROMISC_MODE); @@ -161,26 +174,24 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) int netxen_nic_hw_resources(struct netxen_adapter *adapter) { struct netxen_hardware_context *hw = &adapter->ahw; - int i; u32 state = 0; void *addr; + void *pause_addr; int loops = 0, err = 0; int ctx, ring; u32 card_cmdring = 0; struct netxen_rcv_desc_crb *rcv_desc_crb = NULL; struct netxen_recv_context *recv_ctx; struct netxen_rcv_desc_ctx *rcv_desc; - struct cmd_desc_type0 *pcmd; - DPRINTK(INFO, "pci_base: %lx\n", adapter->ahw.pci_base); DPRINTK(INFO, "crb_base: %lx %lx", NETXEN_PCI_CRBSPACE, - adapter->ahw.pci_base + NETXEN_PCI_CRBSPACE); + PCI_OFFSET_SECOND_RANGE(adapter, NETXEN_PCI_CRBSPACE)); DPRINTK(INFO, "cam base: %lx %lx", NETXEN_CRB_CAM, - adapter->ahw.pci_base + NETXEN_CRB_CAM); + pci_base_offset(adapter, NETXEN_CRB_CAM)); DPRINTK(INFO, "cam RAM: %lx %lx", NETXEN_CAM_RAM_BASE, - adapter->ahw.pci_base + NETXEN_CAM_RAM_BASE); + pci_base_offset(adapter, NETXEN_CAM_RAM_BASE)); DPRINTK(INFO, "NIC base:%lx %lx\n", NIC_CRB_BASE_PORT1, - adapter->ahw.pci_base + NIC_CRB_BASE_PORT1); + pci_base_offset(adapter, NIC_CRB_BASE_PORT1)); /* Window 1 call */ card_cmdring = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMDPEG_CMDRING)); @@ -214,25 +225,34 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) } DPRINTK(INFO, "Recieve Peg ready too. starting stuff\n"); - addr = pci_alloc_consistent(adapter->ahw.pdev, - sizeof(struct cmd_desc_type0) * - adapter->max_tx_desc_count, - &hw->cmd_desc_phys_addr); + addr = netxen_alloc(adapter->ahw.pdev, + sizeof(struct cmd_desc_type0) * + adapter->max_tx_desc_count, + &hw->cmd_desc_phys_addr, &hw->cmd_desc_pdev); + if (addr == NULL) { DPRINTK(ERR, "bad return from pci_alloc_consistent\n"); - err = -ENOMEM; - return err; + return -ENOMEM; + } + + pause_addr = netxen_alloc(adapter->ahw.pdev, 512, + (dma_addr_t *) & hw->pause_physaddr, + &hw->pause_pdev); + if (pause_addr == NULL) { + DPRINTK(1, ERR, "bad return from pci_alloc_consistent\n"); + return -ENOMEM; } - /* we need to prelink all of the cmd descriptors */ - pcmd = (struct cmd_desc_type0 *)addr; - for (i = 1; i < adapter->max_tx_desc_count; i++) { - pcmd->netxen_next = - (card_cmdring + i * sizeof(struct cmd_desc_type0)); - pcmd++; + hw->pauseaddr = (char *)pause_addr; + { + u64 *ptr = (u64 *) pause_addr; + *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; + *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; + *ptr++ = NETXEN_NIC_UNIT_PAUSE_ADDR; + *ptr++ = NETXEN_NIC_ZERO_PAUSE_ADDR; + *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR1; + *ptr++ = NETXEN_NIC_EPG_PAUSE_ADDR2; } - /* fill in last link (point to first) */ - pcmd->netxen_next = card_cmdring; hw->cmd_desc_head = (struct cmd_desc_type0 *)addr; @@ -241,9 +261,10 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { rcv_desc = &recv_ctx->rcv_desc[ring]; - addr = pci_alloc_consistent(adapter->ahw.pdev, - RCV_DESC_RINGSIZE, - &rcv_desc->phys_addr); + addr = netxen_alloc(adapter->ahw.pdev, + RCV_DESC_RINGSIZE, + &rcv_desc->phys_addr, + &rcv_desc->phys_pdev); if (addr == NULL) { DPRINTK(ERR, "bad return from " "pci_alloc_consistent\n"); @@ -254,10 +275,11 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) rcv_desc->desc_head = (struct rcv_desc *)addr; } - addr = pci_alloc_consistent(adapter->ahw.pdev, - STATUS_DESC_RINGSIZE, - &recv_ctx-> - rcv_status_desc_phys_addr); + addr = netxen_alloc(adapter->ahw.pdev, + STATUS_DESC_RINGSIZE, + &recv_ctx-> + rcv_status_desc_phys_addr, + &recv_ctx->rcv_status_desc_pdev); if (addr == NULL) { DPRINTK(ERR, "bad return from" " pci_alloc_consistent\n"); @@ -273,19 +295,20 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) DPRINTK(INFO, "ring #%d crb global ring reg 0x%x\n", ring, rcv_desc_crb->crb_globalrcv_ring); /* Window = 1 */ - writel(rcv_desc->phys_addr, + writel(lower32(rcv_desc->phys_addr), NETXEN_CRB_NORMALIZE(adapter, rcv_desc_crb-> crb_globalrcv_ring)); DPRINTK(INFO, "GLOBAL_RCV_RING ctx %d, addr 0x%x" - " val 0x%x," + " val 0x%llx," " virt %p\n", ctx, rcv_desc_crb->crb_globalrcv_ring, - rcv_desc->phys_addr, rcv_desc->desc_head); + (unsigned long long)rcv_desc->phys_addr, + +rcv_desc->desc_head); } /* Window = 1 */ - writel(recv_ctx->rcv_status_desc_phys_addr, + writel(lower32(recv_ctx->rcv_status_desc_phys_addr), NETXEN_CRB_NORMALIZE(adapter, recv_crb_registers[ctx]. crb_rcvstatus_ring)); @@ -293,13 +316,19 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) " val 0x%x,virt%p\n", ctx, recv_crb_registers[ctx].crb_rcvstatus_ring, - recv_ctx->rcv_status_desc_phys_addr, + (unsigned long long)recv_ctx->rcv_status_desc_phys_addr, recv_ctx->rcv_status_desc_head); } /* Window = 1 */ - writel(hw->cmd_desc_phys_addr, - NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + writel(lower32(hw->pause_physaddr), + NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_LO)); + writel(upper32(hw->pause_physaddr), + NETXEN_CRB_NORMALIZE(adapter, CRB_PAUSE_ADDR_HI)); + writel(lower32(hw->cmd_desc_phys_addr), + NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + writel(upper32(hw->cmd_desc_phys_addr), + NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_HI)); return err; } @@ -310,13 +339,19 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) int ctx, ring; if (adapter->ahw.cmd_desc_head != NULL) { - pci_free_consistent(adapter->ahw.pdev, + pci_free_consistent(adapter->ahw.cmd_desc_pdev, sizeof(struct cmd_desc_type0) * adapter->max_tx_desc_count, adapter->ahw.cmd_desc_head, adapter->ahw.cmd_desc_phys_addr); adapter->ahw.cmd_desc_head = NULL; } + if (adapter->ahw.pauseaddr != NULL) { + pci_free_consistent(adapter->ahw.pause_pdev, 512, + adapter->ahw.pauseaddr, + adapter->ahw.pause_physaddr); + adapter->ahw.pauseaddr = NULL; + } for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { recv_ctx = &adapter->recv_ctx[ctx]; @@ -324,7 +359,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) rcv_desc = &recv_ctx->rcv_desc[ring]; if (rcv_desc->desc_head != NULL) { - pci_free_consistent(adapter->ahw.pdev, + pci_free_consistent(rcv_desc->phys_pdev, RCV_DESC_RINGSIZE, rcv_desc->desc_head, rcv_desc->phys_addr); @@ -333,7 +368,7 @@ void netxen_free_hw_resources(struct netxen_adapter *adapter) } if (recv_ctx->rcv_status_desc_head != NULL) { - pci_free_consistent(adapter->ahw.pdev, + pci_free_consistent(recv_ctx->rcv_status_desc_pdev, STATUS_DESC_RINGSIZE, recv_ctx->rcv_status_desc_head, recv_ctx-> @@ -360,10 +395,10 @@ void netxen_tso_check(struct netxen_adapter *adapter, return; } } + adapter->stats.xmitcsummed++; CMD_DESC_TCP_HDR_OFFSET_WRT(desc, skb->h.raw - skb->data); desc->length_tcp_hdr = cpu_to_le32(desc->length_tcp_hdr); desc->ip_hdr_offset = skb->nh.raw - skb->data; - adapter->stats.xmitcsummed++; } int netxen_is_flash_supported(struct netxen_adapter *adapter) @@ -373,7 +408,7 @@ int netxen_is_flash_supported(struct netxen_adapter *adapter) /* if the flash size less than 4Mb, make huge war cry and die */ for (j = 1; j < 4; j++) { - addr = j * 0x100000; + addr = j * NETXEN_NIC_WINDOW_MARGIN; for (i = 0; i < (sizeof(locs) / sizeof(locs[0])); i++) { if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0 && netxen_rom_fast_read(adapter, (addr + locs[i]), @@ -458,7 +493,9 @@ void netxen_nic_pci_change_crbwindow(struct netxen_adapter *adapter, u32 wndw) * register address is received by PCI. The direct region bypasses * the CRB bus. */ - offset = adapter->ahw.pci_base + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW); + offset = + PCI_OFFSET_SECOND_RANGE(adapter, + NETXEN_PCIX_PH_REG(PCIX_CRB_WINDOW)); if (wndw & 0x1) wndw = NETXEN_WINDOW_ONE; @@ -497,8 +534,8 @@ void netxen_load_firmware(struct netxen_adapter *adapter) "loading flash image\n"); return; } - off = netxen_nic_pci_set_window(adapter->ahw.pci_base, memaddr); - addr = (adapter->ahw.pci_base + off); + off = netxen_nic_pci_set_window(adapter, memaddr); + addr = pci_base_offset(adapter, off); writel(data, addr); flashaddr += 4; memaddr += 4; @@ -521,14 +558,19 @@ netxen_nic_hw_write_wx(struct netxen_adapter *adapter, u64 off, void *data, if (ADDR_IN_WINDOW1(off)) { addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ - addr = adapter->ahw.pci_base + off; + addr = pci_base_offset(adapter, off); netxen_nic_pci_change_crbwindow(adapter, 0); } DPRINTK(INFO, "writing to base %lx offset %llx addr %p" " data %llx len %d\n", - adapter->ahw.pci_base, off, addr, + pci_base(adapter, off), off, addr, *(unsigned long long *)data, len); + if (!addr) { + netxen_nic_pci_change_crbwindow(adapter, 1); + return 1; + } + switch (len) { case 1: writeb(*(u8 *) data, addr); @@ -566,12 +608,16 @@ netxen_nic_hw_read_wx(struct netxen_adapter *adapter, u64 off, void *data, if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ addr = NETXEN_CRB_NORMALIZE(adapter, off); } else { /* Window 0 */ - addr = adapter->ahw.pci_base + off; + addr = pci_base_offset(adapter, off); netxen_nic_pci_change_crbwindow(adapter, 0); } DPRINTK(INFO, "reading from base %lx offset %llx addr %p\n", - adapter->ahw.pci_base, off, addr); + pci_base(adapter, off), off, addr); + if (!addr) { + netxen_nic_pci_change_crbwindow(adapter, 1); + return 1; + } switch (len) { case 1: *(u8 *) data = readb(addr); @@ -604,7 +650,7 @@ void netxen_nic_reg_write(struct netxen_adapter *adapter, u64 off, u32 val) addr = NETXEN_CRB_NORMALIZE(adapter, off); DPRINTK(INFO, "writing to base %lx offset %llx addr %p data %x\n", - adapter->ahw.pci_base, off, addr, val); + pci_base(adapter, off), off, addr); writel(val, addr); } @@ -629,7 +675,7 @@ void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) void __iomem *addr; netxen_nic_pci_change_crbwindow(adapter, 0); - addr = (void __iomem *)(adapter->ahw.pci_base + index); + addr = (void __iomem *)(pci_base_offset(adapter, index)); writel(value, addr); netxen_nic_pci_change_crbwindow(adapter, 1); } @@ -639,7 +685,7 @@ void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value) { void __iomem *addr; - addr = (void __iomem *)(adapter->ahw.pci_base + index); + addr = (void __iomem *)(pci_base_offset(adapter, index)); netxen_nic_pci_change_crbwindow(adapter, 0); *value = readl(addr); @@ -649,7 +695,8 @@ void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value) int netxen_pci_set_window_warning_count = 0; unsigned long -netxen_nic_pci_set_window(void __iomem * pci_base, unsigned long long addr) +netxen_nic_pci_set_window(struct netxen_adapter *adapter, + unsigned long long addr) { static int ddr_mn_window = -1; static int qdr_sn_window = -1; @@ -661,12 +708,15 @@ netxen_nic_pci_set_window(void __iomem * pci_base, unsigned long long addr) window = (addr >> 25) & 0x3ff; if (ddr_mn_window != window) { ddr_mn_window = window; - writel(window, pci_base + - NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW)); + writel(window, PCI_OFFSET_SECOND_RANGE(adapter, + NETXEN_PCIX_PH_REG + (PCIX_MN_WINDOW))); /* MUST make sure window is set before we forge on... */ - readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_MN_WINDOW)); + readl(PCI_OFFSET_SECOND_RANGE(adapter, + NETXEN_PCIX_PH_REG + (PCIX_MN_WINDOW))); } - addr -= (window * 0x2000000); + addr -= (window * NETXEN_WINDOW_ONE); addr += NETXEN_PCI_DDR_NET; } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { addr -= NETXEN_ADDR_OCM0; @@ -682,10 +732,14 @@ netxen_nic_pci_set_window(void __iomem * pci_base, unsigned long long addr) window = (addr >> 22) & 0x3f; if (qdr_sn_window != window) { qdr_sn_window = window; - writel((window << 22), pci_base + - NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW)); + writel((window << 22), + PCI_OFFSET_SECOND_RANGE(adapter, + NETXEN_PCIX_PH_REG + (PCIX_SN_WINDOW))); /* MUST make sure window is set before we forge on... */ - readl(pci_base + NETXEN_PCIX_PH_REG(PCIX_SN_WINDOW)); + readl(PCI_OFFSET_SECOND_RANGE(adapter, + NETXEN_PCIX_PH_REG + (PCIX_SN_WINDOW))); } addr -= (window * 0x400000); addr += NETXEN_PCI_QDR_NET; @@ -811,7 +865,7 @@ netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); } else { netxen_nic_pci_change_crbwindow(adapter, 0); - addr = (void __iomem *)(adapter->ahw.pci_base + off); + addr = (void __iomem *)(pci_base_offset(adapter, off)); writel(data, addr); netxen_nic_pci_change_crbwindow(adapter, 1); } @@ -879,6 +933,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) u32 fw_major = 0; u32 fw_minor = 0; u32 fw_build = 0; + char brd_name[NETXEN_MAX_SHORT_NAME]; + struct netxen_new_user_info user_info; + int i, addr = USER_START; + u32 *ptr32; struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); if (board_info->magic != NETXEN_BDINFO_MAGIC) { @@ -894,6 +952,24 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) valid = 0; } if (valid) { + ptr32 = (u32 *) & user_info; + for (i = 0; + i < sizeof(struct netxen_new_user_info) / sizeof(u32); + i++) { + if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { + printk("%s: ERROR reading %s board userarea.\n", + netxen_nic_driver_name, + netxen_nic_driver_name); + return; + } + ptr32++; + addr += sizeof(u32); + } + get_brd_name_by_type(board_info->board_type, brd_name); + + printk("NetXen %s Board S/N %s Chip id 0x%x\n", + brd_name, user_info.serial_num, board_info->chip_id); + printk("NetXen %s Board #%d, Chip id 0x%x\n", board_info->board_type == 0x0b ? "XGB" : "GBE", board_info->board_num, board_info->chip_id); diff --git a/drivers/net/netxen/netxen_nic_hw.h b/drivers/net/netxen/netxen_nic_hw.h index fb1a0253863f..201a636b7ab8 100644 --- a/drivers/net/netxen/netxen_nic_hw.h +++ b/drivers/net/netxen/netxen_nic_hw.h @@ -82,9 +82,9 @@ struct netxen_adapter; #define NETXEN_PCI_MAPSIZE_BYTES (NETXEN_PCI_MAPSIZE << 20) -#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \ - addr = (adapter->ahw.pci_base + X); \ - *(u32 *)Y = readl((void __iomem*) addr); +#define NETXEN_NIC_LOCKED_READ_REG(X, Y) \ + addr = pci_base_offset(adapter, (X)); \ + *(u32 *)Y = readl(addr); struct netxen_port; void netxen_nic_set_link_parameters(struct netxen_port *port); @@ -472,6 +472,8 @@ int netxen_niu_xg_macaddr_set(struct netxen_port *port, /* Generic enable for GbE ports. Will detect the speed of the link. */ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port); +int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port); + /* Disable a GbE interface */ int netxen_niu_disable_gbe_port(struct netxen_adapter *adapter, int port); diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index d122e51e43ab..0dca029bc3e5 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -51,11 +51,13 @@ static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \ NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20 +#define NETXEN_NIC_XDMA_RESET 0x8000ff + static inline void netxen_nic_locked_write_reg(struct netxen_adapter *adapter, unsigned long off, int *data) { - void __iomem *addr = (adapter->ahw.pci_base + off); + void __iomem *addr = pci_base_offset(adapter, off); writel(*data, addr); } @@ -141,6 +143,24 @@ int netxen_init_firmware(struct netxen_adapter *adapter) return err; } +#define NETXEN_ADDR_LIMIT 0xffffffffULL + +void *netxen_alloc(struct pci_dev *pdev, size_t sz, dma_addr_t * ptr, + struct pci_dev **used_dev) +{ + void *addr; + + addr = pci_alloc_consistent(pdev, sz, ptr); + if ((unsigned long long)(*ptr) < NETXEN_ADDR_LIMIT) { + *used_dev = pdev; + return addr; + } + pci_free_consistent(pdev, sz, addr, *ptr); + addr = pci_alloc_consistent(NULL, sz, ptr); + *used_dev = NULL; + return addr; +} + void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) { int ctxid, ring; @@ -177,23 +197,17 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter) void netxen_initialize_adapter_hw(struct netxen_adapter *adapter) { + int ports = 0; + struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); + if (netxen_nic_get_board_info(adapter) != 0) printk("%s: Error getting board config info.\n", netxen_nic_driver_name); - - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - adapter->ahw.max_ports = 4; - break; - - case NETXEN_NIC_XGBE: - adapter->ahw.max_ports = 1; - break; - - default: + get_brd_port_by_type(board_info->board_type, &ports); + if (ports == 0) printk(KERN_ERR "%s: Unknown board type\n", netxen_nic_driver_name); - } + adapter->ahw.max_ports = ports; } void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) @@ -225,6 +239,7 @@ void netxen_initialize_adapter_ops(struct netxen_adapter *adapter) ops->handle_phy_intr = netxen_nic_xgbe_handle_phy_intr; ops->macaddr_set = netxen_niu_xg_macaddr_set; ops->set_mtu = netxen_nic_set_mtu_xgb; + ops->init_port = netxen_niu_xg_init_port; ops->set_promisc = netxen_niu_xg_set_promiscuous_mode; ops->unset_promisc = netxen_niu_xg_set_promiscuous_mode; ops->stop_port = netxen_niu_disable_xg_port; @@ -295,15 +310,6 @@ static inline int rom_lock(struct netxen_adapter *adapter) return 0; } -static inline void rom_unlock(struct netxen_adapter *adapter) -{ - u32 val; - - /* release semaphore2 */ - netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val); - -} - int netxen_wait_rom_done(struct netxen_adapter *adapter) { long timeout = 0; @@ -321,6 +327,81 @@ int netxen_wait_rom_done(struct netxen_adapter *adapter) return 0; } +static inline int netxen_rom_wren(struct netxen_adapter *adapter) +{ + /* Set write enable latch in ROM status register */ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, + M25P_INSTR_WREN); + if (netxen_wait_rom_done(adapter)) { + return -1; + } + return 0; +} + +static inline unsigned int netxen_rdcrbreg(struct netxen_adapter *adapter, + unsigned int addr) +{ + unsigned int data = 0xdeaddead; + data = netxen_nic_reg_read(adapter, addr); + return data; +} + +static inline int netxen_do_rom_rdsr(struct netxen_adapter *adapter) +{ + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, + M25P_INSTR_RDSR); + if (netxen_wait_rom_done(adapter)) { + return -1; + } + return netxen_rdcrbreg(adapter, NETXEN_ROMUSB_ROM_RDATA); +} + +static inline void netxen_rom_unlock(struct netxen_adapter *adapter) +{ + u32 val; + + /* release semaphore2 */ + netxen_nic_read_w0(adapter, NETXEN_PCIE_REG(PCIE_SEM2_UNLOCK), &val); + +} + +int netxen_rom_wip_poll(struct netxen_adapter *adapter) +{ + long timeout = 0; + long wip = 1; + int val; + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + while (wip != 0) { + val = netxen_do_rom_rdsr(adapter); + wip = val & 1; + timeout++; + if (timeout > rom_max_timeout) { + return -1; + } + } + return 0; +} + +static inline int do_rom_fast_write(struct netxen_adapter *adapter, + int addr, int data) +{ + if (netxen_rom_wren(adapter)) { + return -1; + } + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_WDATA, data); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, + M25P_INSTR_PP); + if (netxen_wait_rom_done(adapter)) { + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + return -1; + } + + return netxen_rom_wip_poll(adapter); +} + static inline int do_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) { @@ -350,7 +431,43 @@ int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) return -EIO; ret = do_rom_fast_read(adapter, addr, valp); - rom_unlock(adapter); + netxen_rom_unlock(adapter); + return ret; +} + +int netxen_rom_fast_write(struct netxen_adapter *adapter, int addr, int data) +{ + int ret = 0; + + if (rom_lock(adapter) != 0) { + return -1; + } + ret = do_rom_fast_write(adapter, addr, data); + netxen_rom_unlock(adapter); + return ret; +} +int netxen_do_rom_se(struct netxen_adapter *adapter, int addr) +{ + netxen_rom_wren(adapter); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, + M25P_INSTR_SE); + if (netxen_wait_rom_done(adapter)) { + netxen_nic_reg_write(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); + return -1; + } + return netxen_rom_wip_poll(adapter); +} + +int netxen_rom_se(struct netxen_adapter *adapter, int addr) +{ + int ret = 0; + if (rom_lock(adapter) != 0) { + return -1; + } + ret = netxen_do_rom_se(adapter, addr); + netxen_rom_unlock(adapter); return ret; } @@ -372,7 +489,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) /* resetall */ status = netxen_nic_get_board_info(adapter); if (status) - printk("%s: pinit_from_rom: Error getting board info\n", + printk("%s: netxen_pinit_from_rom: Error getting board info\n", netxen_nic_driver_name); netxen_crb_writelit_adapter(adapter, NETXEN_ROMUSB_GLB_SW_RESET, @@ -408,8 +525,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); if (buf == NULL) { - printk("%s: pinit_from_rom: Unable to calloc memory.\n", - netxen_nic_driver_name); + printk("%s: netxen_pinit_from_rom: Unable to calloc " + "memory.\n", netxen_nic_driver_name); return -ENOMEM; } for (i = 0; i < n; i++) { @@ -441,7 +558,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) if (off == NETXEN_ROMUSB_GLB_SW_RESET) { init_delay = 1; /* hold xdma in reset also */ - buf[i].data = 0x8000ff; + buf[i].data = NETXEN_NIC_XDMA_RESET; } if (ADDR_IN_WINDOW1(off)) { @@ -450,7 +567,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) } else { netxen_nic_pci_change_crbwindow(adapter, 0); writel(buf[i].data, - adapter->ahw.pci_base + off); + pci_base_offset(adapter, off)); netxen_nic_pci_change_crbwindow(adapter, 1); } @@ -505,18 +622,15 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose) return 0; } -void netxen_phantom_init(struct netxen_adapter *adapter) +void netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) { u32 val = 0; int loops = 0; - netxen_nic_hw_read_wx(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE, &val, 4); - writel(1, - NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); - - if (0 == val) { + if (!pegtune_val) { while (val != PHAN_INITIALIZE_COMPLETE && loops < 200000) { udelay(100); + schedule(); val = readl(NETXEN_CRB_NORMALIZE (adapter, CRB_CMDPEG_STATE)); @@ -536,7 +650,7 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter) &(adapter->recv_ctx[ctx]); u32 consumer; struct status_desc *desc_head; - struct status_desc *desc; /* used to read status desc here */ + struct status_desc *desc; consumer = recv_ctx->status_rx_consumer; desc_head = recv_ctx->rcv_status_desc_head; @@ -549,6 +663,53 @@ int netxen_nic_rx_has_work(struct netxen_adapter *adapter) return 0; } +static inline int netxen_nic_check_temp(struct netxen_adapter *adapter) +{ + int port_num; + struct netxen_port *port; + struct net_device *netdev; + uint32_t temp, temp_state, temp_val; + int rv = 0; + + temp = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_TEMP_STATE)); + + temp_state = nx_get_temp_state(temp); + temp_val = nx_get_temp_val(temp); + + if (temp_state == NX_TEMP_PANIC) { + printk(KERN_ALERT + "%s: Device temperature %d degrees C exceeds" + " maximum allowed. Hardware has been shut down.\n", + netxen_nic_driver_name, temp_val); + for (port_num = 0; port_num < adapter->ahw.max_ports; + port_num++) { + port = adapter->port[port_num]; + netdev = port->netdev; + + netif_carrier_off(netdev); + netif_stop_queue(netdev); + } + rv = 1; + } else if (temp_state == NX_TEMP_WARN) { + if (adapter->temp == NX_TEMP_NORMAL) { + printk(KERN_ALERT + "%s: Device temperature %d degrees C " + "exceeds operating range." + " Immediate action needed.\n", + netxen_nic_driver_name, temp_val); + } + } else { + if (adapter->temp == NX_TEMP_WARN) { + printk(KERN_INFO + "%s: Device temperature is now %d degrees C" + " in normal range.\n", netxen_nic_driver_name, + temp_val); + } + } + adapter->temp = temp_state; + return rv; +} + void netxen_watchdog_task(unsigned long v) { int port_num; @@ -556,6 +717,9 @@ void netxen_watchdog_task(unsigned long v) struct net_device *netdev; struct netxen_adapter *adapter = (struct netxen_adapter *)v; + if (netxen_nic_check_temp(adapter)) + return; + for (port_num = 0; port_num < adapter->ahw.max_ports; port_num++) { port = adapter->port[port_num]; netdev = port->netdev; @@ -570,8 +734,6 @@ void netxen_watchdog_task(unsigned long v) netif_wake_queue(netdev); } - netxen_nic_pci_change_crbwindow(adapter, 1); - if (adapter->ops->handle_phy_intr) adapter->ops->handle_phy_intr(adapter); mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); @@ -742,7 +904,6 @@ void netxen_process_cmd_ring(unsigned long data) * number as part of the descriptor. This way we will be able to get * the netdev which is associated with that device. */ - /* Window = 1 */ consumer = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); @@ -861,7 +1022,7 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid) * We need to schedule the posting of buffers to the pegs. */ rcv_desc->begin_alloc = index; - DPRINTK(ERR, "unm_post_rx_buffers: " + DPRINTK(ERR, "netxen_post_rx_buffers: " " allocated only %d buffers\n", count); break; } diff --git a/drivers/net/netxen/netxen_nic_ioctl.h b/drivers/net/netxen/netxen_nic_ioctl.h index 806818eb9630..23e53adbf123 100644 --- a/drivers/net/netxen/netxen_nic_ioctl.h +++ b/drivers/net/netxen/netxen_nic_ioctl.h @@ -6,12 +6,12 @@ * 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, @@ -32,9 +32,11 @@ #include -#define NETXEN_CMD_START SIOCDEVPRIVATE -#define NETXEN_NIC_CMD (NETXEN_CMD_START + 1) -#define NETXEN_NIC_NAME (NETXEN_CMD_START + 2) +#define NETXEN_CMD_START SIOCDEVPRIVATE +#define NETXEN_NIC_CMD (NETXEN_CMD_START + 1) +#define NETXEN_NIC_NAME (NETXEN_CMD_START + 2) +#define NETXEN_NIC_NAME_LEN 16 +#define NETXEN_NIC_NAME_RSP "NETXEN" typedef enum { netxen_nic_cmd_none = 0, diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c index f1c3e5af03a9..ae180fee8008 100644 --- a/drivers/net/netxen/netxen_nic_isr.c +++ b/drivers/net/netxen/netxen_nic_isr.c @@ -149,47 +149,41 @@ void netxen_handle_port_int(struct netxen_adapter *adapter, u32 portno, void netxen_nic_isr_other(struct netxen_adapter *adapter) { - u32 enable, portno; - u32 i2qhi; - - /* - * bit 3 is for i2qInt, if high its enabled - * check for phy interrupts - * read vector and check for bit 45 for phy - * clear int by writing the same value into ISR_INT_VECTOR REG - */ - - DPRINTK(INFO, "I2Q is the source of INT \n"); + u32 portno; + u32 val, linkup, qg_linksup; /* verify the offset */ - i2qhi = readl(NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); - - DPRINTK(INFO, "isr NETXEN_I2Q_CLR_PCI_HI = 0x%x \n", i2qhi); + val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE)); + if (val == adapter->ahw.qg_linksup) + return; - if (i2qhi & 0x4000) { - for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) { - DPRINTK(INFO, "External PHY interrupt ON PORT %d\n", - portno); + qg_linksup = adapter->ahw.qg_linksup; + adapter->ahw.qg_linksup = val; + DPRINTK(1, INFO, "%s: link update 0x%08x\n", netxen_nic_driver_name, + val); + for (portno = 0; portno < NETXEN_NIU_MAX_GBE_PORTS; portno++) { + linkup = val & 1; + if (linkup != (qg_linksup & 1)) { + printk(KERN_INFO "%s: PORT %d link %s\n", + netxen_nic_driver_name, portno, + ((linkup == 0) ? "down" : "up")); + netxen_indicate_link_status(adapter, portno, linkup); + if (linkup) + netxen_nic_set_link_parameters(adapter-> + port[portno]); - enable = 1; - netxen_handle_port_int(adapter, portno, enable); } + val = val >> 1; + qg_linksup = qg_linksup >> 1; + } - /* Clear the interrupt on I2Q */ - writel((u32) i2qhi, - NETXEN_CRB_NORMALIZE(adapter, NETXEN_I2Q_CLR_PCI_HI)); + adapter->stats.otherints++; - } } void netxen_nic_gbe_handle_phy_intr(struct netxen_adapter *adapter) { - u32 val; - val = readl(NETXEN_CRB_NORMALIZE(adapter, ISR_INT_VECTOR)); - if (val & 0x4) { - adapter->stats.otherints++; - netxen_nic_isr_other(adapter); - } + netxen_nic_isr_other(adapter); } void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index ffd272c93a6b..cd1336e899b1 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -31,6 +31,7 @@ * */ +#include #include "netxen_nic_hw.h" #include "netxen_nic.h" @@ -41,16 +42,19 @@ #include #include +#define PHAN_VENDOR_ID 0x4040 + MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); char netxen_nic_driver_name[] = "netxen"; static char netxen_nic_driver_string[] = "NetXen Network Driver version " - NETXEN_NIC_LINUX_VERSIONID "-" NETXEN_NIC_BUILD_NO; + NETXEN_NIC_LINUX_VERSIONID; #define NETXEN_NETDEV_WEIGHT 120 #define NETXEN_ADAPTER_UP_MAGIC 777 +#define NETXEN_NIC_PEG_TUNE 0 /* Local functions to NetXen NIC driver */ static int __devinit netxen_nic_probe(struct pci_dev *pdev, @@ -101,7 +105,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *netdev = NULL; struct netxen_adapter *adapter = NULL; struct netxen_port *port = NULL; - u8 __iomem *mem_ptr = NULL; + u8 *mem_ptr0 = NULL; + u8 *mem_ptr1 = NULL; + u8 *mem_ptr2 = NULL; + unsigned long mem_base, mem_len; int pci_using_dac, i, err; int ring; @@ -111,6 +118,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) u64 mac_addr[FLASH_NUM_PORTS + 1]; int valid_mac; + printk(KERN_INFO "%s \n", netxen_nic_driver_string); if ((err = pci_enable_device(pdev))) return err; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { @@ -138,11 +146,26 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mem_len = pci_resource_len(pdev, 0); /* 128 Meg of memory */ - mem_ptr = ioremap(mem_base, NETXEN_PCI_MAPSIZE_BYTES); - if (mem_ptr == 0UL) { - printk(KERN_ERR "%s: Cannot ioremap adapter memory aborting." - ":%p\n", netxen_nic_driver_name, mem_ptr); + mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE); + mem_ptr1 = + ioremap(mem_base + SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_SIZE); + mem_ptr2 = + ioremap(mem_base + THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); + + if ((mem_ptr0 == 0UL) || (mem_ptr1 == 0UL) || (mem_ptr2 == 0UL)) { + DPRINTK(1, ERR, + "Cannot remap adapter memory aborting.:" + "0 -> %p, 1 -> %p, 2 -> %p\n", + mem_ptr0, mem_ptr1, mem_ptr2); + err = -EIO; + if (mem_ptr0) + iounmap(mem_ptr0); + if (mem_ptr1) + iounmap(mem_ptr1); + if (mem_ptr2) + iounmap(mem_ptr2); + goto err_out_free_res; } @@ -221,9 +244,17 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } adapter->cmd_buf_arr = cmd_buf_arr; - adapter->ahw.pci_base = mem_ptr; + adapter->ahw.pci_base0 = mem_ptr0; + adapter->ahw.pci_base1 = mem_ptr1; + adapter->ahw.pci_base2 = mem_ptr2; spin_lock_init(&adapter->tx_lock); spin_lock_init(&adapter->lock); +#ifdef CONFIG_IA64 + netxen_pinit_from_rom(adapter, 0); + udelay(500); + netxen_load_firmware(adapter); +#endif + /* initialize the buffers in adapter */ netxen_initialize_adapter_sw(adapter); /* @@ -262,6 +293,20 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) else valid_mac = 0; + /* + * Initialize all the CRB registers here. + */ + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); + writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); + + /* Unlock the HW, prompting the boot sequence */ + writel(1, + NETXEN_CRB_NORMALIZE(adapter, NETXEN_ROMUSB_GLB_PEGTUNE_DONE)); + + /* Handshake with the card before we register the devices. */ + netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); + /* initialize the all the ports */ for (i = 0; i < adapter->ahw.max_ports; i++) { @@ -351,15 +396,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) adapter->port[i] = port; } - /* - * Initialize all the CRB registers here. - */ - /* Window = 1 */ - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_PRODUCER_OFFSET)); - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_CMD_CONSUMER_OFFSET)); - writel(0, NETXEN_CRB_NORMALIZE(adapter, CRB_HOST_CMD_ADDR_LO)); - - netxen_phantom_init(adapter); /* * delay a while to ensure that the Pegs are up & running. * Otherwise, we might see some flaky behaviour. @@ -414,7 +450,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) kfree(adapter); err_out_iounmap: - iounmap(mem_ptr); + iounmap(mem_ptr0); + iounmap(mem_ptr1); + iounmap(mem_ptr2); + err_out_free_res: pci_release_regions(pdev); err_out_disable_pdev: @@ -460,7 +499,9 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) netxen_free_hw_resources(adapter); - iounmap(adapter->ahw.pci_base); + iounmap(adapter->ahw.pci_base0); + iounmap(adapter->ahw.pci_base1); + iounmap(adapter->ahw.pci_base2); pci_release_regions(pdev); pci_disable_device(pdev); @@ -496,7 +537,6 @@ static int netxen_nic_open(struct net_device *netdev) { struct netxen_port *port = netdev_priv(netdev); struct netxen_adapter *adapter = port->adapter; - struct netxen_rcv_desc_ctx *rcv_desc; int err = 0; int ctx, ring; @@ -527,11 +567,8 @@ static int netxen_nic_open(struct net_device *netdev) if (adapter->ops->init_niu) adapter->ops->init_niu(adapter); for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { - for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) { - rcv_desc = - &adapter->recv_ctx[ctx].rcv_desc[ring]; + for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) netxen_post_rx_buffers(adapter, ctx, ring); - } } adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; } @@ -579,10 +616,6 @@ static int netxen_nic_close(struct net_device *netdev) netif_carrier_off(netdev); netif_stop_queue(netdev); - /* disable phy_ints */ - if (adapter->ops->disable_phy_interrupts) - adapter->ops->disable_phy_interrupts(adapter, port->portnum); - adapter->active_ports--; if (!adapter->active_ports) { @@ -690,13 +723,16 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) local_producer = adapter->cmd_producer; /* There 4 fragments per descriptor */ no_of_desc = (frag_count + 3) >> 2; - if (skb_shinfo(skb)->gso_size > 0) { - no_of_desc++; - if (((skb->nh.iph)->ihl * sizeof(u32)) + - ((skb->h.th)->doff * sizeof(u32)) + - sizeof(struct ethhdr) > - (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { + if (netdev->features & NETIF_F_TSO) { + if (skb_shinfo(skb)->gso_size > 0) { + no_of_desc++; + if (((skb->nh.iph)->ihl * sizeof(u32)) + + ((skb->h.th)->doff * sizeof(u32)) + + sizeof(struct ethhdr) > + (sizeof(struct cmd_desc_type0) - NET_IP_ALIGN)) { + no_of_desc++; + } } } k = adapter->cmd_producer; @@ -740,7 +776,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) memset(hwdesc, 0, sizeof(struct cmd_desc_type0)); /* Take skb->data itself */ pbuf = &adapter->cmd_buf_arr[producer]; - if (skb_shinfo(skb)->gso_size > 0) { + if ((netdev->features & NETIF_F_TSO) && skb_shinfo(skb)->gso_size > 0) { pbuf->mss = skb_shinfo(skb)->gso_size; hwdesc->mss = skb_shinfo(skb)->gso_size; } else { @@ -934,9 +970,10 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) /* Window = 0 or 1 */ do { writel(0xffffffff, (void __iomem *) - (adapter->ahw.pci_base + ISR_INT_TARGET_STATUS)); + (PCI_OFFSET_SECOND_RANGE + (adapter, ISR_INT_TARGET_STATUS))); mask = readl((void __iomem *) - (adapter->ahw.pci_base + ISR_INT_VECTOR)); + pci_base_offset(adapter, ISR_INT_VECTOR)); } while (((mask & 0x80) != 0) && (++count < 32)); if ((mask & 0x80) != 0) printk("Could not disable interrupt completely\n"); @@ -1065,8 +1102,10 @@ static int netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { int err = 0; + unsigned long nr_bytes = 0; struct netxen_port *port = netdev_priv(netdev); struct netxen_adapter *adapter = port->adapter; + char dev_name[NETXEN_NIC_NAME_LEN]; DPRINTK(INFO, "doing ioctl for %s\n", netdev->name); switch (cmd) { @@ -1077,7 +1116,13 @@ netxen_nic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case NETXEN_NIC_NAME: DPRINTK(INFO, "ioctl cmd for NetXen\n"); if (ifr->ifr_data) { - put_user(port->portnum, (u16 __user *) ifr->ifr_data); + sprintf(dev_name, "%s-%d", NETXEN_NIC_NAME_RSP, + port->portnum); + nr_bytes = copy_to_user((char *)ifr->ifr_data, dev_name, + NETXEN_NIC_NAME_LEN); + if (nr_bytes) + err = -EIO; + } break; @@ -1101,8 +1146,6 @@ static struct pci_driver netxen_driver = { static int __init netxen_init_module(void) { - printk(KERN_INFO "%s \n", netxen_nic_driver_string); - return pci_module_init(&netxen_driver); } diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c index 6e421c876fe5..7950a04532e6 100644 --- a/drivers/net/netxen/netxen_nic_niu.c +++ b/drivers/net/netxen/netxen_nic_niu.c @@ -6,12 +6,12 @@ * 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, @@ -32,19 +32,56 @@ */ #include "netxen_nic.h" -#include + +#define NETXEN_GB_MAC_SOFT_RESET 0x80000000 +#define NETXEN_GB_MAC_RESET_PROT_BLK 0x000F0000 +#define NETXEN_GB_MAC_ENABLE_TX_RX 0x00000005 +#define NETXEN_GB_MAC_PAUSED_FRMS 0x00000020 + +static long phy_lock_timeout = 100000000; + +static inline int phy_lock(void) +{ + int i; + int done = 0, timeout = 0; + + while (!done) { + done = readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_LOCK)); + if (done == 1) + break; + if (timeout >= phy_lock_timeout) { + return -1; + } + timeout++; + if (!in_atomic()) + schedule(); + else { + for (i = 0; i < 20; i++) + cpu_relax(); + } + } + + writel(NETXEN_PHY_LOCK_ID, (void __iomem *)PHY_LOCK_DRIVER); + return 0; +} + +static inline int phy_unlock(void) +{ + readl((void __iomem *)NETXEN_PCIE_REG(PCIE_SEM3_UNLOCK)); + return 0; +} /* * netxen_niu_gbe_phy_read - read a register from the GbE PHY via * mii management interface. * * Note: The MII management interface goes through port 0. - * Individual phys are addressed as follows: + * Individual phys are addressed as follows: * @param phy [15:8] phy id * @param reg [7:0] register number * * @returns 0 on success - * -1 on error + * -1 on error * */ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, @@ -56,10 +93,17 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, __le32 address; __le32 command; __le32 status; - __le32 mii_cfg; __le32 mac_cfg0; - /* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */ + if (phy_lock() != 0) { + return -1; + } + + /* + * MII mgmt all goes through port 0 MAC interface, + * so it cannot be in reset + */ + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4)) return -EIO; @@ -77,18 +121,6 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, restore = 1; } - /* reset MII management interface */ - mii_cfg = 0; - netxen_gb_set_mii_mgmt_clockselect(mii_cfg, 7); - netxen_gb_mii_mgmt_reset(mii_cfg); - if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0), - &mii_cfg, 4)) - return -EIO; - netxen_gb_mii_mgmt_unset(mii_cfg); - if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_MII_MGMT_CONFIG(0), - &mii_cfg, 4)) - return -EIO; - address = 0; netxen_gb_mii_mgmt_reg_addr(address, reg); netxen_gb_mii_mgmt_phy_addr(address, phy); @@ -130,7 +162,7 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, NETXEN_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4)) return -EIO; - + phy_unlock(); return result; } @@ -139,12 +171,12 @@ int netxen_niu_gbe_phy_read(struct netxen_adapter *adapter, long phy, * mii management interface. * * Note: The MII management interface goes through port 0. - * Individual phys are addressed as follows: + * Individual phys are addressed as follows: * @param phy [15:8] phy id * @param reg [7:0] register number * * @returns 0 on success - * -1 on error + * -1 on error * */ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, @@ -158,7 +190,11 @@ int netxen_niu_gbe_phy_write(struct netxen_adapter *adapter, __le32 status; __le32 mac_cfg0; - /* MII mgmt all goes through port 0 MAC interface, so it cannot be in reset */ + /* + * MII mgmt all goes through port 0 MAC interface, so it + * cannot be in reset + */ + if (netxen_nic_hw_read_wx(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(0), &mac_cfg0, 4)) return -EIO; @@ -382,14 +418,23 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) } } else { - /* We don't have link. Cable must be unconnected. */ - /* Enable phy interrupts so we take action when plugged in */ + /* + * We don't have link. Cable must be unconnected. + * Enable phy interrupts so we take action when + * plugged in. + */ + netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0 - (port), 0x80000000); + (port), + NETXEN_GB_MAC_SOFT_RESET); netxen_crb_writelit_adapter(adapter, NETXEN_NIU_GB_MAC_CONFIG_0 - (port), 0x0000f0025); + (port), + NETXEN_GB_MAC_RESET_PROT_BLK + | NETXEN_GB_MAC_ENABLE_TX_RX + | + NETXEN_GB_MAC_PAUSED_FRMS); if (netxen_niu_gbe_clear_phy_interrupts(adapter, port)) printk(KERN_ERR PFX "ERROR clearing PHY interrupts\n"); @@ -407,10 +452,34 @@ int netxen_niu_gbe_init_port(struct netxen_adapter *adapter, int port) return result; } +int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) +{ + long reg = 0, ret = 0; + + if (adapter->ahw.boardcfg.board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) { + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_XG1_CONFIG_0, 0x5); + /* XXX hack for Mez cards: both ports in promisc mode */ + netxen_nic_hw_read_wx(adapter, + NETXEN_NIU_XGE_CONFIG_1, ®, 4); + reg = (reg | 0x2000UL); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_XGE_CONFIG_1, reg); + reg = 0; + netxen_nic_hw_read_wx(adapter, + NETXEN_NIU_XG1_CONFIG_1, ®, 4); + reg = (reg | 0x2000UL); + netxen_crb_writelit_adapter(adapter, + NETXEN_NIU_XG1_CONFIG_1, reg); + } + + return ret; +} + /* * netxen_niu_gbe_handle_phy_interrupt - Handles GbE PHY interrupts * @param enable 0 means don't enable the port - * 1 means enable (or re-enable) the port + * 1 means enable (or re-enable) the port */ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter, int port, long enable) @@ -421,7 +490,10 @@ int netxen_niu_gbe_handle_phy_interrupt(struct netxen_adapter *adapter, printk(KERN_INFO PFX "NETXEN: Handling PHY interrupt on port %d" " (device enable = %d)\n", (int)port, (int)enable); - /* The read of the PHY INT status will clear the pending interrupt status */ + /* + * The read of the PHY INT status will clear the pending + * interrupt status + */ if (netxen_niu_gbe_phy_read(adapter, port, NETXEN_NIU_GB_MII_MGMT_ADDR_INT_STATUS, &int_src) != 0) @@ -540,20 +612,42 @@ int netxen_niu_macaddr_set(struct netxen_port *port, __le32 temp = 0; struct netxen_adapter *adapter = port->adapter; int phy = port->portnum; + unsigned char mac_addr[MAX_ADDR_LEN]; + int i; + + for (i = 0; i < 10; i++) { + memcpy(&temp, addr, 2); + temp <<= 16; + if (netxen_nic_hw_write_wx + (adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), &temp, 4)) + return -EIO; - memcpy(&temp, addr, 2); - temp <<= 16; - if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_1(phy), - &temp, 4)) - return -EIO; + temp = 0; - temp = 0; + memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); + if (netxen_nic_hw_write_wx + (adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), &temp, 4)) + return -2; - memcpy(&temp, ((u8 *) addr) + 2, sizeof(__le32)); - if (netxen_nic_hw_write_wx(adapter, NETXEN_NIU_GB_STATION_ADDR_0(phy), - &temp, 4)) - return -2; + netxen_niu_macaddr_get(adapter, phy, + (netxen_ethernet_macaddr_t *) mac_addr); + if (memcmp(mac_addr, addr, MAX_ADDR_LEN == 0)) + break; + } + if (i == 10) { + printk(KERN_ERR "%s: cannot set Mac addr for %s\n", + netxen_nic_driver_name, port->netdev->name); + printk(KERN_ERR "MAC address set: " + "%02x:%02x:%02x:%02x:%02x:%02x.\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); + + printk(KERN_ERR "MAC address get: " + "%02x:%02x:%02x:%02x:%02x:%02x.\n", + mac_addr[0], + mac_addr[1], + mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + } return 0; } diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 863645ed1cd3..8181d436783f 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -6,12 +6,12 @@ * 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, @@ -58,6 +58,9 @@ #define CRB_CMD_PRODUCER_OFFSET NETXEN_NIC_REG(0x08) #define CRB_CMD_CONSUMER_OFFSET NETXEN_NIC_REG(0x0c) +#define CRB_PAUSE_ADDR_LO NETXEN_NIC_REG(0x10) +#define CRB_PAUSE_ADDR_HI NETXEN_NIC_REG(0x14) + /* address of command descriptors in the host memory */ #define CRB_HOST_CMD_ADDR_HI NETXEN_NIC_REG(0x30) #define CRB_HOST_CMD_ADDR_LO NETXEN_NIC_REG(0x34) @@ -82,10 +85,18 @@ #define CRB_TX_PKT_TIMER NETXEN_NIC_REG(0x94) #define CRB_RX_PKT_CNT NETXEN_NIC_REG(0x98) #define CRB_RX_TMR_CNT NETXEN_NIC_REG(0x9c) +#define CRB_INT_THRESH NETXEN_NIC_REG(0xa4) /* Register for communicating XG link status */ #define CRB_XG_STATE NETXEN_NIC_REG(0xa0) +/* Register for communicating card temperature */ +/* Upper 16 bits are temperature value. Lower 16 bits are the state */ +#define CRB_TEMP_STATE NETXEN_NIC_REG(0xa8) +#define nx_get_temp_val(x) ((x) >> 16) +#define nx_get_temp_state(x) ((x) & 0xffff) +#define nx_encode_temp(val, state) (((val) << 16) | (state)) + /* Debug registers for controlling NIC pkt gen agent */ #define CRB_AGENT_GO NETXEN_NIC_REG(0xb0) #define CRB_AGENT_TX_SIZE NETXEN_NIC_REG(0xb4) @@ -192,4 +203,13 @@ struct netxen_recv_crb recv_crb_registers[] = { extern struct netxen_recv_crb recv_crb_registers[]; #endif /* DEFINE_GLOBAL_RECEIVE_CRB */ +/* + * Temperature control. + */ +enum { + NX_TEMP_NORMAL = 0x1, /* Normal operating range */ + NX_TEMP_WARN, /* Sound alert, temperature getting high */ + NX_TEMP_PANIC /* Fatal error, hardware has shut down. */ +}; + #endif /* __NIC_PHAN_REG_H_ */ -- cgit v1.2.3 From bca79eb7e7a1855947864952fcd878a5ae7b5c92 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 29 Nov 2006 13:15:17 -0800 Subject: [PATCH] sundance: use NULL for pointer Use NULL instead of 0 for pointers (cures sparse warnings). drivers/net/sundance.c:1106:16: warning: Using plain integer as NULL pointer drivers/net/sundance.c:1652:16: warning: Using plain integer as NULL pointer Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/net/sundance.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index 02679e688c4c..c06ecc8002b9 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -1102,7 +1102,7 @@ reset_tx (struct net_device *dev) np->cur_tx = np->dirty_tx = 0; np->cur_task = 0; - np->last_tx = 0; + np->last_tx = NULL; iowrite8(127, ioaddr + TxDMAPollPeriod); iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); @@ -1648,7 +1648,7 @@ static int netdev_close(struct net_device *dev) np->cur_tx = 0; np->dirty_tx = 0; np->cur_task = 0; - np->last_tx = 0; + np->last_tx = NULL; netif_stop_queue(dev); -- cgit v1.2.3 From a4f0c2ca8c475e00caa469b4574950852c376076 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Wed, 15 Nov 2006 12:29:35 -0600 Subject: [PATCH] Adapt ucc_geth driver to use new of_platform_device support Include of_platform header, and use new of_[un]register_platform_driver() fns. Signed-off-by: Kim Phillips Signed-off-by: Jeff Garzik --- drivers/net/ucc_geth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index b37888011067..1f05511fa390 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -30,7 +30,7 @@ #include #include -#include +#include #include #include #include @@ -4301,12 +4301,12 @@ static int __init ucc_geth_init(void) memcpy(&(ugeth_info[i]), &ugeth_primary_info, sizeof(ugeth_primary_info)); - return of_register_driver(&ucc_geth_driver); + return of_register_platform_driver(&ucc_geth_driver); } static void __exit ucc_geth_exit(void) { - of_unregister_driver(&ucc_geth_driver); + of_unregister_platform_driver(&ucc_geth_driver); } module_init(ucc_geth_init); -- cgit v1.2.3 From 9300abd4c60d385683944b9bc5cbf2c7c2cc6e78 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 11:21:33 -0800 Subject: [PATCH] chelsio: remove leftover code The chelsio network driver has some extra ifdef's that got in because the driver was originally based on code that worked on 2.4 as well as 2.6. This patch removes the dead code. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 35 ----------------------------------- 1 file changed, 35 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index ad7ff9641a7e..a65660b0ea63 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -56,34 +56,6 @@ #include "sge.h" #include "espi.h" -#ifdef work_struct -#include -#define INIT_WORK INIT_TQUEUE -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks - -static inline void schedule_mac_stats_update(struct adapter *ap, int secs) -{ - mod_timer(&ap->stats_update_timer, jiffies + secs * HZ); -} - -static inline void cancel_mac_stats_update(struct adapter *ap) -{ - del_timer_sync(&ap->stats_update_timer); - flush_scheduled_tasks(); -} - -/* - * Stats update timer for 2.4. It schedules a task to do the actual update as - * we need to access MAC statistics in process context. - */ -static void mac_stats_timer(unsigned long data) -{ - struct adapter *ap = (struct adapter *)data; - - schedule_task(&ap->stats_update_task); -} -#else #include static inline void schedule_mac_stats_update(struct adapter *ap, int secs) @@ -95,7 +67,6 @@ static inline void cancel_mac_stats_update(struct adapter *ap) { cancel_delayed_work(&ap->stats_update_task); } -#endif #define MAX_CMDQ_ENTRIES 16384 #define MAX_CMDQ1_ENTRIES 1024 @@ -1090,12 +1061,6 @@ static int __devinit init_one(struct pci_dev *pdev, ext_intr_task, adapter); INIT_WORK(&adapter->stats_update_task, mac_stats_task, adapter); -#ifdef work_struct - init_timer(&adapter->stats_update_timer); - adapter->stats_update_timer.function = mac_stats_timer; - adapter->stats_update_timer.data = - (unsigned long)adapter; -#endif pci_set_drvdata(pdev, netdev); } -- cgit v1.2.3 From 205781510d2a55a5c231f6e51df5b6c4aa765143 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 11:21:22 -0800 Subject: [PATCH] chelsio: whitespace cleanup Whitespace cleanups. Replace leading spaces with tabs and fix indentation Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 202 ++++++++++++++++++++++---------------------- 1 file changed, 101 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index a65660b0ea63..3309bfc774e0 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -120,7 +120,7 @@ static void t1_set_rxmode(struct net_device *dev) static void link_report(struct port_info *p) { if (!netif_carrier_ok(p->dev)) - printk(KERN_INFO "%s: link down\n", p->dev->name); + printk(KERN_INFO "%s: link down\n", p->dev->name); else { const char *s = "10Mbps"; @@ -130,7 +130,7 @@ static void link_report(struct port_info *p) case SPEED_100: s = "100Mbps"; break; } - printk(KERN_INFO "%s: link up, %s, %s-duplex\n", + printk(KERN_INFO "%s: link up, %s, %s-duplex\n", p->dev->name, s, p->link_config.duplex == DUPLEX_FULL ? "full" : "half"); } @@ -261,7 +261,7 @@ static struct net_device_stats *t1_get_stats(struct net_device *dev) /* Do a full update of the MAC stats */ pstats = p->mac->ops->statistics_update(p->mac, - MAC_STATS_UPDATE_FULL); + MAC_STATS_UPDATE_FULL); ns->tx_packets = pstats->TxUnicastFramesOK + pstats->TxMulticastFramesOK + pstats->TxBroadcastFramesOK; @@ -315,39 +315,39 @@ static void set_msglevel(struct net_device *dev, u32 val) } static char stats_strings[][ETH_GSTRING_LEN] = { - "TxOctetsOK", - "TxOctetsBad", - "TxUnicastFramesOK", - "TxMulticastFramesOK", - "TxBroadcastFramesOK", - "TxPauseFrames", - "TxFramesWithDeferredXmissions", - "TxLateCollisions", - "TxTotalCollisions", - "TxFramesAbortedDueToXSCollisions", - "TxUnderrun", - "TxLengthErrors", - "TxInternalMACXmitError", - "TxFramesWithExcessiveDeferral", - "TxFCSErrors", - - "RxOctetsOK", - "RxOctetsBad", - "RxUnicastFramesOK", - "RxMulticastFramesOK", - "RxBroadcastFramesOK", - "RxPauseFrames", - "RxFCSErrors", - "RxAlignErrors", - "RxSymbolErrors", - "RxDataErrors", - "RxSequenceErrors", - "RxRuntErrors", - "RxJabberErrors", - "RxInternalMACRcvError", - "RxInRangeLengthErrors", - "RxOutOfRangeLengthField", - "RxFrameTooLongErrors", + "TxOctetsOK", + "TxOctetsBad", + "TxUnicastFramesOK", + "TxMulticastFramesOK", + "TxBroadcastFramesOK", + "TxPauseFrames", + "TxFramesWithDeferredXmissions", + "TxLateCollisions", + "TxTotalCollisions", + "TxFramesAbortedDueToXSCollisions", + "TxUnderrun", + "TxLengthErrors", + "TxInternalMACXmitError", + "TxFramesWithExcessiveDeferral", + "TxFCSErrors", + + "RxOctetsOK", + "RxOctetsBad", + "RxUnicastFramesOK", + "RxMulticastFramesOK", + "RxBroadcastFramesOK", + "RxPauseFrames", + "RxFCSErrors", + "RxAlignErrors", + "RxSymbolErrors", + "RxDataErrors", + "RxSequenceErrors", + "RxRuntErrors", + "RxJabberErrors", + "RxInternalMACRcvError", + "RxInRangeLengthErrors", + "RxOutOfRangeLengthField", + "RxFrameTooLongErrors", "TSO", "VLANextractions", @@ -367,7 +367,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "tx_reg_pkts", "tx_lso_pkts", "tx_do_cksum", - + "espi_DIP2ParityErr", "espi_DIP4Err", "espi_RxDrops", @@ -375,7 +375,7 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "espi_RxOvfl", "espi_ParityErr" }; - + #define T2_REGMAP_SIZE (3 * 1024) static int get_regs_len(struct net_device *dev) @@ -417,39 +417,39 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, ss = t1_sge_get_port_stats(adapter->sge, dev->if_port); t = t1_sge_get_intr_counts(adapter->sge); - *data++ = s->TxOctetsOK; - *data++ = s->TxOctetsBad; - *data++ = s->TxUnicastFramesOK; - *data++ = s->TxMulticastFramesOK; - *data++ = s->TxBroadcastFramesOK; - *data++ = s->TxPauseFrames; - *data++ = s->TxFramesWithDeferredXmissions; - *data++ = s->TxLateCollisions; - *data++ = s->TxTotalCollisions; - *data++ = s->TxFramesAbortedDueToXSCollisions; - *data++ = s->TxUnderrun; - *data++ = s->TxLengthErrors; - *data++ = s->TxInternalMACXmitError; - *data++ = s->TxFramesWithExcessiveDeferral; - *data++ = s->TxFCSErrors; - - *data++ = s->RxOctetsOK; - *data++ = s->RxOctetsBad; - *data++ = s->RxUnicastFramesOK; - *data++ = s->RxMulticastFramesOK; - *data++ = s->RxBroadcastFramesOK; - *data++ = s->RxPauseFrames; - *data++ = s->RxFCSErrors; - *data++ = s->RxAlignErrors; - *data++ = s->RxSymbolErrors; - *data++ = s->RxDataErrors; - *data++ = s->RxSequenceErrors; - *data++ = s->RxRuntErrors; - *data++ = s->RxJabberErrors; - *data++ = s->RxInternalMACRcvError; - *data++ = s->RxInRangeLengthErrors; - *data++ = s->RxOutOfRangeLengthField; - *data++ = s->RxFrameTooLongErrors; + *data++ = s->TxOctetsOK; + *data++ = s->TxOctetsBad; + *data++ = s->TxUnicastFramesOK; + *data++ = s->TxMulticastFramesOK; + *data++ = s->TxBroadcastFramesOK; + *data++ = s->TxPauseFrames; + *data++ = s->TxFramesWithDeferredXmissions; + *data++ = s->TxLateCollisions; + *data++ = s->TxTotalCollisions; + *data++ = s->TxFramesAbortedDueToXSCollisions; + *data++ = s->TxUnderrun; + *data++ = s->TxLengthErrors; + *data++ = s->TxInternalMACXmitError; + *data++ = s->TxFramesWithExcessiveDeferral; + *data++ = s->TxFCSErrors; + + *data++ = s->RxOctetsOK; + *data++ = s->RxOctetsBad; + *data++ = s->RxUnicastFramesOK; + *data++ = s->RxMulticastFramesOK; + *data++ = s->RxBroadcastFramesOK; + *data++ = s->RxPauseFrames; + *data++ = s->RxFCSErrors; + *data++ = s->RxAlignErrors; + *data++ = s->RxSymbolErrors; + *data++ = s->RxDataErrors; + *data++ = s->RxSequenceErrors; + *data++ = s->RxRuntErrors; + *data++ = s->RxJabberErrors; + *data++ = s->RxInternalMACRcvError; + *data++ = s->RxInRangeLengthErrors; + *data++ = s->RxOutOfRangeLengthField; + *data++ = s->RxFrameTooLongErrors; *data++ = ss->tso; *data++ = ss->vlan_xtract; @@ -510,12 +510,12 @@ static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) cmd->duplex = -1; } - cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; - cmd->phy_address = p->phy->addr; - cmd->transceiver = XCVR_EXTERNAL; - cmd->autoneg = p->link_config.autoneg; - cmd->maxtxpkt = 0; - cmd->maxrxpkt = 0; + cmd->port = (cmd->supported & SUPPORTED_TP) ? PORT_TP : PORT_FIBRE; + cmd->phy_address = p->phy->addr; + cmd->transceiver = XCVR_EXTERNAL; + cmd->autoneg = p->link_config.autoneg; + cmd->maxtxpkt = 0; + cmd->maxrxpkt = 0; return 0; } @@ -686,7 +686,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e) return -EINVAL; if (adapter->flags & FULL_INIT_DONE) - return -EBUSY; + return -EBUSY; adapter->params.sge.freelQ_size[!jumbo_fl] = e->rx_pending; adapter->params.sge.freelQ_size[jumbo_fl] = e->rx_jumbo_pending; @@ -793,34 +793,34 @@ static void cxgb_proc_cleanup(struct adapter *adapter, static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { - struct adapter *adapter = dev->priv; - struct mii_ioctl_data *data = if_mii(req); + struct adapter *adapter = dev->priv; + struct mii_ioctl_data *data = if_mii(req); switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->port[dev->if_port].phy->addr; - /* FALLTHRU */ - case SIOCGMIIREG: { + case SIOCGMIIPHY: + data->phy_id = adapter->port[dev->if_port].phy->addr; + /* FALLTHRU */ + case SIOCGMIIREG: { struct cphy *phy = adapter->port[dev->if_port].phy; u32 val; if (!phy->mdio_read) - return -EOPNOTSUPP; + return -EOPNOTSUPP; phy->mdio_read(adapter, data->phy_id, 0, data->reg_num & 0x1f, &val); - data->val_out = val; - break; + data->val_out = val; + break; } - case SIOCSMIIREG: { + case SIOCSMIIREG: { struct cphy *phy = adapter->port[dev->if_port].phy; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; + if (!capable(CAP_NET_ADMIN)) + return -EPERM; if (!phy->mdio_write) - return -EOPNOTSUPP; + return -EOPNOTSUPP; phy->mdio_write(adapter, data->phy_id, 0, data->reg_num & 0x1f, data->val_in); - break; + break; } default: @@ -836,9 +836,9 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu) struct cmac *mac = adapter->port[dev->if_port].mac; if (!mac->ops->set_mtu) - return -EOPNOTSUPP; + return -EOPNOTSUPP; if (new_mtu < 68) - return -EINVAL; + return -EINVAL; if ((ret = mac->ops->set_mtu(mac, new_mtu))) return ret; dev->mtu = new_mtu; @@ -889,7 +889,7 @@ static void t1_netpoll(struct net_device *dev) struct adapter *adapter = dev->priv; local_irq_save(flags); - t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter); + t1_select_intr_handler(adapter)(adapter->pdev->irq, adapter); local_irq_restore(flags); } #endif @@ -933,7 +933,7 @@ static void ext_intr_task(void *data) adapter->slow_intr_mask |= F_PL_INTR_EXT; writel(F_PL_INTR_EXT, adapter->regs + A_PL_CAUSE); writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, - adapter->regs + A_PL_ENABLE); + adapter->regs + A_PL_ENABLE); spin_unlock_irq(&adapter->async_lock); } @@ -949,7 +949,7 @@ void t1_elmer0_ext_intr(struct adapter *adapter) */ adapter->slow_intr_mask &= ~F_PL_INTR_EXT; writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA, - adapter->regs + A_PL_ENABLE); + adapter->regs + A_PL_ENABLE); schedule_work(&adapter->ext_intr_handler_task); } @@ -982,7 +982,7 @@ static int __devinit init_one(struct pci_dev *pdev, err = pci_enable_device(pdev); if (err) - return err; + return err; if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) { CH_ERR("%s: cannot find PCI device memory base address\n", @@ -1014,7 +1014,7 @@ static int __devinit init_one(struct pci_dev *pdev, pci_set_master(pdev); - mmio_start = pci_resource_start(pdev, 0); + mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); bi = t1_get_board_info(ent->driver_data); @@ -1107,7 +1107,7 @@ static int __devinit init_one(struct pci_dev *pdev, #endif netdev->weight = 64; - SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); + SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops); } if (t1_init_sw_modules(adapter, bi) < 0) { @@ -1134,7 +1134,7 @@ static int __devinit init_one(struct pci_dev *pdev, if (!adapter->registered_device_map) adapter->name = adapter->port[i].dev->name; - __set_bit(i, &adapter->registered_device_map); + __set_bit(i, &adapter->registered_device_map); } } if (!adapter->registered_device_map) { -- cgit v1.2.3 From bac7e8746ce562556b7bd750c7652154483b15e2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 11:23:41 -0800 Subject: [PATCH] chelsio: procectomy Complete removal of proc stuff from chelsio. The orignal driver had a debug proc interface, but not all the code got removed. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 3309bfc774e0..37de99b65c14 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include @@ -780,17 +779,6 @@ static const struct ethtool_ops t1_ethtool_ops = { .set_tso = set_tso, }; -static void cxgb_proc_cleanup(struct adapter *adapter, - struct proc_dir_entry *dir) -{ - const char *name; - name = adapter->name; - remove_proc_entry(name, dir); -} -//#define chtoe_setup_toedev(adapter) NULL -#define update_mtu_tab(adapter) -#define write_smt_entry(adapter, idx) - static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { struct adapter *adapter = dev->priv; @@ -1156,7 +1144,6 @@ static int __devinit init_one(struct pci_dev *pdev, if (adapter->regs) iounmap(adapter->regs); for (i = bi->port_number - 1; i >= 0; --i) if (adapter->port[i].dev) { - cxgb_proc_cleanup(adapter, proc_root_driver); kfree(adapter->port[i].dev); } } @@ -1189,7 +1176,6 @@ static void __devexit remove_one(struct pci_dev *pdev) iounmap(adapter->regs); while (--i >= 0) if (adapter->port[i].dev) { - cxgb_proc_cleanup(adapter, proc_root_driver); kfree(adapter->port[i].dev); } pci_release_regions(pdev); -- cgit v1.2.3 From e487647abbe66390b99f9a32ede4688b255282dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 11:25:23 -0800 Subject: [PATCH] chelsio: free_netdev Network devices need to be free'd with free_netdev() not kfree() otherwise the kernel will panic if an application has /sys/class/net/ethX/value open and reads it. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 37de99b65c14..37037e5890e1 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -1141,11 +1141,11 @@ static int __devinit init_one(struct pci_dev *pdev, t1_free_sw_modules(adapter); out_free_dev: if (adapter) { - if (adapter->regs) iounmap(adapter->regs); + if (adapter->regs) + iounmap(adapter->regs); for (i = bi->port_number - 1; i >= 0; --i) - if (adapter->port[i].dev) { - kfree(adapter->port[i].dev); - } + if (adapter->port[i].dev) + free_netdev(adapter->port[i].dev); } pci_release_regions(pdev); out_disable_pdev: @@ -1175,9 +1175,9 @@ static void __devexit remove_one(struct pci_dev *pdev) t1_free_sw_modules(adapter); iounmap(adapter->regs); while (--i >= 0) - if (adapter->port[i].dev) { - kfree(adapter->port[i].dev); - } + if (adapter->port[i].dev) + free_netdev(adapter->port[i].dev); + pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); -- cgit v1.2.3 From 86c27d275507d81da179b571f35d34df61f7c6d3 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 17:00:34 -0800 Subject: [PATCH] chelsio: use __netif_rx_schedule_prep The chelsio driver can use __netif_rx_schedule_prep instead of it's own test_and_set inline. Applies after the previous 4 patches. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/sge.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 9799c12380fc..11c70b59a1a3 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -929,18 +929,6 @@ static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q) # define __netif_rx_complete(dev) netif_rx_complete(dev) #endif -/* - * We cannot use the standard netif_rx_schedule_prep() because we have multiple - * ports plus the TOE all multiplexing onto a single response queue, therefore - * accepting new responses cannot depend on the state of any particular port. - * So define our own equivalent that omits the netif_running() test. - */ -static inline int napi_schedule_prep(struct net_device *dev) -{ - return !test_and_set_bit(__LINK_STATE_RX_SCHED, &dev->state); -} - - /** * sge_rx - process an ingress ethernet packet * @sge: the sge structure @@ -1241,10 +1229,10 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data) if (e->GenerationBit == q->genbit) { if (e->DataValid || process_pure_responses(adapter, e)) { - if (likely(napi_schedule_prep(sge->netdev))) + if (likely(__netif_rx_schedule_prep(sge->netdev))) __netif_rx_schedule(sge->netdev); - else - printk(KERN_CRIT + else if (net_ratelimit()) + printk(KERN_INFO "NAPI schedule failure!\n"); } else writel(q->cidx, adapter->regs + A_SG_SLEEPING); -- cgit v1.2.3 From cbee9f9115da7eac5dc44a450f2dab343236cb2c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 17 Nov 2006 17:01:52 -0800 Subject: [PATCH] chelsio: use kzalloc Use kzalloc() in chelsio driver. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/sge.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 11c70b59a1a3..9fb77c6d6c6b 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -335,10 +335,9 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p) goto err_no_mem; memset(q->entries, 0, size); size = sizeof(struct freelQ_ce) * q->size; - q->centries = kmalloc(size, GFP_KERNEL); + q->centries = kzalloc(size, GFP_KERNEL); if (!q->centries) goto err_no_mem; - memset(q->centries, 0, size); } /* @@ -463,10 +462,9 @@ static int alloc_tx_resources(struct sge *sge, struct sge_params *p) goto err_no_mem; memset(q->entries, 0, size); size = sizeof(struct cmdQ_ce) * q->size; - q->centries = kmalloc(size, GFP_KERNEL); + q->centries = kzalloc(size, GFP_KERNEL); if (!q->centries) goto err_no_mem; - memset(q->centries, 0, size); } /* @@ -1635,11 +1633,10 @@ static void espibug_workaround(void *data) struct sge * __devinit t1_sge_create(struct adapter *adapter, struct sge_params *p) { - struct sge *sge = kmalloc(sizeof(*sge), GFP_KERNEL); + struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL); if (!sge) return NULL; - memset(sge, 0, sizeof(*sge)); sge->adapter = adapter; sge->netdev = adapter->port[0].dev; -- cgit v1.2.3 From 5ac366152a44da60c22c08df619012b1e3bc1adb Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 16 Nov 2006 21:39:11 -0800 Subject: [PATCH] netxen: uses PCI drivers/built-in.o: In function `netxen_nic_remove': netxen_nic_main.c:(.text+0x31b4d): undefined reference to `pci_disable_msi' netxen_nic_main.c:(.text+0x31b8e): undefined reference to `pci_release_regions' drivers/built-in.o: In function `netxen_init_module': netxen_nic_main.c:(.init.text+0x3f17): undefined reference to `pci_module_init' make: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Randy Dunlap Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 10ac1c763f33..460517a19a63 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2468,6 +2468,7 @@ config MYRI10GE config NETXEN_NIC tristate "NetXen Multi port (1/10) Gigabit Ethernet NIC" + depends on PCI help This enables the support for NetXen's Gigabit Ethernet card. -- cgit v1.2.3 From 7628b0a8c01a02966d2228bdf741ddedb128e8f8 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Thu, 30 Nov 2006 07:11:24 -0500 Subject: drivers/net/tulip/dmfe: support basic carrier detection Signed-off-by: Jeff Garzik --- drivers/net/tulip/dmfe.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c index 4dd8a0bae860..7f59a3d4fda2 100644 --- a/drivers/net/tulip/dmfe.c +++ b/drivers/net/tulip/dmfe.c @@ -187,7 +187,7 @@ struct rx_desc { struct dmfe_board_info { u32 chip_id; /* Chip vendor/Device ID */ u32 chip_revision; /* Chip revision */ - struct DEVICE *next_dev; /* next device */ + struct DEVICE *dev; /* net device */ struct pci_dev *pdev; /* PCI device */ spinlock_t lock; @@ -399,6 +399,8 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, /* Init system & device */ db = netdev_priv(dev); + db->dev = dev; + /* Allocate Tx/Rx descriptor memory */ db->desc_pool_ptr = pci_alloc_consistent(pdev, sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, &db->desc_pool_dma_ptr); db->buf_pool_ptr = pci_alloc_consistent(pdev, TX_BUF_ALLOC * TX_DESC_CNT + 4, &db->buf_pool_dma_ptr); @@ -426,6 +428,7 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev, dev->poll_controller = &poll_dmfe; #endif dev->ethtool_ops = &netdev_ethtool_ops; + netif_carrier_off(db->dev); spin_lock_init(&db->lock); pci_read_config_dword(pdev, 0x50, &pci_pmr); @@ -1050,6 +1053,7 @@ static void netdev_get_drvinfo(struct net_device *dev, static const struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo, + .get_link = ethtool_op_get_link, }; /* @@ -1144,6 +1148,7 @@ static void dmfe_timer(unsigned long data) /* Link Failed */ DMFE_DBUG(0, "Link Failed", tmp_cr12); db->link_failed = 1; + netif_carrier_off(db->dev); /* For Force 10/100M Half/Full mode: Enable Auto-Nego mode */ /* AUTO or force 1M Homerun/Longrun don't need */ @@ -1166,6 +1171,8 @@ static void dmfe_timer(unsigned long data) if ( (db->media_mode & DMFE_AUTO) && dmfe_sense_speed(db) ) db->link_failed = 1; + else + netif_carrier_on(db->dev); dmfe_process_mode(db); /* SHOW_MEDIA_TYPE(db->op_mode); */ } -- cgit v1.2.3 From 758140900a82e3ed3bb2be1d4705dd352fe44825 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 11:41:08 -0800 Subject: [PATCH] skge: don't clear MC state on link down I would rather fix Andy's problem by not clearing multicast information on link down. Also, add code to restore multicast state after ethtool phy reset. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index b2949035f66a..010fc6541122 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2154,8 +2154,6 @@ static void yukon_link_down(struct skge_port *skge) int port = skge->port; u16 ctrl; - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0); - ctrl = gma_read16(hw, port, GM_GP_CTRL); ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); gma_write16(hw, port, GM_GP_CTRL, ctrl); @@ -2167,7 +2165,6 @@ static void yukon_link_down(struct skge_port *skge) gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl); } - yukon_reset(hw, port); skge_link_down(skge); yukon_init(hw, port); @@ -2268,6 +2265,8 @@ static void skge_phy_reset(struct skge_port *skge) yukon_init(hw, port); } mutex_unlock(&hw->phy_mutex); + + dev->set_multicast_list(dev); } /* Basic MII support */ -- cgit v1.2.3 From 5df791117afedf7fdc67dc0842dab4859e3edf69 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 14:29:33 -0800 Subject: [PATCH] sky2: receive error handling fix If sky2 detects out of memory, or gets a bad frame, it reuses the same receive buffer, but forgets to poke the hardware. This could lead to the receiver getting stuck if there were lots of errors. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 16616f5440d0..0c8a5354f99c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2065,7 +2065,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) case OP_RXSTAT: skb = sky2_receive(dev, length, status); if (!skb) - break; + goto force_update; skb->protocol = eth_type_trans(skb, dev); dev->last_rx = jiffies; @@ -2081,8 +2081,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do) /* Update receiver after 16 frames */ if (++buf_write[le->link] == RX_BUF_WRITE) { - sky2_put_idx(hw, rxqaddr[le->link], - sky2->rx_put); +force_update: + sky2_put_idx(hw, rxqaddr[le->link], sky2->rx_put); buf_write[le->link] = 0; } -- cgit v1.2.3 From 508f89e75ab26506fcdbb1b6f7166029e4c56855 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 14:29:34 -0800 Subject: [PATCH] sky2: add Dlink 560SX id Add new PCI ID for DLink 560SX. This from the latest SysKonnect vendor driver (version 8.41). Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0c8a5354f99c..79d62ae8d7cd 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -104,6 +104,7 @@ static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4001) }, /* DGE-550SX */ + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4B02) }, /* DGE-560SX */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, -- cgit v1.2.3 From 8df9a87604e38529898ce35c610792c03c8713a2 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 14:29:35 -0800 Subject: [PATCH] sky2: fixes for Yukon EC_U chip revisions Update workarounds for 88E803X based on the latest SysKonnect vendor driver version (8.41). Tested on EC_U rev A1, only. These up the receive performance. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 13 ++++++------- drivers/net/sky2.h | 9 +++++++-- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 79d62ae8d7cd..71722f53f2b4 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -677,17 +677,15 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) /* Flush Rx MAC FIFO on any flow control or error */ sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); - /* Set threshold to 0xa (64 bytes) - * ASF disabled so no need to do WA dev #4.30 - */ - sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); + /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ + sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); /* Configure Tx MAC FIFO */ sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); if (hw->chip_id == CHIP_ID_YUKON_EC_U) { - sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 512/8); + sky2_write8(hw, SK_REG(port, RX_GMF_LP_THR), 768/8); sky2_write8(hw, SK_REG(port, RX_GMF_UP_THR), 1024/8); if (hw->dev[port]->mtu > ETH_DATA_LEN) { /* set Tx GMAC FIFO Almost Empty Threshold */ @@ -1061,7 +1059,8 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2->rx_put = sky2->rx_next = 0; sky2_qset(hw, rxq); - if (hw->chip_id == CHIP_ID_YUKON_EC_U && hw->chip_rev >= 2) { + if (hw->chip_id == CHIP_ID_YUKON_EC_U && + (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) { /* MAC Rx RAM Read is controlled by hardware */ sky2_write32(hw, Q_ADDR(rxq, Q_F), F_M_RX_RAM_DIS); } @@ -1510,7 +1509,7 @@ static int sky2_down(struct net_device *dev) /* WA for dev. #4.209 */ if (hw->chip_id == CHIP_ID_YUKON_EC_U - && hw->chip_rev == CHIP_REV_YU_EC_U_A1) + && (hw->chip_rev == CHIP_REV_YU_EC_U_A1 || hw->chip_rev == CHIP_REV_YU_EC_U_B0)) sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), sky2->speed != SPEED_1000 ? TX_STFW_ENA : TX_STFW_DIS); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 6d2a23f66c9a..c551ec32e63d 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -383,8 +383,13 @@ enum { CHIP_REV_YU_EC_A2 = 1, /* Chip Rev. for Yukon-EC A2 */ CHIP_REV_YU_EC_A3 = 2, /* Chip Rev. for Yukon-EC A3 */ - CHIP_REV_YU_EC_U_A0 = 0, - CHIP_REV_YU_EC_U_A1 = 1, + CHIP_REV_YU_EC_U_A0 = 1, + CHIP_REV_YU_EC_U_A1 = 2, + CHIP_REV_YU_EC_U_B0 = 3, + + CHIP_REV_YU_FE_A1 = 1, + CHIP_REV_YU_FE_A2 = 2, + }; /* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */ -- cgit v1.2.3 From 794b2bd20f620892616b09466186ff27101d9e5b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 14:29:36 -0800 Subject: [PATCH] sky2: kfree_skb_any needed It is possible for the sky2 driver NAPI poll routine to be called with IRQ's disabled if netpoll is trying to make space in the tx queue. This is an obscure path, but if it happens, the kfree_skb needs to happen via softirq. Calling kfree_skb with IRQ's disabled is a not allowed. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 71722f53f2b4..b95b9b7cce00 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1453,7 +1453,7 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done) if (unlikely(netif_msg_tx_done(sky2))) printk(KERN_DEBUG "%s: tx done %u\n", dev->name, idx); - dev_kfree_skb(re->skb); + dev_kfree_skb_any(re->skb); } le->opcode = 0; /* paranoia */ -- cgit v1.2.3 From b0a20ded562cfa60b0d45d269e416f541f2d5aaf Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 14:29:37 -0800 Subject: [PATCH] sky2: msi enhancements. If using Message Signaled Interrupts (MSI) then the IRQ will never be shared. Don't call pci_disable_msi() unless using MSI. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 17 ++++++++++------- drivers/net/sky2.h | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index b95b9b7cce00..0ef1848b9761 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -3311,7 +3311,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id) return IRQ_NONE; if (status & Y2_IS_IRQ_SW) { - hw->msi_detected = 1; + hw->msi = 1; wake_up(&hw->msi_wait); sky2_write8(hw, B0_CTST, CS_CL_SW_IRQ); } @@ -3330,7 +3330,7 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) sky2_write32(hw, B0_IMSK, Y2_IS_IRQ_SW); - err = request_irq(pdev->irq, sky2_test_intr, IRQF_SHARED, DRV_NAME, hw); + err = request_irq(pdev->irq, sky2_test_intr, 0, DRV_NAME, hw); if (err) { printk(KERN_ERR PFX "%s: cannot assign irq %d\n", pci_name(pdev), pdev->irq); @@ -3340,9 +3340,9 @@ static int __devinit sky2_test_msi(struct sky2_hw *hw) sky2_write8(hw, B0_CTST, CS_ST_SW_IRQ); sky2_read8(hw, B0_CTST); - wait_event_timeout(hw->msi_wait, hw->msi_detected, HZ/10); + wait_event_timeout(hw->msi_wait, hw->msi, HZ/10); - if (!hw->msi_detected) { + if (!hw->msi) { /* MSI test failed, go back to INTx mode */ printk(KERN_INFO PFX "%s: No interrupt generated using MSI, " "switching to INTx mode.\n", @@ -3475,7 +3475,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, goto err_out_free_netdev; } - err = request_irq(pdev->irq, sky2_intr, IRQF_SHARED, dev->name, hw); + err = request_irq(pdev->irq, sky2_intr, hw->msi ? 0 : IRQF_SHARED, + dev->name, hw); if (err) { printk(KERN_ERR PFX "%s: cannot assign irq %d\n", pci_name(pdev), pdev->irq); @@ -3505,7 +3506,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev, return 0; err_out_unregister: - pci_disable_msi(pdev); + if (hw->msi) + pci_disable_msi(pdev); unregister_netdev(dev); err_out_free_netdev: free_netdev(dev); @@ -3548,7 +3550,8 @@ static void __devexit sky2_remove(struct pci_dev *pdev) sky2_read8(hw, B0_CTST); free_irq(pdev->irq, hw); - pci_disable_msi(pdev); + if (hw->msi) + pci_disable_msi(pdev); pci_free_consistent(pdev, STATUS_LE_BYTES, hw->st_le, hw->st_dma); pci_release_regions(pdev); pci_disable_device(pdev); diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index c551ec32e63d..7760545edbf2 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1900,7 +1900,7 @@ struct sky2_hw { dma_addr_t st_dma; struct timer_list idle_timer; - int msi_detected; + int msi; wait_queue_head_t msi_wait; }; -- cgit v1.2.3 From 6b4bdde61bd1f8451801e5fb092cbe2d1050984e Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:10:50 -0800 Subject: [PATCH] amd8111e use standard CRC lib I noticed this driver (and several others) reinvent their own copy of the existing CRC library. Don't have the hardware, but tested by extracting code and comparing result. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/amd8111e.c | 27 +-------------------------- drivers/net/amd8111e.h | 4 ---- 2 files changed, 1 insertion(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c index ef65e5917c8f..18896f24d407 100644 --- a/drivers/net/amd8111e.c +++ b/drivers/net/amd8111e.c @@ -1490,32 +1490,7 @@ static void amd8111e_read_regs(struct amd8111e_priv *lp, u32 *buf) buf[12] = readl(mmio + STAT0); } -/* -amd8111e crc generator implementation is different from the kernel -ether_crc() function. -*/ -static int amd8111e_ether_crc(int len, char* mac_addr) -{ - int i,byte; - unsigned char octet; - u32 crc= INITCRC; - - for(byte=0; byte < len; byte++){ - octet = mac_addr[byte]; - for( i=0;i < 8; i++){ - /*If the next bit form the input stream is 1,subtract the divisor (CRC32) from the dividend(crc).*/ - if( (octet & 0x1) ^ (crc & 0x1) ){ - crc >>= 1; - crc ^= CRC32; - } - else - crc >>= 1; - octet >>= 1; - } - } - return crc; -} /* This function sets promiscuos mode, all-multi mode or the multicast address list to the device. @@ -1556,7 +1531,7 @@ static void amd8111e_set_multicast_list(struct net_device *dev) mc_filter[1] = mc_filter[0] = 0; for (i = 0, mc_ptr = dev->mc_list; mc_ptr && i < dev->mc_count; i++, mc_ptr = mc_ptr->next) { - bit_num = ( amd8111e_ether_crc(ETH_ALEN,mc_ptr->dmi_addr) >> 26 ) & 0x3f; + bit_num = (ether_crc_le(ETH_ALEN, mc_ptr->dmi_addr) >> 26) & 0x3f; mc_filter[bit_num >> 5] |= 1 << (bit_num & 31); } amd8111e_writeq(*(u64*)mc_filter,lp->mmio+ LADRF); diff --git a/drivers/net/amd8111e.h b/drivers/net/amd8111e.h index 7727d328f65e..2007510c4eb6 100644 --- a/drivers/net/amd8111e.h +++ b/drivers/net/amd8111e.h @@ -651,10 +651,6 @@ typedef enum { /* driver ioctl parameters */ #define AMD8111E_REG_DUMP_LEN 13*sizeof(u32) -/* crc generator constants */ -#define CRC32 0xedb88320 -#define INITCRC 0xFFFFFFFF - /* amd8111e desriptor format */ struct amd8111e_tx_dr{ -- cgit v1.2.3 From 11e5a202ca9e93ecb5ff314a6a345e0e4db77d97 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:13 -0800 Subject: [PATCH] chelsio: whitespace fixes Fix indentation and blank/tab issues. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 2 +- drivers/net/chelsio/espi.c | 2 +- drivers/net/chelsio/pm3393.c | 16 ++++++++-------- drivers/net/chelsio/subr.c | 12 ++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 37037e5890e1..1d78d5d4b1a7 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -729,7 +729,7 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) static int get_eeprom_len(struct net_device *dev) { - return EEPROM_SIZE; + return EEPROM_SIZE; } #define EEPROM_MAGIC(ap) \ diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c index 542e5e065c6f..40af47b795e6 100644 --- a/drivers/net/chelsio/espi.c +++ b/drivers/net/chelsio/espi.c @@ -192,7 +192,7 @@ int t1_espi_intr_handler(struct peespi *espi) const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi) { - return &espi->intr_cnt; + return &espi->intr_cnt; } static void espi_setup_for_pm3393(adapter_t *adapter) diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 04a1404fc65e..b442b585b4b1 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -46,17 +46,17 @@ /* 802.3ae 10Gb/s MDIO Manageable Device(MMD) */ enum { - MMD_RESERVED, - MMD_PMAPMD, - MMD_WIS, - MMD_PCS, - MMD_PHY_XGXS, /* XGMII Extender Sublayer */ - MMD_DTE_XGXS, + MMD_RESERVED, + MMD_PMAPMD, + MMD_WIS, + MMD_PCS, + MMD_PHY_XGXS, /* XGMII Extender Sublayer */ + MMD_DTE_XGXS, }; enum { - PHY_XGXS_CTRL_1, - PHY_XGXS_STATUS_1 + PHY_XGXS_CTRL_1, + PHY_XGXS_STATUS_1 }; #define OFFSET(REG_ADDR) (REG_ADDR << 2) diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index 12e4e96dba2d..e4473ec43d26 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -166,11 +166,11 @@ static int t1_pci_intr_handler(adapter_t *adapter) { u32 pcix_cause; - pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause); + pci_read_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, &pcix_cause); if (pcix_cause) { pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, - pcix_cause); + pcix_cause); t1_fatal_err(adapter); /* PCI errors are fatal */ } return 0; @@ -420,9 +420,9 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) */ int elmer0_ext_intr_handler(adapter_t *adapter) { - struct cphy *phy; + struct cphy *phy; int phy_cause; - u32 cause; + u32 cause; t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); @@ -515,7 +515,7 @@ void t1_interrupts_clear(adapter_t* adapter) } /* Enable interrupts for external devices. */ - pl_intr = readl(adapter->regs + A_PL_CAUSE); + pl_intr = readl(adapter->regs + A_PL_CAUSE); writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX, adapter->regs + A_PL_CAUSE); @@ -643,7 +643,7 @@ static int board_init(adapter_t *adapter, const struct board_info *bi) case CHBT_BOARD_N110: case CHBT_BOARD_N210: writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); break; } return 0; -- cgit v1.2.3 From 1270266cf94c0de5bd1121f15aff9af8556dee84 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:14 -0800 Subject: [PATCH] chelsio: use kzalloc Use kzalloc in several places. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/mv88x201x.c | 4 ++-- drivers/net/chelsio/pm3393.c | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c index db5034282782..bf7d8538885d 100644 --- a/drivers/net/chelsio/mv88x201x.c +++ b/drivers/net/chelsio/mv88x201x.c @@ -205,11 +205,11 @@ static struct cphy *mv88x201x_phy_create(adapter_t *adapter, int phy_addr, struct mdio_ops *mdio_ops) { u32 val; - struct cphy *cphy = kmalloc(sizeof(*cphy), GFP_KERNEL); + struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); if (!cphy) return NULL; - memset(cphy, 0, sizeof(*cphy)); + cphy_init(cphy, adapter, phy_addr, &mv88x201x_ops, mdio_ops); /* Commands the PHY to enable XFP's clock. */ diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index b442b585b4b1..50983f9ce4bc 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -631,10 +631,9 @@ static struct cmac *pm3393_mac_create(adapter_t *adapter, int index) { struct cmac *cmac; - cmac = kmalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL); + cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL); if (!cmac) return NULL; - memset(cmac, 0, sizeof(*cmac)); cmac->ops = &pm3393_ops; cmac->instance = (cmac_instance *) (cmac + 1); -- cgit v1.2.3 From 415294ecbb32ddbd0a7a2b7bae0b60fedfa09cc4 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:15 -0800 Subject: [PATCH] chelsio: remove unused mutex This mutex is unused in current (non TOE) code. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/common.h | 1 - drivers/net/chelsio/cxgb2.c | 1 - 2 files changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 5d9dd14427c5..efe1f6685285 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -212,7 +212,6 @@ struct adapter { struct work_struct stats_update_task; struct timer_list stats_update_timer; - struct semaphore mib_mutex; spinlock_t tpi_lock; spinlock_t work_lock; /* guards async operations */ diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 1d78d5d4b1a7..42ad9cfd670a 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -1040,7 +1040,6 @@ static int __devinit init_one(struct pci_dev *pdev, adapter->msg_enable = dflt_msg_enable; adapter->mmio_len = mmio_len; - init_MUTEX(&adapter->mib_mutex); spin_lock_init(&adapter->tpi_lock); spin_lock_init(&adapter->work_lock); spin_lock_init(&adapter->async_lock); -- cgit v1.2.3 From f1d3d38af75789f1b82969b83b69cab540609789 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:16 -0800 Subject: [PATCH] chelsio: add support for other 10G boards Add support for other versions of the 10G Chelsio boards. This is basically a port of the vendor driver with the TOE features removed. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 6 +- drivers/net/chelsio/Makefile | 7 +- drivers/net/chelsio/common.h | 101 +- drivers/net/chelsio/cphy.h | 24 +- drivers/net/chelsio/cpl5_cmd.h | 510 ++++++++- drivers/net/chelsio/cxgb2.c | 238 ++++- drivers/net/chelsio/elmer0.h | 7 + drivers/net/chelsio/espi.c | 203 ++-- drivers/net/chelsio/espi.h | 1 + drivers/net/chelsio/fpga_defs.h | 232 +++++ drivers/net/chelsio/gmac.h | 5 + drivers/net/chelsio/mv88e1xxx.h | 127 +++ drivers/net/chelsio/mv88x201x.c | 32 +- drivers/net/chelsio/my3126.c | 204 ++++ drivers/net/chelsio/pm3393.c | 24 +- drivers/net/chelsio/regs.h | 1718 ++++++++++++++++++++++++++++++- drivers/net/chelsio/sge.c | 770 +++++++++++--- drivers/net/chelsio/sge.h | 4 + drivers/net/chelsio/subr.c | 265 +++-- drivers/net/chelsio/suni1x10gexp_regs.h | 1430 +++++++++++++++++++++++++ drivers/net/chelsio/tp.c | 145 +++ drivers/net/chelsio/tp.h | 73 ++ drivers/net/chelsio/vsc7326_reg.h | 286 +++++ 23 files changed, 6041 insertions(+), 371 deletions(-) create mode 100644 drivers/net/chelsio/fpga_defs.h create mode 100644 drivers/net/chelsio/mv88e1xxx.h create mode 100644 drivers/net/chelsio/my3126.c create mode 100644 drivers/net/chelsio/tp.c create mode 100644 drivers/net/chelsio/tp.h create mode 100644 drivers/net/chelsio/vsc7326_reg.h (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 460517a19a63..2f10dd554e33 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2361,9 +2361,9 @@ config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" depends on PCI help - This driver supports Chelsio N110 and N210 models 10Gb Ethernet - cards. More information about adapter features and performance - tuning is in . + This driver supports Chelsio gigabit and 10-gigabit + Ethernet cards. More information about adapter features and + performance tuning is in . For general information about Chelsio and our products, visit our website at . diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile index 54c78d94f48b..6d87316e58cb 100644 --- a/drivers/net/chelsio/Makefile +++ b/drivers/net/chelsio/Makefile @@ -1,11 +1,10 @@ # -# Chelsio 10Gb NIC driver for Linux. +# Chelsio T1 driver # obj-$(CONFIG_CHELSIO_T1) += cxgb.o -EXTRA_CFLAGS += -Idrivers/net/chelsio $(DEBUG_FLAGS) +cxgb-objs := cxgb2.o espi.o tp.o pm3393.o sge.o subr.o \ + mv88x201x.o my3126.o $(cxgb-y) -cxgb-objs := cxgb2.o espi.o pm3393.o sge.o subr.o mv88x201x.o - diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index efe1f6685285..e4e59d2d410e 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -53,13 +54,30 @@ #define DRV_DESCRIPTION "Chelsio 10Gb Ethernet Driver" #define DRV_NAME "cxgb" -#define DRV_VERSION "2.1.1" +#define DRV_VERSION "2.2" #define PFX DRV_NAME ": " #define CH_ERR(fmt, ...) printk(KERN_ERR PFX fmt, ## __VA_ARGS__) #define CH_WARN(fmt, ...) printk(KERN_WARNING PFX fmt, ## __VA_ARGS__) #define CH_ALERT(fmt, ...) printk(KERN_ALERT PFX fmt, ## __VA_ARGS__) +/* + * More powerful macro that selectively prints messages based on msg_enable. + * For info and debugging messages. + */ +#define CH_MSG(adapter, level, category, fmt, ...) do { \ + if ((adapter)->msg_enable & NETIF_MSG_##category) \ + printk(KERN_##level PFX "%s: " fmt, (adapter)->name, \ + ## __VA_ARGS__); \ +} while (0) + +#ifdef DEBUG +# define CH_DBG(adapter, category, fmt, ...) \ + CH_MSG(adapter, DEBUG, category, fmt, ## __VA_ARGS__) +#else +# define CH_DBG(fmt, ...) +#endif + #define CH_DEVICE(devid, ssid, idx) \ { PCI_VENDOR_ID_CHELSIO, devid, PCI_ANY_ID, ssid, 0, 0, idx } @@ -71,10 +89,6 @@ typedef struct adapter adapter_t; -void t1_elmer0_ext_intr(adapter_t *adapter); -void t1_link_changed(adapter_t *adapter, int port_id, int link_status, - int speed, int duplex, int fc); - struct t1_rx_mode { struct net_device *dev; u32 idx; @@ -97,26 +111,53 @@ static inline u8 *t1_get_next_mcaddr(struct t1_rx_mode *rm) } #define MAX_NPORTS 4 +#define PORT_MASK ((1 << MAX_NPORTS) - 1) +#define NMTUS 8 +#define TCB_SIZE 128 #define SPEED_INVALID 0xffff #define DUPLEX_INVALID 0xff enum { CHBT_BOARD_N110, - CHBT_BOARD_N210 + CHBT_BOARD_N210, + CHBT_BOARD_7500, + CHBT_BOARD_8000, + CHBT_BOARD_CHT101, + CHBT_BOARD_CHT110, + CHBT_BOARD_CHT210, + CHBT_BOARD_CHT204, + CHBT_BOARD_CHT204V, + CHBT_BOARD_CHT204E, + CHBT_BOARD_CHN204, + CHBT_BOARD_COUGAR, + CHBT_BOARD_6800, + CHBT_BOARD_SIMUL, }; enum { + CHBT_TERM_FPGA, CHBT_TERM_T1, - CHBT_TERM_T2 + CHBT_TERM_T2, + CHBT_TERM_T3 }; enum { + CHBT_MAC_CHELSIO_A, + CHBT_MAC_IXF1010, CHBT_MAC_PM3393, + CHBT_MAC_VSC7321, + CHBT_MAC_DUMMY }; enum { + CHBT_PHY_88E1041, + CHBT_PHY_88E1111, CHBT_PHY_88X2010, + CHBT_PHY_XPAK, + CHBT_PHY_MY3126, + CHBT_PHY_8244, + CHBT_PHY_DUMMY }; enum { @@ -150,16 +191,43 @@ struct chelsio_pci_params { unsigned char is_pcix; }; +struct tp_params { + unsigned int pm_size; + unsigned int cm_size; + unsigned int pm_rx_base; + unsigned int pm_tx_base; + unsigned int pm_rx_pg_size; + unsigned int pm_tx_pg_size; + unsigned int pm_rx_num_pgs; + unsigned int pm_tx_num_pgs; + unsigned int rx_coalescing_size; + unsigned int use_5tuple_mode; +}; + +struct mc5_params { + unsigned int mode; /* selects MC5 width */ + unsigned int nservers; /* size of server region */ + unsigned int nroutes; /* size of routing region */ +}; + +/* Default MC5 region sizes */ +#define DEFAULT_SERVER_REGION_LEN 256 +#define DEFAULT_RT_REGION_LEN 1024 + struct adapter_params { struct sge_params sge; + struct mc5_params mc5; + struct tp_params tp; struct chelsio_pci_params pci; const struct board_info *brd_info; + unsigned short mtus[NMTUS]; unsigned int nports; /* # of ethernet ports */ unsigned int stats_update_period; unsigned short chip_revision; unsigned char chip_version; + unsigned char is_asic; }; struct link_config { @@ -207,6 +275,7 @@ struct adapter { /* Terminator modules. */ struct sge *sge; struct peespi *espi; + struct petp *tp; struct port_info port[MAX_NPORTS]; struct work_struct stats_update_task; @@ -217,6 +286,7 @@ struct adapter { /* guards async operations */ spinlock_t async_lock ____cacheline_aligned; u32 slow_intr_mask; + int t1powersave; }; enum { /* adapter flags */ @@ -255,6 +325,11 @@ struct board_info { const char *desc; }; +static inline int t1_is_asic(const adapter_t *adapter) +{ + return adapter->params.is_asic; +} + extern struct pci_device_id t1_pci_tbl[]; static inline int adapter_matches_type(const adapter_t *adapter, @@ -284,13 +359,15 @@ static inline unsigned int core_ticks_per_usec(const adapter_t *adap) return board_info(adap)->clock_core / 1000000; } +extern int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp); +extern int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value); extern int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value); extern int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *value); extern void t1_interrupts_enable(adapter_t *adapter); extern void t1_interrupts_disable(adapter_t *adapter); extern void t1_interrupts_clear(adapter_t *adapter); -extern int elmer0_ext_intr_handler(adapter_t *adapter); +extern int t1_elmer0_ext_intr_handler(adapter_t *adapter); extern int t1_slow_intr_handler(adapter_t *adapter); extern int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc); @@ -304,9 +381,7 @@ extern int t1_init_hw_modules(adapter_t *adapter); extern int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi); extern void t1_free_sw_modules(adapter_t *adapter); extern void t1_fatal_err(adapter_t *adapter); - -extern void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable); -extern void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable); -extern void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable); - +extern void t1_link_changed(adapter_t *adapter, int port_id); +extern void t1_link_negotiated(adapter_t *adapter, int port_id, int link_stat, + int speed, int duplex, int pause); #endif /* _CXGB_COMMON_H_ */ diff --git a/drivers/net/chelsio/cphy.h b/drivers/net/chelsio/cphy.h index 3412342f7345..60901f25014e 100644 --- a/drivers/net/chelsio/cphy.h +++ b/drivers/net/chelsio/cphy.h @@ -52,7 +52,14 @@ struct mdio_ops { /* PHY interrupt types */ enum { cphy_cause_link_change = 0x1, - cphy_cause_error = 0x2 + cphy_cause_error = 0x2, + cphy_cause_fifo_error = 0x3 +}; + +enum { + PHY_LINK_UP = 0x1, + PHY_AUTONEG_RDY = 0x2, + PHY_AUTONEG_EN = 0x4 }; struct cphy; @@ -81,7 +88,18 @@ struct cphy_ops { /* A PHY instance */ struct cphy { int addr; /* PHY address */ + int state; /* Link status state machine */ adapter_t *adapter; /* associated adapter */ + + struct work_struct phy_update; + + u16 bmsr; + int count; + int act_count; + int act_on; + + u32 elmer_gpo; + struct cphy_ops *ops; /* PHY operations */ int (*mdio_read)(adapter_t *adapter, int phy_addr, int mmd_addr, int reg_addr, unsigned int *val); @@ -142,6 +160,10 @@ struct gphy { int (*reset)(adapter_t *adapter); }; +extern struct gphy t1_my3126_ops; +extern struct gphy t1_mv88e1xxx_ops; +extern struct gphy t1_vsc8244_ops; +extern struct gphy t1_xpak_ops; extern struct gphy t1_mv88x201x_ops; extern struct gphy t1_dummy_phy_ops; diff --git a/drivers/net/chelsio/cpl5_cmd.h b/drivers/net/chelsio/cpl5_cmd.h index 5b357d9e88d6..35f565be4fd3 100644 --- a/drivers/net/chelsio/cpl5_cmd.h +++ b/drivers/net/chelsio/cpl5_cmd.h @@ -46,24 +46,385 @@ #endif enum CPL_opcode { + CPL_PASS_OPEN_REQ = 0x1, + CPL_PASS_OPEN_RPL = 0x2, + CPL_PASS_ESTABLISH = 0x3, + CPL_PASS_ACCEPT_REQ = 0xE, + CPL_PASS_ACCEPT_RPL = 0x4, + CPL_ACT_OPEN_REQ = 0x5, + CPL_ACT_OPEN_RPL = 0x6, + CPL_CLOSE_CON_REQ = 0x7, + CPL_CLOSE_CON_RPL = 0x8, + CPL_CLOSE_LISTSRV_REQ = 0x9, + CPL_CLOSE_LISTSRV_RPL = 0xA, + CPL_ABORT_REQ = 0xB, + CPL_ABORT_RPL = 0xC, + CPL_PEER_CLOSE = 0xD, + CPL_ACT_ESTABLISH = 0x17, + + CPL_GET_TCB = 0x24, + CPL_GET_TCB_RPL = 0x25, + CPL_SET_TCB = 0x26, + CPL_SET_TCB_FIELD = 0x27, + CPL_SET_TCB_RPL = 0x28, + CPL_PCMD = 0x29, + + CPL_PCMD_READ = 0x31, + CPL_PCMD_READ_RPL = 0x32, + + + CPL_RX_DATA = 0xA0, + CPL_RX_DATA_DDP = 0xA1, + CPL_RX_DATA_ACK = 0xA3, CPL_RX_PKT = 0xAD, + CPL_RX_ISCSI_HDR = 0xAF, + CPL_TX_DATA_ACK = 0xB0, + CPL_TX_DATA = 0xB1, CPL_TX_PKT = 0xB2, CPL_TX_PKT_LSO = 0xB6, + + CPL_RTE_DELETE_REQ = 0xC0, + CPL_RTE_DELETE_RPL = 0xC1, + CPL_RTE_WRITE_REQ = 0xC2, + CPL_RTE_WRITE_RPL = 0xD3, + CPL_RTE_READ_REQ = 0xC3, + CPL_RTE_READ_RPL = 0xC4, + CPL_L2T_WRITE_REQ = 0xC5, + CPL_L2T_WRITE_RPL = 0xD4, + CPL_L2T_READ_REQ = 0xC6, + CPL_L2T_READ_RPL = 0xC7, + CPL_SMT_WRITE_REQ = 0xC8, + CPL_SMT_WRITE_RPL = 0xD5, + CPL_SMT_READ_REQ = 0xC9, + CPL_SMT_READ_RPL = 0xCA, + CPL_ARP_MISS_REQ = 0xCD, + CPL_ARP_MISS_RPL = 0xCE, + CPL_MIGRATE_C2T_REQ = 0xDC, + CPL_MIGRATE_C2T_RPL = 0xDD, + CPL_ERROR = 0xD7, + + /* internal: driver -> TOM */ + CPL_MSS_CHANGE = 0xE1 }; -enum { /* TX_PKT_LSO ethernet types */ +#define NUM_CPL_CMDS 256 + +enum CPL_error { + CPL_ERR_NONE = 0, + CPL_ERR_TCAM_PARITY = 1, + CPL_ERR_TCAM_FULL = 3, + CPL_ERR_CONN_RESET = 20, + CPL_ERR_CONN_EXIST = 22, + CPL_ERR_ARP_MISS = 23, + CPL_ERR_BAD_SYN = 24, + CPL_ERR_CONN_TIMEDOUT = 30, + CPL_ERR_XMIT_TIMEDOUT = 31, + CPL_ERR_PERSIST_TIMEDOUT = 32, + CPL_ERR_FINWAIT2_TIMEDOUT = 33, + CPL_ERR_KEEPALIVE_TIMEDOUT = 34, + CPL_ERR_ABORT_FAILED = 42, + CPL_ERR_GENERAL = 99 +}; + +enum { + CPL_CONN_POLICY_AUTO = 0, + CPL_CONN_POLICY_ASK = 1, + CPL_CONN_POLICY_DENY = 3 +}; + +enum { + ULP_MODE_NONE = 0, + ULP_MODE_TCPDDP = 1, + ULP_MODE_ISCSI = 2, + ULP_MODE_IWARP = 3, + ULP_MODE_SSL = 4 +}; + +enum { + CPL_PASS_OPEN_ACCEPT, + CPL_PASS_OPEN_REJECT +}; + +enum { + CPL_ABORT_SEND_RST = 0, + CPL_ABORT_NO_RST, + CPL_ABORT_POST_CLOSE_REQ = 2 +}; + +enum { // TX_PKT_LSO ethernet types CPL_ETH_II, CPL_ETH_II_VLAN, CPL_ETH_802_3, CPL_ETH_802_3_VLAN }; -struct cpl_rx_data { +union opcode_tid { + u32 opcode_tid; + u8 opcode; +}; + +#define S_OPCODE 24 +#define V_OPCODE(x) ((x) << S_OPCODE) +#define G_OPCODE(x) (((x) >> S_OPCODE) & 0xFF) +#define G_TID(x) ((x) & 0xFFFFFF) + +/* tid is assumed to be 24-bits */ +#define MK_OPCODE_TID(opcode, tid) (V_OPCODE(opcode) | (tid)) + +#define OPCODE_TID(cmd) ((cmd)->ot.opcode_tid) + +/* extract the TID from a CPL command */ +#define GET_TID(cmd) (G_TID(ntohl(OPCODE_TID(cmd)))) + +struct tcp_options { + u16 mss; + u8 wsf; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 rsvd:4; + u8 ecn:1; + u8 sack:1; + u8 tstamp:1; +#else + u8 tstamp:1; + u8 sack:1; + u8 ecn:1; + u8 rsvd:4; +#endif +}; + +struct cpl_pass_open_req { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 opt0h; + u32 opt0l; + u32 peer_netmask; + u32 opt1; +}; + +struct cpl_pass_open_rpl { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u8 resvd[7]; + u8 status; +}; + +struct cpl_pass_establish { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 tos_tid; + u8 l2t_idx; + u8 rsvd[3]; + u32 snd_isn; + u32 rcv_isn; +}; + +struct cpl_pass_accept_req { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 tos_tid; + struct tcp_options tcp_options; + u8 dst_mac[6]; + u16 vlan_tag; + u8 src_mac[6]; + u8 rsvd[2]; + u32 rcv_isn; + u32 unknown_tcp_options; +}; + +struct cpl_pass_accept_rpl { + union opcode_tid ot; + u32 rsvd0; + u32 rsvd1; + u32 peer_ip; + u32 opt0h; + union { + u32 opt0l; + struct { + u8 rsvd[3]; + u8 status; + }; + }; +}; + +struct cpl_act_open_req { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 opt0h; + u32 opt0l; + u32 iff_vlantag; + u32 rsvd; +}; + +struct cpl_act_open_rpl { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 new_tid; + u8 rsvd[3]; + u8 status; +}; + +struct cpl_act_establish { + union opcode_tid ot; + u16 local_port; + u16 peer_port; + u32 local_ip; + u32 peer_ip; + u32 tos_tid; + u32 rsvd; + u32 snd_isn; + u32 rcv_isn; +}; + +struct cpl_get_tcb { + union opcode_tid ot; + u32 rsvd; +}; + +struct cpl_get_tcb_rpl { + union opcode_tid ot; + u16 len; + u8 rsvd; + u8 status; +}; + +struct cpl_set_tcb { + union opcode_tid ot; + u16 len; + u16 rsvd; +}; + +struct cpl_set_tcb_field { + union opcode_tid ot; + u8 rsvd[3]; + u8 offset; + u32 mask; + u32 val; +}; + +struct cpl_set_tcb_rpl { + union opcode_tid ot; + u8 rsvd[3]; + u8 status; +}; + +struct cpl_pcmd { + union opcode_tid ot; + u16 dlen_in; + u16 dlen_out; + u32 pcmd_parm[2]; +}; + +struct cpl_pcmd_read { + union opcode_tid ot; + u32 rsvd1; + u16 rsvd2; + u32 addr; + u16 len; +}; + +struct cpl_pcmd_read_rpl { + union opcode_tid ot; + u16 len; +}; + +struct cpl_close_con_req { + union opcode_tid ot; + u32 rsvd; +}; + +struct cpl_close_con_rpl { + union opcode_tid ot; + u8 rsvd[3]; + u8 status; + u32 snd_nxt; + u32 rcv_nxt; +}; + +struct cpl_close_listserv_req { + union opcode_tid ot; + u32 rsvd; +}; + +struct cpl_close_listserv_rpl { + union opcode_tid ot; + u8 rsvd[3]; + u8 status; +}; + +struct cpl_abort_req { + union opcode_tid ot; u32 rsvd0; + u8 rsvd1; + u8 cmd; + u8 rsvd2[6]; +}; + +struct cpl_abort_rpl { + union opcode_tid ot; + u32 rsvd0; + u8 rsvd1; + u8 status; + u8 rsvd2[6]; +}; + +struct cpl_peer_close { + union opcode_tid ot; + u32 rsvd; +}; + +struct cpl_tx_data { + union opcode_tid ot; + u32 len; + u32 rsvd0; + u16 urg; + u16 flags; +}; + +struct cpl_tx_data_ack { + union opcode_tid ot; + u32 ack_seq; +}; + +struct cpl_rx_data { + union opcode_tid ot; u32 len; u32 seq; u16 urg; - u8 rsvd1; + u8 rsvd; + u8 status; +}; + +struct cpl_rx_data_ack { + union opcode_tid ot; + u32 credit; +}; + +struct cpl_rx_data_ddp { + union opcode_tid ot; + u32 len; + u32 seq; + u32 nxt_seq; + u32 ulp_crc; + u16 ddp_status; + u8 rsvd; u8 status; }; @@ -99,9 +460,9 @@ struct cpl_tx_pkt_lso { u8 ip_csum_dis:1; u8 l4_csum_dis:1; u8 vlan_valid:1; - u8 rsvd:1; + u8 :1; #else - u8 rsvd:1; + u8 :1; u8 vlan_valid:1; u8 l4_csum_dis:1; u8 ip_csum_dis:1; @@ -110,8 +471,7 @@ struct cpl_tx_pkt_lso { u16 vlan; __be32 len; - u32 rsvd2; - u8 rsvd3; + u8 rsvd[5]; #if defined(__LITTLE_ENDIAN_BITFIELD) u8 tcp_hdr_words:4; u8 ip_hdr_words:4; @@ -138,8 +498,142 @@ struct cpl_rx_pkt { u8 iff:4; #endif u16 csum; - __be16 vlan; + u16 vlan; u16 len; }; +struct cpl_l2t_write_req { + union opcode_tid ot; + u32 params; + u8 rsvd1[2]; + u8 dst_mac[6]; +}; + +struct cpl_l2t_write_rpl { + union opcode_tid ot; + u8 status; + u8 rsvd[3]; +}; + +struct cpl_l2t_read_req { + union opcode_tid ot; + u8 rsvd[3]; + u8 l2t_idx; +}; + +struct cpl_l2t_read_rpl { + union opcode_tid ot; + u32 params; + u8 rsvd1[2]; + u8 dst_mac[6]; +}; + +struct cpl_smt_write_req { + union opcode_tid ot; + u8 rsvd0; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 rsvd1:1; + u8 mtu_idx:3; + u8 iff:4; +#else + u8 iff:4; + u8 mtu_idx:3; + u8 rsvd1:1; +#endif + u16 rsvd2; + u16 rsvd3; + u8 src_mac1[6]; + u16 rsvd4; + u8 src_mac0[6]; +}; + +struct cpl_smt_write_rpl { + union opcode_tid ot; + u8 status; + u8 rsvd[3]; +}; + +struct cpl_smt_read_req { + union opcode_tid ot; + u8 rsvd0; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 rsvd1:4; + u8 iff:4; +#else + u8 iff:4; + u8 rsvd1:4; +#endif + u16 rsvd2; +}; + +struct cpl_smt_read_rpl { + union opcode_tid ot; + u8 status; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 rsvd1:1; + u8 mtu_idx:3; + u8 rsvd0:4; +#else + u8 rsvd0:4; + u8 mtu_idx:3; + u8 rsvd1:1; +#endif + u16 rsvd2; + u16 rsvd3; + u8 src_mac1[6]; + u16 rsvd4; + u8 src_mac0[6]; +}; + +struct cpl_rte_delete_req { + union opcode_tid ot; + u32 params; +}; + +struct cpl_rte_delete_rpl { + union opcode_tid ot; + u8 status; + u8 rsvd[3]; +}; + +struct cpl_rte_write_req { + union opcode_tid ot; + u32 params; + u32 netmask; + u32 faddr; +}; + +struct cpl_rte_write_rpl { + union opcode_tid ot; + u8 status; + u8 rsvd[3]; +}; + +struct cpl_rte_read_req { + union opcode_tid ot; + u32 params; +}; + +struct cpl_rte_read_rpl { + union opcode_tid ot; + u8 status; + u8 rsvd0[2]; + u8 l2t_idx; +#if defined(__LITTLE_ENDIAN_BITFIELD) + u8 rsvd1:7; + u8 select:1; +#else + u8 select:1; + u8 rsvd1:7; +#endif + u8 rsvd2[3]; + u32 addr; +}; + +struct cpl_mss_change { + union opcode_tid ot; + u32 mss; +}; + #endif /* _CXGB_CPL5_CMD_H_ */ + diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 42ad9cfd670a..a8c873b0af54 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -53,7 +53,9 @@ #include "gmac.h" #include "cphy.h" #include "sge.h" +#include "tp.h" #include "espi.h" +#include "elmer0.h" #include @@ -73,10 +75,9 @@ static inline void cancel_mac_stats_update(struct adapter *ap) #define MAX_RX_JUMBO_BUFFERS 16384 #define MAX_TX_BUFFERS_HIGH 16384U #define MAX_TX_BUFFERS_LOW 1536U +#define MAX_TX_BUFFERS 1460U #define MIN_FL_ENTRIES 32 -#define PORT_MASK ((1 << MAX_NPORTS) - 1) - #define DFLT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | \ NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\ NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) @@ -94,8 +95,17 @@ MODULE_LICENSE("GPL"); static int dflt_msg_enable = DFLT_MSG_ENABLE; module_param(dflt_msg_enable, int, 0); -MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 message enable bitmap"); +MODULE_PARM_DESC(dflt_msg_enable, "Chelsio T1 default message enable bitmap"); + +#define HCLOCK 0x0 +#define LCLOCK 0x1 + +/* T1 cards powersave mode */ +static int t1_clock(struct adapter *adapter, int mode); +static int t1powersave = 1; /* HW default is powersave mode. */ +module_param(t1powersave, int, 0); +MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode"); static const char pci_speed[][4] = { "33", "66", "100", "133" @@ -135,7 +145,7 @@ static void link_report(struct port_info *p) } } -void t1_link_changed(struct adapter *adapter, int port_id, int link_stat, +void t1_link_negotiated(struct adapter *adapter, int port_id, int link_stat, int speed, int duplex, int pause) { struct port_info *p = &adapter->port[port_id]; @@ -147,6 +157,22 @@ void t1_link_changed(struct adapter *adapter, int port_id, int link_stat, netif_carrier_off(p->dev); link_report(p); + /* multi-ports: inform toe */ + if ((speed > 0) && (adapter->params.nports > 1)) { + unsigned int sched_speed = 10; + switch (speed) { + case SPEED_1000: + sched_speed = 1000; + break; + case SPEED_100: + sched_speed = 100; + break; + case SPEED_10: + sched_speed = 10; + break; + } + t1_sched_update_parms(adapter->sge, port_id, 0, sched_speed); + } } } @@ -165,8 +191,10 @@ static void link_start(struct port_info *p) static void enable_hw_csum(struct adapter *adapter) { if (adapter->flags & TSO_CAPABLE) - t1_tp_set_ip_checksum_offload(adapter, 1); /* for TSO only */ - t1_tp_set_tcp_checksum_offload(adapter, 1); + t1_tp_set_ip_checksum_offload(adapter->tp, 1); /* for TSO only */ + if (adapter->flags & UDP_CSUM_CAPABLE) + t1_tp_set_udp_checksum_offload(adapter->tp, 1); + t1_tp_set_tcp_checksum_offload(adapter->tp, 1); } /* @@ -468,6 +496,18 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = (u64)t->tx_reg_pkts; *data++ = (u64)t->tx_lso_pkts; *data++ = (u64)t->tx_do_cksum; + + if (adapter->espi) { + const struct espi_intr_counts *e; + + e = t1_espi_get_intr_counts(adapter->espi); + *data++ = (u64) e->DIP2_parity_err; + *data++ = (u64) e->DIP4_err; + *data++ = (u64) e->rx_drops; + *data++ = (u64) e->tx_drops; + *data++ = (u64) e->rx_ovflw; + *data++ = (u64) e->parity_err; + } } static inline void reg_block_dump(struct adapter *ap, void *buf, @@ -491,6 +531,15 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs, memset(buf, 0, T2_REGMAP_SIZE); reg_block_dump(ap, buf, 0, A_SG_RESPACCUTIMER); + reg_block_dump(ap, buf, A_MC3_CFG, A_MC4_INT_CAUSE); + reg_block_dump(ap, buf, A_TPI_ADDR, A_TPI_PAR); + reg_block_dump(ap, buf, A_TP_IN_CONFIG, A_TP_TX_DROP_COUNT); + reg_block_dump(ap, buf, A_RAT_ROUTE_CONTROL, A_RAT_INTR_CAUSE); + reg_block_dump(ap, buf, A_CSPI_RX_AE_WM, A_CSPI_INTR_ENABLE); + reg_block_dump(ap, buf, A_ESPI_SCH_TOKEN0, A_ESPI_GOSTAT); + reg_block_dump(ap, buf, A_ULP_ULIMIT, A_ULP_PIO_CTRL); + reg_block_dump(ap, buf, A_PL_ENABLE, A_PL_CAUSE); + reg_block_dump(ap, buf, A_MC5_CONFIG, A_MC5_MASK_WRITE_CMD); } static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd) @@ -729,7 +778,9 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) static int get_eeprom_len(struct net_device *dev) { - return EEPROM_SIZE; + struct adapter *adapter = dev->priv; + + return t1_is_asic(adapter) ? EEPROM_SIZE : 0; } #define EEPROM_MAGIC(ap) \ @@ -914,7 +965,7 @@ static void ext_intr_task(void *data) { struct adapter *adapter = data; - elmer0_ext_intr_handler(adapter); + t1_elmer0_ext_intr_handler(adapter); /* Now reenable external interrupts */ spin_lock_irq(&adapter->async_lock); @@ -1074,16 +1125,19 @@ static int __devinit init_one(struct pci_dev *pdev, netdev->vlan_rx_register = vlan_rx_register; netdev->vlan_rx_kill_vid = vlan_rx_kill_vid; #endif - adapter->flags |= TSO_CAPABLE; - netdev->features |= NETIF_F_TSO; + + /* T204: disable TSO */ + if (!(is_T2(adapter)) || bi->port_number != 4) { + adapter->flags |= TSO_CAPABLE; + netdev->features |= NETIF_F_TSO; + } } netdev->open = cxgb_open; netdev->stop = cxgb_close; netdev->hard_start_xmit = t1_start_xmit; netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ? - sizeof(struct cpl_tx_pkt_lso) : - sizeof(struct cpl_tx_pkt); + sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt); netdev->get_stats = t1_get_stats; netdev->set_multicast_list = t1_set_rxmode; netdev->do_ioctl = t1_ioctl; @@ -1134,6 +1188,17 @@ static int __devinit init_one(struct pci_dev *pdev, bi->desc, adapter->params.chip_revision, adapter->params.pci.is_pcix ? "PCIX" : "PCI", adapter->params.pci.speed, adapter->params.pci.width); + + /* + * Set the T1B ASIC and memory clocks. + */ + if (t1powersave) + adapter->t1powersave = LCLOCK; /* HW default is powersave mode. */ + else + adapter->t1powersave = HCLOCK; + if (t1_is_T1B(adapter)) + t1_clock(adapter, t1powersave); + return 0; out_release_adapter_res: @@ -1153,6 +1218,155 @@ static int __devinit init_one(struct pci_dev *pdev, return err; } +static void bit_bang(struct adapter *adapter, int bitdata, int nbits) +{ + int data; + int i; + u32 val; + + enum { + S_CLOCK = 1 << 3, + S_DATA = 1 << 4 + }; + + for (i = (nbits - 1); i > -1; i--) { + + udelay(50); + + data = ((bitdata >> i) & 0x1); + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + + if (data) + val |= S_DATA; + else + val &= ~S_DATA; + + udelay(50); + + /* Set SCLOCK low */ + val &= ~S_CLOCK; + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + + udelay(50); + + /* Write SCLOCK high */ + val |= S_CLOCK; + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + + } +} + +static int t1_clock(struct adapter *adapter, int mode) +{ + u32 val; + int M_CORE_VAL; + int M_MEM_VAL; + + enum { + M_CORE_BITS = 9, + T_CORE_VAL = 0, + T_CORE_BITS = 2, + N_CORE_VAL = 0, + N_CORE_BITS = 2, + M_MEM_BITS = 9, + T_MEM_VAL = 0, + T_MEM_BITS = 2, + N_MEM_VAL = 0, + N_MEM_BITS = 2, + NP_LOAD = 1 << 17, + S_LOAD_MEM = 1 << 5, + S_LOAD_CORE = 1 << 6, + S_CLOCK = 1 << 3 + }; + + if (!t1_is_T1B(adapter)) + return -ENODEV; /* Can't re-clock this chip. */ + + if (mode & 2) { + return 0; /* show current mode. */ + } + + if ((adapter->t1powersave & 1) == (mode & 1)) + return -EALREADY; /* ASIC already running in mode. */ + + if ((mode & 1) == HCLOCK) { + M_CORE_VAL = 0x14; + M_MEM_VAL = 0x18; + adapter->t1powersave = HCLOCK; /* overclock */ + } else { + M_CORE_VAL = 0xe; + M_MEM_VAL = 0x10; + adapter->t1powersave = LCLOCK; /* underclock */ + } + + /* Don't interrupt this serial stream! */ + spin_lock(&adapter->tpi_lock); + + /* Initialize for ASIC core */ + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val |= NP_LOAD; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~S_LOAD_CORE; + val &= ~S_CLOCK; + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + + /* Serial program the ASIC clock synthesizer */ + bit_bang(adapter, T_CORE_VAL, T_CORE_BITS); + bit_bang(adapter, N_CORE_VAL, N_CORE_BITS); + bit_bang(adapter, M_CORE_VAL, M_CORE_BITS); + udelay(50); + + /* Finish ASIC core */ + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val |= S_LOAD_CORE; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~S_LOAD_CORE; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + + /* Initialize for memory */ + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val |= NP_LOAD; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~S_LOAD_MEM; + val &= ~S_CLOCK; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + + /* Serial program the memory clock synthesizer */ + bit_bang(adapter, T_MEM_VAL, T_MEM_BITS); + bit_bang(adapter, N_MEM_VAL, N_MEM_BITS); + bit_bang(adapter, M_MEM_VAL, M_MEM_BITS); + udelay(50); + + /* Finish memory */ + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val |= S_LOAD_MEM; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(50); + __t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~S_LOAD_MEM; + udelay(50); + __t1_tpi_write(adapter, A_ELMER0_GPO, val); + + spin_unlock(&adapter->tpi_lock); + + return 0; +} + static inline void t1_sw_reset(struct pci_dev *pdev) { pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 3); diff --git a/drivers/net/chelsio/elmer0.h b/drivers/net/chelsio/elmer0.h index 5590cb2dac19..9ebecaa97d31 100644 --- a/drivers/net/chelsio/elmer0.h +++ b/drivers/net/chelsio/elmer0.h @@ -39,6 +39,12 @@ #ifndef _CXGB_ELMER0_H_ #define _CXGB_ELMER0_H_ +/* ELMER0 flavors */ +enum { + ELMER0_XC2S300E_6FT256_C, + ELMER0_XC2S100E_6TQ144_C +}; + /* ELMER0 registers */ #define A_ELMER0_VERSION 0x100000 #define A_ELMER0_PHY_CFG 0x100004 @@ -149,3 +155,4 @@ #define MI1_OP_INDIRECT_READ 3 #endif /* _CXGB_ELMER0_H_ */ + diff --git a/drivers/net/chelsio/espi.c b/drivers/net/chelsio/espi.c index 40af47b795e6..4192f0f5b3ee 100644 --- a/drivers/net/chelsio/espi.c +++ b/drivers/net/chelsio/espi.c @@ -81,46 +81,36 @@ static int tricn_write(adapter_t *adapter, int bundle_addr, int module_addr, return busy; } -/* 1. Deassert rx_reset_core. */ -/* 2. Program TRICN_CNFG registers. */ -/* 3. Deassert rx_reset_link */ static int tricn_init(adapter_t *adapter) { - int i = 0; - int stat = 0; - int timeout = 0; - int is_ready = 0; + int i, sme = 1; - /* 1 */ - timeout=1000; - do { - stat = readl(adapter->regs + A_ESPI_RX_RESET); - is_ready = (stat & 0x4); - timeout--; - udelay(5); - } while (!is_ready || (timeout==0)); - writel(0x2, adapter->regs + A_ESPI_RX_RESET); - if (timeout==0) - { - CH_ERR("ESPI : ERROR : Timeout tricn_init() \n"); - t1_fatal_err(adapter); + if (!(readl(adapter->regs + A_ESPI_RX_RESET) & F_RX_CLK_STATUS)) { + CH_ERR("%s: ESPI clock not ready\n", adapter->name); + return -1; } - /* 2 */ - tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81); - tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81); - tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81); - for (i=1; i<= 8; i++) tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1); - for (i=1; i<= 2; i++) tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1); - for (i=1; i<= 3; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1); - for (i=4; i<= 4; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1); - for (i=5; i<= 5; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1); - for (i=6; i<= 6; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1); - for (i=7; i<= 7; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0x80); - for (i=8; i<= 8; i++) tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xf1); - - /* 3 */ - writel(0x3, adapter->regs + A_ESPI_RX_RESET); + writel(F_ESPI_RX_CORE_RST, adapter->regs + A_ESPI_RX_RESET); + + if (sme) { + tricn_write(adapter, 0, 0, 0, TRICN_CNFG, 0x81); + tricn_write(adapter, 0, 1, 0, TRICN_CNFG, 0x81); + tricn_write(adapter, 0, 2, 0, TRICN_CNFG, 0x81); + } + for (i = 1; i <= 8; i++) + tricn_write(adapter, 0, 0, i, TRICN_CNFG, 0xf1); + for (i = 1; i <= 2; i++) + tricn_write(adapter, 0, 1, i, TRICN_CNFG, 0xf1); + for (i = 1; i <= 3; i++) + tricn_write(adapter, 0, 2, i, TRICN_CNFG, 0xe1); + tricn_write(adapter, 0, 2, 4, TRICN_CNFG, 0xf1); + tricn_write(adapter, 0, 2, 5, TRICN_CNFG, 0xe1); + tricn_write(adapter, 0, 2, 6, TRICN_CNFG, 0xf1); + tricn_write(adapter, 0, 2, 7, TRICN_CNFG, 0x80); + tricn_write(adapter, 0, 2, 8, TRICN_CNFG, 0xf1); + + writel(F_ESPI_RX_CORE_RST | F_ESPI_RX_LNK_RST, + adapter->regs + A_ESPI_RX_RESET); return 0; } @@ -143,6 +133,7 @@ void t1_espi_intr_enable(struct peespi *espi) void t1_espi_intr_clear(struct peespi *espi) { + readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT); writel(0xffffffff, espi->adapter->regs + A_ESPI_INTR_STATUS); writel(F_PL_INTR_ESPI, espi->adapter->regs + A_PL_CAUSE); } @@ -157,7 +148,6 @@ void t1_espi_intr_disable(struct peespi *espi) int t1_espi_intr_handler(struct peespi *espi) { - u32 cnt; u32 status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS); if (status & F_DIP4ERR) @@ -177,7 +167,7 @@ int t1_espi_intr_handler(struct peespi *espi) * Must read the error count to clear the interrupt * that it causes. */ - cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT); + readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT); } /* @@ -210,17 +200,45 @@ static void espi_setup_for_pm3393(adapter_t *adapter) writel(V_RX_NPORTS(1) | V_TX_NPORTS(1), adapter->regs + A_PORT_CONFIG); } -/* T2 Init part -- */ -/* 1. Set T_ESPI_MISCCTRL_ADDR */ -/* 2. Init ESPI registers. */ -/* 3. Init TriCN Hard Macro */ -int t1_espi_init(struct peespi *espi, int mac_type, int nports) +static void espi_setup_for_vsc7321(adapter_t *adapter) +{ + writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN0); + writel(0x1f401f4, adapter->regs + A_ESPI_SCH_TOKEN1); + writel(0x1f4, adapter->regs + A_ESPI_SCH_TOKEN2); + writel(0xa00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK); + writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK); + writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH); + writel(V_RX_NPORTS(4) | V_TX_NPORTS(4), adapter->regs + A_PORT_CONFIG); + + writel(0x08000008, adapter->regs + A_ESPI_TRAIN); +} + +/* + * Note that T1B requires at least 2 ports for IXF1010 due to a HW bug. + */ +static void espi_setup_for_ixf1010(adapter_t *adapter, int nports) { - u32 cnt; + writel(1, adapter->regs + A_ESPI_CALENDAR_LENGTH); + if (nports == 4) { + if (is_T2(adapter)) { + writel(0xf00, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK); + writel(0x3c0, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK); + } else { + writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK); + writel(0x1ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK); + } + } else { + writel(0x1fff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK); + writel(0x7ff, adapter->regs + A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK); + } + writel(V_RX_NPORTS(nports) | V_TX_NPORTS(nports), adapter->regs + A_PORT_CONFIG); +} + +int t1_espi_init(struct peespi *espi, int mac_type, int nports) +{ u32 status_enable_extra = 0; adapter_t *adapter = espi->adapter; - u32 status, burstval = 0x800100; /* Disable ESPI training. MACs that can handle it enable it below. */ writel(0, adapter->regs + A_ESPI_TRAIN); @@ -229,38 +247,20 @@ int t1_espi_init(struct peespi *espi, int mac_type, int nports) writel(V_OUT_OF_SYNC_COUNT(4) | V_DIP2_PARITY_ERR_THRES(3) | V_DIP4_THRES(1), adapter->regs + A_ESPI_MISC_CONTROL); - if (nports == 4) { - /* T204: maxburst1 = 0x40, maxburst2 = 0x20 */ - burstval = 0x200040; - } - } - writel(burstval, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); + writel(nports == 4 ? 0x200040 : 0x1000080, + adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); + } else + writel(0x800100, adapter->regs + A_ESPI_MAXBURST1_MAXBURST2); - switch (mac_type) { - case CHBT_MAC_PM3393: + if (mac_type == CHBT_MAC_PM3393) espi_setup_for_pm3393(adapter); - break; - default: + else if (mac_type == CHBT_MAC_VSC7321) + espi_setup_for_vsc7321(adapter); + else if (mac_type == CHBT_MAC_IXF1010) { + status_enable_extra = F_INTEL1010MODE; + espi_setup_for_ixf1010(adapter, nports); + } else return -1; - } - - /* - * Make sure any pending interrupts from the SPI are - * Cleared before enabling the interrupt. - */ - writel(ESPI_INTR_MASK, espi->adapter->regs + A_ESPI_INTR_ENABLE); - status = readl(espi->adapter->regs + A_ESPI_INTR_STATUS); - if (status & F_DIP2PARITYERR) { - cnt = readl(espi->adapter->regs + A_ESPI_DIP2_ERR_COUNT); - } - - /* - * For T1B we need to write 1 to clear ESPI interrupts. For T2+ we - * write the status as is. - */ - if (status && t1_is_T1B(espi->adapter)) - status = 1; - writel(status, espi->adapter->regs + A_ESPI_INTR_STATUS); writel(status_enable_extra | F_RXSTATUSENABLE, adapter->regs + A_ESPI_FIFO_STATUS_ENABLE); @@ -271,9 +271,11 @@ int t1_espi_init(struct peespi *espi, int mac_type, int nports) * Always position the control at the 1st port egress IN * (sop,eop) counter to reduce PIOs for T/N210 workaround. */ - espi->misc_ctrl = (readl(adapter->regs + A_ESPI_MISC_CONTROL) - & ~MON_MASK) | (F_MONITORED_DIRECTION - | F_MONITORED_INTERFACE); + espi->misc_ctrl = readl(adapter->regs + A_ESPI_MISC_CONTROL); + espi->misc_ctrl &= ~MON_MASK; + espi->misc_ctrl |= F_MONITORED_DIRECTION; + if (adapter->params.nports == 1) + espi->misc_ctrl |= F_MONITORED_INTERFACE; writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); spin_lock_init(&espi->lock); } @@ -299,8 +301,7 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val) { struct peespi *espi = adapter->espi; - if (!is_T2(adapter)) - return; + if (!is_T2(adapter)) return; spin_lock(&espi->lock); espi->misc_ctrl = (val & ~MON_MASK) | (espi->misc_ctrl & MON_MASK); @@ -310,27 +311,61 @@ void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val) u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait) { - u32 sel; - struct peespi *espi = adapter->espi; + u32 sel; if (!is_T2(adapter)) return 0; + sel = V_MONITORED_PORT_NUM((addr & 0x3c) >> 2); if (!wait) { if (!spin_trylock(&espi->lock)) return 0; - } - else + } else spin_lock(&espi->lock); + if ((sel != (espi->misc_ctrl & MON_MASK))) { writel(((espi->misc_ctrl & ~MON_MASK) | sel), adapter->regs + A_ESPI_MISC_CONTROL); sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3); writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); - } - else + } else sel = readl(adapter->regs + A_ESPI_SCH_TOKEN3); spin_unlock(&espi->lock); return sel; } + +/* + * This function is for T204 only. + * compare with t1_espi_get_mon(), it reads espiInTxSop[0 ~ 3] in + * one shot, since there is no per port counter on the out side. + */ +int +t1_espi_get_mon_t204(adapter_t *adapter, u32 *valp, u8 wait) +{ + struct peespi *espi = adapter->espi; + u8 i, nport = (u8)adapter->params.nports; + + if (!wait) { + if (!spin_trylock(&espi->lock)) + return -1; + } else + spin_lock(&espi->lock); + + if ( (espi->misc_ctrl & MON_MASK) != F_MONITORED_DIRECTION ) { + espi->misc_ctrl = (espi->misc_ctrl & ~MON_MASK) | + F_MONITORED_DIRECTION; + writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); + } + for (i = 0 ; i < nport; i++, valp++) { + if (i) { + writel(espi->misc_ctrl | V_MONITORED_PORT_NUM(i), + adapter->regs + A_ESPI_MISC_CONTROL); + } + *valp = readl(adapter->regs + A_ESPI_SCH_TOKEN3); + } + + writel(espi->misc_ctrl, adapter->regs + A_ESPI_MISC_CONTROL); + spin_unlock(&espi->lock); + return 0; +} diff --git a/drivers/net/chelsio/espi.h b/drivers/net/chelsio/espi.h index c90e37f8457c..84f2c98bc4cc 100644 --- a/drivers/net/chelsio/espi.h +++ b/drivers/net/chelsio/espi.h @@ -64,5 +64,6 @@ const struct espi_intr_counts *t1_espi_get_intr_counts(struct peespi *espi); void t1_espi_set_misc_ctrl(adapter_t *adapter, u32 val); u32 t1_espi_get_mon(adapter_t *adapter, u32 addr, u8 wait); +int t1_espi_get_mon_t204(adapter_t *, u32 *, u8); #endif /* _CXGB_ESPI_H_ */ diff --git a/drivers/net/chelsio/fpga_defs.h b/drivers/net/chelsio/fpga_defs.h new file mode 100644 index 000000000000..17a3c2ba36a3 --- /dev/null +++ b/drivers/net/chelsio/fpga_defs.h @@ -0,0 +1,232 @@ +/* $Date: 2005/03/07 23:59:05 $ $RCSfile: fpga_defs.h,v $ $Revision: 1.4 $ */ + +/* + * FPGA specific definitions + */ + +#ifndef __CHELSIO_FPGA_DEFS_H__ +#define __CHELSIO_FPGA_DEFS_H__ + +#define FPGA_PCIX_ADDR_VERSION 0xA08 +#define FPGA_PCIX_ADDR_STAT 0xA0C + +/* FPGA master interrupt Cause/Enable bits */ +#define FPGA_PCIX_INTERRUPT_SGE_ERROR 0x1 +#define FPGA_PCIX_INTERRUPT_SGE_DATA 0x2 +#define FPGA_PCIX_INTERRUPT_TP 0x4 +#define FPGA_PCIX_INTERRUPT_MC3 0x8 +#define FPGA_PCIX_INTERRUPT_GMAC 0x10 +#define FPGA_PCIX_INTERRUPT_PCIX 0x20 + +/* TP interrupt register addresses */ +#define FPGA_TP_ADDR_INTERRUPT_ENABLE 0xA10 +#define FPGA_TP_ADDR_INTERRUPT_CAUSE 0xA14 +#define FPGA_TP_ADDR_VERSION 0xA18 + +/* TP interrupt Cause/Enable bits */ +#define FPGA_TP_INTERRUPT_MC4 0x1 +#define FPGA_TP_INTERRUPT_MC5 0x2 + +/* + * PM interrupt register addresses + */ +#define FPGA_MC3_REG_INTRENABLE 0xA20 +#define FPGA_MC3_REG_INTRCAUSE 0xA24 +#define FPGA_MC3_REG_VERSION 0xA28 + +/* + * GMAC interrupt register addresses + */ +#define FPGA_GMAC_ADDR_INTERRUPT_ENABLE 0xA30 +#define FPGA_GMAC_ADDR_INTERRUPT_CAUSE 0xA34 +#define FPGA_GMAC_ADDR_VERSION 0xA38 + +/* GMAC Cause/Enable bits */ +#define FPGA_GMAC_INTERRUPT_PORT0 0x1 +#define FPGA_GMAC_INTERRUPT_PORT1 0x2 +#define FPGA_GMAC_INTERRUPT_PORT2 0x4 +#define FPGA_GMAC_INTERRUPT_PORT3 0x8 + +/* MI0 registers */ +#define A_MI0_CLK 0xb00 + +#define S_MI0_CLK_DIV 0 +#define M_MI0_CLK_DIV 0xff +#define V_MI0_CLK_DIV(x) ((x) << S_MI0_CLK_DIV) +#define G_MI0_CLK_DIV(x) (((x) >> S_MI0_CLK_DIV) & M_MI0_CLK_DIV) + +#define S_MI0_CLK_CNT 8 +#define M_MI0_CLK_CNT 0xff +#define V_MI0_CLK_CNT(x) ((x) << S_MI0_CLK_CNT) +#define G_MI0_CLK_CNT(x) (((x) >> S_MI0_CLK_CNT) & M_MI0_CLK_CNT) + +#define A_MI0_CSR 0xb04 + +#define S_MI0_CSR_POLL 0 +#define V_MI0_CSR_POLL(x) ((x) << S_MI0_CSR_POLL) +#define F_MI0_CSR_POLL V_MI0_CSR_POLL(1U) + +#define S_MI0_PREAMBLE 1 +#define V_MI0_PREAMBLE(x) ((x) << S_MI0_PREAMBLE) +#define F_MI0_PREAMBLE V_MI0_PREAMBLE(1U) + +#define S_MI0_INTR_ENABLE 2 +#define V_MI0_INTR_ENABLE(x) ((x) << S_MI0_INTR_ENABLE) +#define F_MI0_INTR_ENABLE V_MI0_INTR_ENABLE(1U) + +#define S_MI0_BUSY 3 +#define V_MI0_BUSY(x) ((x) << S_MI0_BUSY) +#define F_MI0_BUSY V_MI0_BUSY(1U) + +#define S_MI0_MDIO 4 +#define V_MI0_MDIO(x) ((x) << S_MI0_MDIO) +#define F_MI0_MDIO V_MI0_MDIO(1U) + +#define A_MI0_ADDR 0xb08 + +#define S_MI0_PHY_REG_ADDR 0 +#define M_MI0_PHY_REG_ADDR 0x1f +#define V_MI0_PHY_REG_ADDR(x) ((x) << S_MI0_PHY_REG_ADDR) +#define G_MI0_PHY_REG_ADDR(x) (((x) >> S_MI0_PHY_REG_ADDR) & M_MI0_PHY_REG_ADDR) + +#define S_MI0_PHY_ADDR 5 +#define M_MI0_PHY_ADDR 0x1f +#define V_MI0_PHY_ADDR(x) ((x) << S_MI0_PHY_ADDR) +#define G_MI0_PHY_ADDR(x) (((x) >> S_MI0_PHY_ADDR) & M_MI0_PHY_ADDR) + +#define A_MI0_DATA_EXT 0xb0c +#define A_MI0_DATA_INT 0xb10 + +/* GMAC registers */ +#define A_GMAC_MACID_LO 0x28 +#define A_GMAC_MACID_HI 0x2c +#define A_GMAC_CSR 0x30 + +#define S_INTERFACE 0 +#define M_INTERFACE 0x3 +#define V_INTERFACE(x) ((x) << S_INTERFACE) +#define G_INTERFACE(x) (((x) >> S_INTERFACE) & M_INTERFACE) + +#define S_MAC_TX_ENABLE 2 +#define V_MAC_TX_ENABLE(x) ((x) << S_MAC_TX_ENABLE) +#define F_MAC_TX_ENABLE V_MAC_TX_ENABLE(1U) + +#define S_MAC_RX_ENABLE 3 +#define V_MAC_RX_ENABLE(x) ((x) << S_MAC_RX_ENABLE) +#define F_MAC_RX_ENABLE V_MAC_RX_ENABLE(1U) + +#define S_MAC_LB_ENABLE 4 +#define V_MAC_LB_ENABLE(x) ((x) << S_MAC_LB_ENABLE) +#define F_MAC_LB_ENABLE V_MAC_LB_ENABLE(1U) + +#define S_MAC_SPEED 5 +#define M_MAC_SPEED 0x3 +#define V_MAC_SPEED(x) ((x) << S_MAC_SPEED) +#define G_MAC_SPEED(x) (((x) >> S_MAC_SPEED) & M_MAC_SPEED) + +#define S_MAC_HD_FC_ENABLE 7 +#define V_MAC_HD_FC_ENABLE(x) ((x) << S_MAC_HD_FC_ENABLE) +#define F_MAC_HD_FC_ENABLE V_MAC_HD_FC_ENABLE(1U) + +#define S_MAC_HALF_DUPLEX 8 +#define V_MAC_HALF_DUPLEX(x) ((x) << S_MAC_HALF_DUPLEX) +#define F_MAC_HALF_DUPLEX V_MAC_HALF_DUPLEX(1U) + +#define S_MAC_PROMISC 9 +#define V_MAC_PROMISC(x) ((x) << S_MAC_PROMISC) +#define F_MAC_PROMISC V_MAC_PROMISC(1U) + +#define S_MAC_MC_ENABLE 10 +#define V_MAC_MC_ENABLE(x) ((x) << S_MAC_MC_ENABLE) +#define F_MAC_MC_ENABLE V_MAC_MC_ENABLE(1U) + +#define S_MAC_RESET 11 +#define V_MAC_RESET(x) ((x) << S_MAC_RESET) +#define F_MAC_RESET V_MAC_RESET(1U) + +#define S_MAC_RX_PAUSE_ENABLE 12 +#define V_MAC_RX_PAUSE_ENABLE(x) ((x) << S_MAC_RX_PAUSE_ENABLE) +#define F_MAC_RX_PAUSE_ENABLE V_MAC_RX_PAUSE_ENABLE(1U) + +#define S_MAC_TX_PAUSE_ENABLE 13 +#define V_MAC_TX_PAUSE_ENABLE(x) ((x) << S_MAC_TX_PAUSE_ENABLE) +#define F_MAC_TX_PAUSE_ENABLE V_MAC_TX_PAUSE_ENABLE(1U) + +#define S_MAC_LWM_ENABLE 14 +#define V_MAC_LWM_ENABLE(x) ((x) << S_MAC_LWM_ENABLE) +#define F_MAC_LWM_ENABLE V_MAC_LWM_ENABLE(1U) + +#define S_MAC_MAGIC_PKT_ENABLE 15 +#define V_MAC_MAGIC_PKT_ENABLE(x) ((x) << S_MAC_MAGIC_PKT_ENABLE) +#define F_MAC_MAGIC_PKT_ENABLE V_MAC_MAGIC_PKT_ENABLE(1U) + +#define S_MAC_ISL_ENABLE 16 +#define V_MAC_ISL_ENABLE(x) ((x) << S_MAC_ISL_ENABLE) +#define F_MAC_ISL_ENABLE V_MAC_ISL_ENABLE(1U) + +#define S_MAC_JUMBO_ENABLE 17 +#define V_MAC_JUMBO_ENABLE(x) ((x) << S_MAC_JUMBO_ENABLE) +#define F_MAC_JUMBO_ENABLE V_MAC_JUMBO_ENABLE(1U) + +#define S_MAC_RX_PAD_ENABLE 18 +#define V_MAC_RX_PAD_ENABLE(x) ((x) << S_MAC_RX_PAD_ENABLE) +#define F_MAC_RX_PAD_ENABLE V_MAC_RX_PAD_ENABLE(1U) + +#define S_MAC_RX_CRC_ENABLE 19 +#define V_MAC_RX_CRC_ENABLE(x) ((x) << S_MAC_RX_CRC_ENABLE) +#define F_MAC_RX_CRC_ENABLE V_MAC_RX_CRC_ENABLE(1U) + +#define A_GMAC_IFS 0x34 + +#define S_MAC_IFS2 0 +#define M_MAC_IFS2 0x3f +#define V_MAC_IFS2(x) ((x) << S_MAC_IFS2) +#define G_MAC_IFS2(x) (((x) >> S_MAC_IFS2) & M_MAC_IFS2) + +#define S_MAC_IFS1 8 +#define M_MAC_IFS1 0x7f +#define V_MAC_IFS1(x) ((x) << S_MAC_IFS1) +#define G_MAC_IFS1(x) (((x) >> S_MAC_IFS1) & M_MAC_IFS1) + +#define A_GMAC_JUMBO_FRAME_LEN 0x38 +#define A_GMAC_LNK_DLY 0x3c +#define A_GMAC_PAUSETIME 0x40 +#define A_GMAC_MCAST_LO 0x44 +#define A_GMAC_MCAST_HI 0x48 +#define A_GMAC_MCAST_MASK_LO 0x4c +#define A_GMAC_MCAST_MASK_HI 0x50 +#define A_GMAC_RMT_CNT 0x54 +#define A_GMAC_RMT_DATA 0x58 +#define A_GMAC_BACKOFF_SEED 0x5c +#define A_GMAC_TXF_THRES 0x60 + +#define S_TXF_READ_THRESHOLD 0 +#define M_TXF_READ_THRESHOLD 0xff +#define V_TXF_READ_THRESHOLD(x) ((x) << S_TXF_READ_THRESHOLD) +#define G_TXF_READ_THRESHOLD(x) (((x) >> S_TXF_READ_THRESHOLD) & M_TXF_READ_THRESHOLD) + +#define S_TXF_WRITE_THRESHOLD 16 +#define M_TXF_WRITE_THRESHOLD 0xff +#define V_TXF_WRITE_THRESHOLD(x) ((x) << S_TXF_WRITE_THRESHOLD) +#define G_TXF_WRITE_THRESHOLD(x) (((x) >> S_TXF_WRITE_THRESHOLD) & M_TXF_WRITE_THRESHOLD) + +#define MAC_REG_BASE 0x600 +#define MAC_REG_ADDR(idx, reg) (MAC_REG_BASE + (idx) * 128 + (reg)) + +#define MAC_REG_IDLO(idx) MAC_REG_ADDR(idx, A_GMAC_MACID_LO) +#define MAC_REG_IDHI(idx) MAC_REG_ADDR(idx, A_GMAC_MACID_HI) +#define MAC_REG_CSR(idx) MAC_REG_ADDR(idx, A_GMAC_CSR) +#define MAC_REG_IFS(idx) MAC_REG_ADDR(idx, A_GMAC_IFS) +#define MAC_REG_LARGEFRAMELENGTH(idx) MAC_REG_ADDR(idx, A_GMAC_JUMBO_FRAME_LEN) +#define MAC_REG_LINKDLY(idx) MAC_REG_ADDR(idx, A_GMAC_LNK_DLY) +#define MAC_REG_PAUSETIME(idx) MAC_REG_ADDR(idx, A_GMAC_PAUSETIME) +#define MAC_REG_CASTLO(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_LO) +#define MAC_REG_MCASTHI(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_HI) +#define MAC_REG_CASTMASKLO(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_LO) +#define MAC_REG_MCASTMASKHI(idx) MAC_REG_ADDR(idx, A_GMAC_MCAST_MASK_HI) +#define MAC_REG_RMCNT(idx) MAC_REG_ADDR(idx, A_GMAC_RMT_CNT) +#define MAC_REG_RMDATA(idx) MAC_REG_ADDR(idx, A_GMAC_RMT_DATA) +#define MAC_REG_GMRANDBACKOFFSEED(idx) MAC_REG_ADDR(idx, A_GMAC_BACKOFF_SEED) +#define MAC_REG_TXFTHRESHOLDS(idx) MAC_REG_ADDR(idx, A_GMAC_TXF_THRES) + +#endif diff --git a/drivers/net/chelsio/gmac.h b/drivers/net/chelsio/gmac.h index 746b0eeea964..a2b8ad9b5535 100644 --- a/drivers/net/chelsio/gmac.h +++ b/drivers/net/chelsio/gmac.h @@ -62,6 +62,8 @@ struct cmac_statistics { u64 TxInternalMACXmitError; u64 TxFramesWithExcessiveDeferral; u64 TxFCSErrors; + u64 TxJumboFramesOK; + u64 TxJumboOctetsOK; /* Receive */ u64 RxOctetsOK; @@ -81,6 +83,8 @@ struct cmac_statistics { u64 RxInRangeLengthErrors; u64 RxOutOfRangeLengthField; u64 RxFrameTooLongErrors; + u64 RxJumboFramesOK; + u64 RxJumboOctetsOK; }; struct cmac_ops { @@ -128,6 +132,7 @@ struct gmac { extern struct gmac t1_pm3393_ops; extern struct gmac t1_chelsio_mac_ops; extern struct gmac t1_vsc7321_ops; +extern struct gmac t1_vsc7326_ops; extern struct gmac t1_ixf1010_ops; extern struct gmac t1_dummy_mac_ops; diff --git a/drivers/net/chelsio/mv88e1xxx.h b/drivers/net/chelsio/mv88e1xxx.h new file mode 100644 index 000000000000..967cc4286359 --- /dev/null +++ b/drivers/net/chelsio/mv88e1xxx.h @@ -0,0 +1,127 @@ +/* $Date: 2005/03/07 23:59:05 $ $RCSfile: mv88e1xxx.h,v $ $Revision: 1.13 $ */ +#ifndef CHELSIO_MV8E1XXX_H +#define CHELSIO_MV8E1XXX_H + +#ifndef BMCR_SPEED1000 +# define BMCR_SPEED1000 0x40 +#endif + +#ifndef ADVERTISE_PAUSE +# define ADVERTISE_PAUSE 0x400 +#endif +#ifndef ADVERTISE_PAUSE_ASYM +# define ADVERTISE_PAUSE_ASYM 0x800 +#endif + +/* Gigabit MII registers */ +#define MII_GBCR 9 /* 1000Base-T control register */ +#define MII_GBSR 10 /* 1000Base-T status register */ + +/* 1000Base-T control register fields */ +#define GBCR_ADV_1000HALF 0x100 +#define GBCR_ADV_1000FULL 0x200 +#define GBCR_PREFER_MASTER 0x400 +#define GBCR_MANUAL_AS_MASTER 0x800 +#define GBCR_MANUAL_CONFIG_ENABLE 0x1000 + +/* 1000Base-T status register fields */ +#define GBSR_LP_1000HALF 0x400 +#define GBSR_LP_1000FULL 0x800 +#define GBSR_REMOTE_OK 0x1000 +#define GBSR_LOCAL_OK 0x2000 +#define GBSR_LOCAL_MASTER 0x4000 +#define GBSR_MASTER_FAULT 0x8000 + +/* Marvell PHY interrupt status bits. */ +#define MV88E1XXX_INTR_JABBER 0x0001 +#define MV88E1XXX_INTR_POLARITY_CHNG 0x0002 +#define MV88E1XXX_INTR_ENG_DETECT_CHNG 0x0010 +#define MV88E1XXX_INTR_DOWNSHIFT 0x0020 +#define MV88E1XXX_INTR_MDI_XOVER_CHNG 0x0040 +#define MV88E1XXX_INTR_FIFO_OVER_UNDER 0x0080 +#define MV88E1XXX_INTR_FALSE_CARRIER 0x0100 +#define MV88E1XXX_INTR_SYMBOL_ERROR 0x0200 +#define MV88E1XXX_INTR_LINK_CHNG 0x0400 +#define MV88E1XXX_INTR_AUTONEG_DONE 0x0800 +#define MV88E1XXX_INTR_PAGE_RECV 0x1000 +#define MV88E1XXX_INTR_DUPLEX_CHNG 0x2000 +#define MV88E1XXX_INTR_SPEED_CHNG 0x4000 +#define MV88E1XXX_INTR_AUTONEG_ERR 0x8000 + +/* Marvell PHY specific registers. */ +#define MV88E1XXX_SPECIFIC_CNTRL_REGISTER 16 +#define MV88E1XXX_SPECIFIC_STATUS_REGISTER 17 +#define MV88E1XXX_INTERRUPT_ENABLE_REGISTER 18 +#define MV88E1XXX_INTERRUPT_STATUS_REGISTER 19 +#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER 20 +#define MV88E1XXX_RECV_ERR_CNTR_REGISTER 21 +#define MV88E1XXX_RES_REGISTER 22 +#define MV88E1XXX_GLOBAL_STATUS_REGISTER 23 +#define MV88E1XXX_LED_CONTROL_REGISTER 24 +#define MV88E1XXX_MANUAL_LED_OVERRIDE_REGISTER 25 +#define MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_2_REGISTER 26 +#define MV88E1XXX_EXT_PHY_SPECIFIC_STATUS_REGISTER 27 +#define MV88E1XXX_VIRTUAL_CABLE_TESTER_REGISTER 28 +#define MV88E1XXX_EXTENDED_ADDR_REGISTER 29 +#define MV88E1XXX_EXTENDED_REGISTER 30 + +/* PHY specific control register fields */ +#define S_PSCR_MDI_XOVER_MODE 5 +#define M_PSCR_MDI_XOVER_MODE 0x3 +#define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE) +#define G_PSCR_MDI_XOVER_MODE(x) (((x) >> S_PSCR_MDI_XOVER_MODE) & M_PSCR_MDI_XOVER_MODE) + +/* Extended PHY specific control register fields */ +#define S_DOWNSHIFT_ENABLE 8 +#define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE) + +#define S_DOWNSHIFT_CNT 9 +#define M_DOWNSHIFT_CNT 0x7 +#define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT) +#define G_DOWNSHIFT_CNT(x) (((x) >> S_DOWNSHIFT_CNT) & M_DOWNSHIFT_CNT) + +/* PHY specific status register fields */ +#define S_PSSR_JABBER 0 +#define V_PSSR_JABBER (1 << S_PSSR_JABBER) + +#define S_PSSR_POLARITY 1 +#define V_PSSR_POLARITY (1 << S_PSSR_POLARITY) + +#define S_PSSR_RX_PAUSE 2 +#define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE) + +#define S_PSSR_TX_PAUSE 3 +#define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE) + +#define S_PSSR_ENERGY_DETECT 4 +#define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT) + +#define S_PSSR_DOWNSHIFT_STATUS 5 +#define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS) + +#define S_PSSR_MDI 6 +#define V_PSSR_MDI (1 << S_PSSR_MDI) + +#define S_PSSR_CABLE_LEN 7 +#define M_PSSR_CABLE_LEN 0x7 +#define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN) +#define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN) + +#define S_PSSR_LINK 10 +#define V_PSSR_LINK (1 << S_PSSR_LINK) + +#define S_PSSR_STATUS_RESOLVED 11 +#define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED) + +#define S_PSSR_PAGE_RECEIVED 12 +#define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED) + +#define S_PSSR_DUPLEX 13 +#define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX) + +#define S_PSSR_SPEED 14 +#define M_PSSR_SPEED 0x3 +#define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED) +#define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED) + +#endif diff --git a/drivers/net/chelsio/mv88x201x.c b/drivers/net/chelsio/mv88x201x.c index bf7d8538885d..c8e89480d906 100644 --- a/drivers/net/chelsio/mv88x201x.c +++ b/drivers/net/chelsio/mv88x201x.c @@ -85,29 +85,33 @@ static int mv88x201x_reset(struct cphy *cphy, int wait) static int mv88x201x_interrupt_enable(struct cphy *cphy) { - u32 elmer; - /* Enable PHY LASI interrupts. */ mdio_write(cphy, 0x1, 0x9002, 0x1); /* Enable Marvell interrupts through Elmer0. */ - t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); - elmer |= ELMER0_GP_BIT6; - t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer |= ELMER0_GP_BIT6; + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } return 0; } static int mv88x201x_interrupt_disable(struct cphy *cphy) { - u32 elmer; - /* Disable PHY LASI interrupts. */ mdio_write(cphy, 0x1, 0x9002, 0x0); /* Disable Marvell interrupts through Elmer0. */ - t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); - elmer &= ~ELMER0_GP_BIT6; - t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer &= ~ELMER0_GP_BIT6; + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } return 0; } @@ -140,9 +144,11 @@ static int mv88x201x_interrupt_clear(struct cphy *cphy) #endif /* Clear Marvell interrupts through Elmer0. */ - t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); - elmer |= ELMER0_GP_BIT6; - t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); + if (t1_is_asic(cphy->adapter)) { + t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); + elmer |= ELMER0_GP_BIT6; + t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); + } return 0; } diff --git a/drivers/net/chelsio/my3126.c b/drivers/net/chelsio/my3126.c new file mode 100644 index 000000000000..0b90014d5b3e --- /dev/null +++ b/drivers/net/chelsio/my3126.c @@ -0,0 +1,204 @@ +/* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */ +#include "cphy.h" +#include "elmer0.h" +#include "suni1x10gexp_regs.h" + +/* Port Reset */ +static int my3126_reset(struct cphy *cphy, int wait) +{ + /* + * This can be done through registers. It is not required since + * a full chip reset is used. + */ + return (0); +} + +static int my3126_interrupt_enable(struct cphy *cphy) +{ + schedule_delayed_work(&cphy->phy_update, HZ/30); + t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo); + return (0); +} + +static int my3126_interrupt_disable(struct cphy *cphy) +{ + cancel_rearming_delayed_work(&cphy->phy_update); + return (0); +} + +static int my3126_interrupt_clear(struct cphy *cphy) +{ + return (0); +} + +#define OFFSET(REG_ADDR) (REG_ADDR << 2) + +static int my3126_interrupt_handler(struct cphy *cphy) +{ + u32 val; + u16 val16; + u16 status; + u32 act_count; + adapter_t *adapter; + adapter = cphy->adapter; + + if (cphy->count == 50) { + mdio_read(cphy, 0x1, 0x1, &val); + val16 = (u16) val; + status = cphy->bmsr ^ val16; + + if (status & BMSR_LSTATUS) + t1_link_changed(adapter, 0); + cphy->bmsr = val16; + + /* We have only enabled link change interrupts so it + must be that + */ + cphy->count = 0; + } + + t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL), + SUNI1x10GEXP_BITMSK_MSTAT_SNAP); + t1_tpi_read(adapter, + OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count); + t1_tpi_read(adapter, + OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val); + act_count += val; + + /* Populate elmer_gpo with the register value */ + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + cphy->elmer_gpo = val; + + if ( (val & (1 << 8)) || (val & (1 << 19)) || + (cphy->act_count == act_count) || cphy->act_on ) { + if (is_T2(adapter)) + val |= (1 << 9); + else if (t1_is_T1B(adapter)) + val |= (1 << 20); + cphy->act_on = 0; + } else { + if (is_T2(adapter)) + val &= ~(1 << 9); + else if (t1_is_T1B(adapter)) + val &= ~(1 << 20); + cphy->act_on = 1; + } + + t1_tpi_write(adapter, A_ELMER0_GPO, val); + + cphy->elmer_gpo = val; + cphy->act_count = act_count; + cphy->count++; + + return cphy_cause_link_change; +} + +static void my3216_poll(void *arg) +{ + my3126_interrupt_handler(arg); +} + +static int my3126_set_loopback(struct cphy *cphy, int on) +{ + return (0); +} + +/* To check the activity LED */ +static int my3126_get_link_status(struct cphy *cphy, + int *link_ok, int *speed, int *duplex, int *fc) +{ + u32 val; + u16 val16; + adapter_t *adapter; + + adapter = cphy->adapter; + mdio_read(cphy, 0x1, 0x1, &val); + val16 = (u16) val; + + /* Populate elmer_gpo with the register value */ + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + cphy->elmer_gpo = val; + + *link_ok = (val16 & BMSR_LSTATUS); + + if (*link_ok) { + /* Turn on the LED. */ + if (is_T2(adapter)) + val &= ~(1 << 8); + else if (t1_is_T1B(adapter)) + val &= ~(1 << 19); + } else { + /* Turn off the LED. */ + if (is_T2(adapter)) + val |= (1 << 8); + else if (t1_is_T1B(adapter)) + val |= (1 << 19); + } + + t1_tpi_write(adapter, A_ELMER0_GPO, val); + cphy->elmer_gpo = val; + *speed = SPEED_10000; + *duplex = DUPLEX_FULL; + + /* need to add flow control */ + if (fc) + *fc = PAUSE_RX | PAUSE_TX; + + return (0); +} + +static void my3126_destroy(struct cphy *cphy) +{ + kfree(cphy); +} + +static struct cphy_ops my3126_ops = { + .destroy = my3126_destroy, + .reset = my3126_reset, + .interrupt_enable = my3126_interrupt_enable, + .interrupt_disable = my3126_interrupt_disable, + .interrupt_clear = my3126_interrupt_clear, + .interrupt_handler = my3126_interrupt_handler, + .get_link_status = my3126_get_link_status, + .set_loopback = my3126_set_loopback, +}; + +static struct cphy *my3126_phy_create(adapter_t *adapter, + int phy_addr, struct mdio_ops *mdio_ops) +{ + struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL); + + if (cphy) + cphy_init(cphy, adapter, phy_addr, &my3126_ops, mdio_ops); + + INIT_WORK(&cphy->phy_update, my3216_poll, cphy); + cphy->bmsr = 0; + + return (cphy); +} + +/* Chip Reset */ +static int my3126_phy_reset(adapter_t * adapter) +{ + u32 val; + + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~4; + t1_tpi_write(adapter, A_ELMER0_GPO, val); + msleep(100); + + t1_tpi_write(adapter, A_ELMER0_GPO, val | 4); + msleep(1000); + + /* Now lets enable the Laser. Delay 100us */ + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val |= 0x8000; + t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(100); + return (0); +} + +struct gphy t1_my3126_ops = { + my3126_phy_create, + my3126_phy_reset +}; diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index 50983f9ce4bc..b943f5ddd8fd 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -88,6 +88,8 @@ enum { /* RMON registers */ RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW, RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW, RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW, + RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW, + RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW, TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW, TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW, @@ -95,7 +97,9 @@ enum { /* RMON registers */ TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW, TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW, TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW, - TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW + TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW, + TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW, + TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW }; struct _cmac_instance { @@ -265,6 +269,8 @@ static int pm3393_interrupt_handler(struct cmac *cmac) /* Read the master interrupt status register. */ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &master_intr_status); + CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n", + master_intr_status); /* TBD XXX Lets just clear everything for now */ pm3393_interrupt_clear(cmac); @@ -307,11 +313,7 @@ static int pm3393_enable_port(struct cmac *cmac, int which) * The PHY doesn't give us link status indication on its own so have * the link management code query it instead. */ - { - extern void link_changed(adapter_t *adapter, int port_id); - - link_changed(cmac->adapter, 0); - } + t1_link_changed(cmac->adapter, 0); return 0; } @@ -519,6 +521,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, RMON_UPDATE(mac, RxJabbers, RxJabberErrors); RMON_UPDATE(mac, RxFragments, RxRuntErrors); RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors); + RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK); + RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK); /* Tx stats */ RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK); @@ -529,6 +533,8 @@ static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK); RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK); RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames); + RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK); + RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK); return &mac->stats; } @@ -814,6 +820,12 @@ static int pm3393_mac_reset(adapter_t * adapter) successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock && is_xaui_mabc_pll_locked); + + CH_DBG(adapter, HW, + "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, " + "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n", + i, is_pl4_reset_finished, val, is_pl4_outof_lock, + is_xaui_mabc_pll_locked); } return successful_reset ? 0 : 1; } diff --git a/drivers/net/chelsio/regs.h b/drivers/net/chelsio/regs.h index b90e11f40d1f..c80bf4d6d0a6 100644 --- a/drivers/net/chelsio/regs.h +++ b/drivers/net/chelsio/regs.h @@ -71,6 +71,10 @@ #define V_CMDQ_PRIORITY(x) ((x) << S_CMDQ_PRIORITY) #define G_CMDQ_PRIORITY(x) (((x) >> S_CMDQ_PRIORITY) & M_CMDQ_PRIORITY) +#define S_DISABLE_CMDQ0_GTS 8 +#define V_DISABLE_CMDQ0_GTS(x) ((x) << S_DISABLE_CMDQ0_GTS) +#define F_DISABLE_CMDQ0_GTS V_DISABLE_CMDQ0_GTS(1U) + #define S_DISABLE_CMDQ1_GTS 9 #define V_DISABLE_CMDQ1_GTS(x) ((x) << S_DISABLE_CMDQ1_GTS) #define F_DISABLE_CMDQ1_GTS V_DISABLE_CMDQ1_GTS(1U) @@ -87,12 +91,18 @@ #define V_ENABLE_BIG_ENDIAN(x) ((x) << S_ENABLE_BIG_ENDIAN) #define F_ENABLE_BIG_ENDIAN V_ENABLE_BIG_ENDIAN(1U) +#define S_FL_SELECTION_CRITERIA 13 +#define V_FL_SELECTION_CRITERIA(x) ((x) << S_FL_SELECTION_CRITERIA) +#define F_FL_SELECTION_CRITERIA V_FL_SELECTION_CRITERIA(1U) + #define S_ISCSI_COALESCE 14 #define V_ISCSI_COALESCE(x) ((x) << S_ISCSI_COALESCE) #define F_ISCSI_COALESCE V_ISCSI_COALESCE(1U) #define S_RX_PKT_OFFSET 15 +#define M_RX_PKT_OFFSET 0x7 #define V_RX_PKT_OFFSET(x) ((x) << S_RX_PKT_OFFSET) +#define G_RX_PKT_OFFSET(x) (((x) >> S_RX_PKT_OFFSET) & M_RX_PKT_OFFSET) #define S_VLAN_XTRACT 18 #define V_VLAN_XTRACT(x) ((x) << S_VLAN_XTRACT) @@ -108,16 +118,114 @@ #define A_SG_FL1BASELWR 0x20 #define A_SG_FL1BASEUPR 0x24 #define A_SG_CMD0SIZE 0x28 + +#define S_CMDQ0_SIZE 0 +#define M_CMDQ0_SIZE 0x1ffff +#define V_CMDQ0_SIZE(x) ((x) << S_CMDQ0_SIZE) +#define G_CMDQ0_SIZE(x) (((x) >> S_CMDQ0_SIZE) & M_CMDQ0_SIZE) + #define A_SG_FL0SIZE 0x2c + +#define S_FL0_SIZE 0 +#define M_FL0_SIZE 0x1ffff +#define V_FL0_SIZE(x) ((x) << S_FL0_SIZE) +#define G_FL0_SIZE(x) (((x) >> S_FL0_SIZE) & M_FL0_SIZE) + #define A_SG_RSPSIZE 0x30 + +#define S_RESPQ_SIZE 0 +#define M_RESPQ_SIZE 0x1ffff +#define V_RESPQ_SIZE(x) ((x) << S_RESPQ_SIZE) +#define G_RESPQ_SIZE(x) (((x) >> S_RESPQ_SIZE) & M_RESPQ_SIZE) + #define A_SG_RSPBASELWR 0x34 #define A_SG_RSPBASEUPR 0x38 #define A_SG_FLTHRESHOLD 0x3c + +#define S_FL_THRESHOLD 0 +#define M_FL_THRESHOLD 0xffff +#define V_FL_THRESHOLD(x) ((x) << S_FL_THRESHOLD) +#define G_FL_THRESHOLD(x) (((x) >> S_FL_THRESHOLD) & M_FL_THRESHOLD) + #define A_SG_RSPQUEUECREDIT 0x40 + +#define S_RESPQ_CREDIT 0 +#define M_RESPQ_CREDIT 0x1ffff +#define V_RESPQ_CREDIT(x) ((x) << S_RESPQ_CREDIT) +#define G_RESPQ_CREDIT(x) (((x) >> S_RESPQ_CREDIT) & M_RESPQ_CREDIT) + #define A_SG_SLEEPING 0x48 + +#define S_SLEEPING 0 +#define M_SLEEPING 0xffff +#define V_SLEEPING(x) ((x) << S_SLEEPING) +#define G_SLEEPING(x) (((x) >> S_SLEEPING) & M_SLEEPING) + #define A_SG_INTRTIMER 0x4c + +#define S_INTERRUPT_TIMER_COUNT 0 +#define M_INTERRUPT_TIMER_COUNT 0xffffff +#define V_INTERRUPT_TIMER_COUNT(x) ((x) << S_INTERRUPT_TIMER_COUNT) +#define G_INTERRUPT_TIMER_COUNT(x) (((x) >> S_INTERRUPT_TIMER_COUNT) & M_INTERRUPT_TIMER_COUNT) + +#define A_SG_CMD0PTR 0x50 + +#define S_CMDQ0_POINTER 0 +#define M_CMDQ0_POINTER 0xffff +#define V_CMDQ0_POINTER(x) ((x) << S_CMDQ0_POINTER) +#define G_CMDQ0_POINTER(x) (((x) >> S_CMDQ0_POINTER) & M_CMDQ0_POINTER) + +#define S_CURRENT_GENERATION_BIT 16 +#define V_CURRENT_GENERATION_BIT(x) ((x) << S_CURRENT_GENERATION_BIT) +#define F_CURRENT_GENERATION_BIT V_CURRENT_GENERATION_BIT(1U) + +#define A_SG_CMD1PTR 0x54 + +#define S_CMDQ1_POINTER 0 +#define M_CMDQ1_POINTER 0xffff +#define V_CMDQ1_POINTER(x) ((x) << S_CMDQ1_POINTER) +#define G_CMDQ1_POINTER(x) (((x) >> S_CMDQ1_POINTER) & M_CMDQ1_POINTER) + +#define A_SG_FL0PTR 0x58 + +#define S_FL0_POINTER 0 +#define M_FL0_POINTER 0xffff +#define V_FL0_POINTER(x) ((x) << S_FL0_POINTER) +#define G_FL0_POINTER(x) (((x) >> S_FL0_POINTER) & M_FL0_POINTER) + +#define A_SG_FL1PTR 0x5c + +#define S_FL1_POINTER 0 +#define M_FL1_POINTER 0xffff +#define V_FL1_POINTER(x) ((x) << S_FL1_POINTER) +#define G_FL1_POINTER(x) (((x) >> S_FL1_POINTER) & M_FL1_POINTER) + +#define A_SG_VERSION 0x6c + +#define S_DAY 0 +#define M_DAY 0x1f +#define V_DAY(x) ((x) << S_DAY) +#define G_DAY(x) (((x) >> S_DAY) & M_DAY) + +#define S_MONTH 5 +#define M_MONTH 0xf +#define V_MONTH(x) ((x) << S_MONTH) +#define G_MONTH(x) (((x) >> S_MONTH) & M_MONTH) + #define A_SG_CMD1SIZE 0xb0 + +#define S_CMDQ1_SIZE 0 +#define M_CMDQ1_SIZE 0x1ffff +#define V_CMDQ1_SIZE(x) ((x) << S_CMDQ1_SIZE) +#define G_CMDQ1_SIZE(x) (((x) >> S_CMDQ1_SIZE) & M_CMDQ1_SIZE) + #define A_SG_FL1SIZE 0xb4 + +#define S_FL1_SIZE 0 +#define M_FL1_SIZE 0x1ffff +#define V_FL1_SIZE(x) ((x) << S_FL1_SIZE) +#define G_FL1_SIZE(x) (((x) >> S_FL1_SIZE) & M_FL1_SIZE) + #define A_SG_INT_ENABLE 0xb8 #define S_RESPQ_EXHAUSTED 0 @@ -144,21 +252,369 @@ #define A_SG_RESPACCUTIMER 0xc0 /* MC3 registers */ +#define A_MC3_CFG 0x100 + +#define S_CLK_ENABLE 0 +#define V_CLK_ENABLE(x) ((x) << S_CLK_ENABLE) +#define F_CLK_ENABLE V_CLK_ENABLE(1U) #define S_READY 1 #define V_READY(x) ((x) << S_READY) #define F_READY V_READY(1U) -/* MC4 registers */ +#define S_READ_TO_WRITE_DELAY 2 +#define M_READ_TO_WRITE_DELAY 0x7 +#define V_READ_TO_WRITE_DELAY(x) ((x) << S_READ_TO_WRITE_DELAY) +#define G_READ_TO_WRITE_DELAY(x) (((x) >> S_READ_TO_WRITE_DELAY) & M_READ_TO_WRITE_DELAY) + +#define S_WRITE_TO_READ_DELAY 5 +#define M_WRITE_TO_READ_DELAY 0x7 +#define V_WRITE_TO_READ_DELAY(x) ((x) << S_WRITE_TO_READ_DELAY) +#define G_WRITE_TO_READ_DELAY(x) (((x) >> S_WRITE_TO_READ_DELAY) & M_WRITE_TO_READ_DELAY) +#define S_MC3_BANK_CYCLE 8 +#define M_MC3_BANK_CYCLE 0xf +#define V_MC3_BANK_CYCLE(x) ((x) << S_MC3_BANK_CYCLE) +#define G_MC3_BANK_CYCLE(x) (((x) >> S_MC3_BANK_CYCLE) & M_MC3_BANK_CYCLE) + +#define S_REFRESH_CYCLE 12 +#define M_REFRESH_CYCLE 0xf +#define V_REFRESH_CYCLE(x) ((x) << S_REFRESH_CYCLE) +#define G_REFRESH_CYCLE(x) (((x) >> S_REFRESH_CYCLE) & M_REFRESH_CYCLE) + +#define S_PRECHARGE_CYCLE 16 +#define M_PRECHARGE_CYCLE 0x3 +#define V_PRECHARGE_CYCLE(x) ((x) << S_PRECHARGE_CYCLE) +#define G_PRECHARGE_CYCLE(x) (((x) >> S_PRECHARGE_CYCLE) & M_PRECHARGE_CYCLE) + +#define S_ACTIVE_TO_READ_WRITE_DELAY 18 +#define V_ACTIVE_TO_READ_WRITE_DELAY(x) ((x) << S_ACTIVE_TO_READ_WRITE_DELAY) +#define F_ACTIVE_TO_READ_WRITE_DELAY V_ACTIVE_TO_READ_WRITE_DELAY(1U) + +#define S_ACTIVE_TO_PRECHARGE_DELAY 19 +#define M_ACTIVE_TO_PRECHARGE_DELAY 0x7 +#define V_ACTIVE_TO_PRECHARGE_DELAY(x) ((x) << S_ACTIVE_TO_PRECHARGE_DELAY) +#define G_ACTIVE_TO_PRECHARGE_DELAY(x) (((x) >> S_ACTIVE_TO_PRECHARGE_DELAY) & M_ACTIVE_TO_PRECHARGE_DELAY) + +#define S_WRITE_RECOVERY_DELAY 22 +#define M_WRITE_RECOVERY_DELAY 0x3 +#define V_WRITE_RECOVERY_DELAY(x) ((x) << S_WRITE_RECOVERY_DELAY) +#define G_WRITE_RECOVERY_DELAY(x) (((x) >> S_WRITE_RECOVERY_DELAY) & M_WRITE_RECOVERY_DELAY) + +#define S_DENSITY 24 +#define M_DENSITY 0x3 +#define V_DENSITY(x) ((x) << S_DENSITY) +#define G_DENSITY(x) (((x) >> S_DENSITY) & M_DENSITY) + +#define S_ORGANIZATION 26 +#define V_ORGANIZATION(x) ((x) << S_ORGANIZATION) +#define F_ORGANIZATION V_ORGANIZATION(1U) + +#define S_BANKS 27 +#define V_BANKS(x) ((x) << S_BANKS) +#define F_BANKS V_BANKS(1U) + +#define S_UNREGISTERED 28 +#define V_UNREGISTERED(x) ((x) << S_UNREGISTERED) +#define F_UNREGISTERED V_UNREGISTERED(1U) + +#define S_MC3_WIDTH 29 +#define M_MC3_WIDTH 0x3 +#define V_MC3_WIDTH(x) ((x) << S_MC3_WIDTH) +#define G_MC3_WIDTH(x) (((x) >> S_MC3_WIDTH) & M_MC3_WIDTH) + +#define S_MC3_SLOW 31 +#define V_MC3_SLOW(x) ((x) << S_MC3_SLOW) +#define F_MC3_SLOW V_MC3_SLOW(1U) + +#define A_MC3_MODE 0x104 + +#define S_MC3_MODE 0 +#define M_MC3_MODE 0x3fff +#define V_MC3_MODE(x) ((x) << S_MC3_MODE) +#define G_MC3_MODE(x) (((x) >> S_MC3_MODE) & M_MC3_MODE) + +#define S_BUSY 31 +#define V_BUSY(x) ((x) << S_BUSY) +#define F_BUSY V_BUSY(1U) + +#define A_MC3_EXT_MODE 0x108 + +#define S_MC3_EXTENDED_MODE 0 +#define M_MC3_EXTENDED_MODE 0x3fff +#define V_MC3_EXTENDED_MODE(x) ((x) << S_MC3_EXTENDED_MODE) +#define G_MC3_EXTENDED_MODE(x) (((x) >> S_MC3_EXTENDED_MODE) & M_MC3_EXTENDED_MODE) + +#define A_MC3_PRECHARG 0x10c +#define A_MC3_REFRESH 0x110 + +#define S_REFRESH_ENABLE 0 +#define V_REFRESH_ENABLE(x) ((x) << S_REFRESH_ENABLE) +#define F_REFRESH_ENABLE V_REFRESH_ENABLE(1U) + +#define S_REFRESH_DIVISOR 1 +#define M_REFRESH_DIVISOR 0x3fff +#define V_REFRESH_DIVISOR(x) ((x) << S_REFRESH_DIVISOR) +#define G_REFRESH_DIVISOR(x) (((x) >> S_REFRESH_DIVISOR) & M_REFRESH_DIVISOR) + +#define A_MC3_STROBE 0x114 + +#define S_MASTER_DLL_RESET 0 +#define V_MASTER_DLL_RESET(x) ((x) << S_MASTER_DLL_RESET) +#define F_MASTER_DLL_RESET V_MASTER_DLL_RESET(1U) + +#define S_MASTER_DLL_TAP_COUNT 1 +#define M_MASTER_DLL_TAP_COUNT 0xff +#define V_MASTER_DLL_TAP_COUNT(x) ((x) << S_MASTER_DLL_TAP_COUNT) +#define G_MASTER_DLL_TAP_COUNT(x) (((x) >> S_MASTER_DLL_TAP_COUNT) & M_MASTER_DLL_TAP_COUNT) + +#define S_MASTER_DLL_LOCKED 9 +#define V_MASTER_DLL_LOCKED(x) ((x) << S_MASTER_DLL_LOCKED) +#define F_MASTER_DLL_LOCKED V_MASTER_DLL_LOCKED(1U) + +#define S_MASTER_DLL_MAX_TAP_COUNT 10 +#define V_MASTER_DLL_MAX_TAP_COUNT(x) ((x) << S_MASTER_DLL_MAX_TAP_COUNT) +#define F_MASTER_DLL_MAX_TAP_COUNT V_MASTER_DLL_MAX_TAP_COUNT(1U) + +#define S_MASTER_DLL_TAP_COUNT_OFFSET 11 +#define M_MASTER_DLL_TAP_COUNT_OFFSET 0x3f +#define V_MASTER_DLL_TAP_COUNT_OFFSET(x) ((x) << S_MASTER_DLL_TAP_COUNT_OFFSET) +#define G_MASTER_DLL_TAP_COUNT_OFFSET(x) (((x) >> S_MASTER_DLL_TAP_COUNT_OFFSET) & M_MASTER_DLL_TAP_COUNT_OFFSET) + +#define S_SLAVE_DLL_RESET 11 +#define V_SLAVE_DLL_RESET(x) ((x) << S_SLAVE_DLL_RESET) +#define F_SLAVE_DLL_RESET V_SLAVE_DLL_RESET(1U) + +#define S_SLAVE_DLL_DELTA 12 +#define M_SLAVE_DLL_DELTA 0xf +#define V_SLAVE_DLL_DELTA(x) ((x) << S_SLAVE_DLL_DELTA) +#define G_SLAVE_DLL_DELTA(x) (((x) >> S_SLAVE_DLL_DELTA) & M_SLAVE_DLL_DELTA) + +#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT 17 +#define M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT 0x3f +#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT) +#define G_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT) & M_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT) + +#define S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE 23 +#define V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(x) ((x) << S_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE) +#define F_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE V_SLAVE_DELAY_LINE_MANUAL_TAP_COUNT_ENABLE(1U) + +#define S_SLAVE_DELAY_LINE_TAP_COUNT 24 +#define M_SLAVE_DELAY_LINE_TAP_COUNT 0x3f +#define V_SLAVE_DELAY_LINE_TAP_COUNT(x) ((x) << S_SLAVE_DELAY_LINE_TAP_COUNT) +#define G_SLAVE_DELAY_LINE_TAP_COUNT(x) (((x) >> S_SLAVE_DELAY_LINE_TAP_COUNT) & M_SLAVE_DELAY_LINE_TAP_COUNT) + +#define A_MC3_ECC_CNTL 0x118 + +#define S_ECC_GENERATION_ENABLE 0 +#define V_ECC_GENERATION_ENABLE(x) ((x) << S_ECC_GENERATION_ENABLE) +#define F_ECC_GENERATION_ENABLE V_ECC_GENERATION_ENABLE(1U) + +#define S_ECC_CHECK_ENABLE 1 +#define V_ECC_CHECK_ENABLE(x) ((x) << S_ECC_CHECK_ENABLE) +#define F_ECC_CHECK_ENABLE V_ECC_CHECK_ENABLE(1U) + +#define S_CORRECTABLE_ERROR_COUNT 2 +#define M_CORRECTABLE_ERROR_COUNT 0xff +#define V_CORRECTABLE_ERROR_COUNT(x) ((x) << S_CORRECTABLE_ERROR_COUNT) +#define G_CORRECTABLE_ERROR_COUNT(x) (((x) >> S_CORRECTABLE_ERROR_COUNT) & M_CORRECTABLE_ERROR_COUNT) + +#define S_UNCORRECTABLE_ERROR_COUNT 10 +#define M_UNCORRECTABLE_ERROR_COUNT 0xff +#define V_UNCORRECTABLE_ERROR_COUNT(x) ((x) << S_UNCORRECTABLE_ERROR_COUNT) +#define G_UNCORRECTABLE_ERROR_COUNT(x) (((x) >> S_UNCORRECTABLE_ERROR_COUNT) & M_UNCORRECTABLE_ERROR_COUNT) + +#define A_MC3_CE_ADDR 0x11c + +#define S_MC3_CE_ADDR 4 +#define M_MC3_CE_ADDR 0xfffffff +#define V_MC3_CE_ADDR(x) ((x) << S_MC3_CE_ADDR) +#define G_MC3_CE_ADDR(x) (((x) >> S_MC3_CE_ADDR) & M_MC3_CE_ADDR) + +#define A_MC3_CE_DATA0 0x120 +#define A_MC3_CE_DATA1 0x124 +#define A_MC3_CE_DATA2 0x128 +#define A_MC3_CE_DATA3 0x12c +#define A_MC3_CE_DATA4 0x130 +#define A_MC3_UE_ADDR 0x134 + +#define S_MC3_UE_ADDR 4 +#define M_MC3_UE_ADDR 0xfffffff +#define V_MC3_UE_ADDR(x) ((x) << S_MC3_UE_ADDR) +#define G_MC3_UE_ADDR(x) (((x) >> S_MC3_UE_ADDR) & M_MC3_UE_ADDR) + +#define A_MC3_UE_DATA0 0x138 +#define A_MC3_UE_DATA1 0x13c +#define A_MC3_UE_DATA2 0x140 +#define A_MC3_UE_DATA3 0x144 +#define A_MC3_UE_DATA4 0x148 +#define A_MC3_BD_ADDR 0x14c +#define A_MC3_BD_DATA0 0x150 +#define A_MC3_BD_DATA1 0x154 +#define A_MC3_BD_DATA2 0x158 +#define A_MC3_BD_DATA3 0x15c +#define A_MC3_BD_DATA4 0x160 +#define A_MC3_BD_OP 0x164 + +#define S_BACK_DOOR_OPERATION 0 +#define V_BACK_DOOR_OPERATION(x) ((x) << S_BACK_DOOR_OPERATION) +#define F_BACK_DOOR_OPERATION V_BACK_DOOR_OPERATION(1U) + +#define A_MC3_BIST_ADDR_BEG 0x168 +#define A_MC3_BIST_ADDR_END 0x16c +#define A_MC3_BIST_DATA 0x170 +#define A_MC3_BIST_OP 0x174 + +#define S_OP 0 +#define V_OP(x) ((x) << S_OP) +#define F_OP V_OP(1U) + +#define S_DATA_PATTERN 1 +#define M_DATA_PATTERN 0x3 +#define V_DATA_PATTERN(x) ((x) << S_DATA_PATTERN) +#define G_DATA_PATTERN(x) (((x) >> S_DATA_PATTERN) & M_DATA_PATTERN) + +#define S_CONTINUOUS 3 +#define V_CONTINUOUS(x) ((x) << S_CONTINUOUS) +#define F_CONTINUOUS V_CONTINUOUS(1U) + +#define A_MC3_INT_ENABLE 0x178 + +#define S_MC3_CORR_ERR 0 +#define V_MC3_CORR_ERR(x) ((x) << S_MC3_CORR_ERR) +#define F_MC3_CORR_ERR V_MC3_CORR_ERR(1U) + +#define S_MC3_UNCORR_ERR 1 +#define V_MC3_UNCORR_ERR(x) ((x) << S_MC3_UNCORR_ERR) +#define F_MC3_UNCORR_ERR V_MC3_UNCORR_ERR(1U) + +#define S_MC3_PARITY_ERR 2 +#define M_MC3_PARITY_ERR 0xff +#define V_MC3_PARITY_ERR(x) ((x) << S_MC3_PARITY_ERR) +#define G_MC3_PARITY_ERR(x) (((x) >> S_MC3_PARITY_ERR) & M_MC3_PARITY_ERR) + +#define S_MC3_ADDR_ERR 10 +#define V_MC3_ADDR_ERR(x) ((x) << S_MC3_ADDR_ERR) +#define F_MC3_ADDR_ERR V_MC3_ADDR_ERR(1U) + +#define A_MC3_INT_CAUSE 0x17c + +/* MC4 registers */ #define A_MC4_CFG 0x180 + +#define S_POWER_UP 0 +#define V_POWER_UP(x) ((x) << S_POWER_UP) +#define F_POWER_UP V_POWER_UP(1U) + +#define S_MC4_BANK_CYCLE 8 +#define M_MC4_BANK_CYCLE 0x7 +#define V_MC4_BANK_CYCLE(x) ((x) << S_MC4_BANK_CYCLE) +#define G_MC4_BANK_CYCLE(x) (((x) >> S_MC4_BANK_CYCLE) & M_MC4_BANK_CYCLE) + +#define S_MC4_NARROW 24 +#define V_MC4_NARROW(x) ((x) << S_MC4_NARROW) +#define F_MC4_NARROW V_MC4_NARROW(1U) + #define S_MC4_SLOW 25 #define V_MC4_SLOW(x) ((x) << S_MC4_SLOW) #define F_MC4_SLOW V_MC4_SLOW(1U) -/* TPI registers */ +#define S_MC4A_WIDTH 24 +#define M_MC4A_WIDTH 0x3 +#define V_MC4A_WIDTH(x) ((x) << S_MC4A_WIDTH) +#define G_MC4A_WIDTH(x) (((x) >> S_MC4A_WIDTH) & M_MC4A_WIDTH) + +#define S_MC4A_SLOW 26 +#define V_MC4A_SLOW(x) ((x) << S_MC4A_SLOW) +#define F_MC4A_SLOW V_MC4A_SLOW(1U) + +#define A_MC4_MODE 0x184 + +#define S_MC4_MODE 0 +#define M_MC4_MODE 0x7fff +#define V_MC4_MODE(x) ((x) << S_MC4_MODE) +#define G_MC4_MODE(x) (((x) >> S_MC4_MODE) & M_MC4_MODE) + +#define A_MC4_EXT_MODE 0x188 + +#define S_MC4_EXTENDED_MODE 0 +#define M_MC4_EXTENDED_MODE 0x7fff +#define V_MC4_EXTENDED_MODE(x) ((x) << S_MC4_EXTENDED_MODE) +#define G_MC4_EXTENDED_MODE(x) (((x) >> S_MC4_EXTENDED_MODE) & M_MC4_EXTENDED_MODE) + +#define A_MC4_REFRESH 0x190 +#define A_MC4_STROBE 0x194 +#define A_MC4_ECC_CNTL 0x198 +#define A_MC4_CE_ADDR 0x19c + +#define S_MC4_CE_ADDR 4 +#define M_MC4_CE_ADDR 0xffffff +#define V_MC4_CE_ADDR(x) ((x) << S_MC4_CE_ADDR) +#define G_MC4_CE_ADDR(x) (((x) >> S_MC4_CE_ADDR) & M_MC4_CE_ADDR) + +#define A_MC4_CE_DATA0 0x1a0 +#define A_MC4_CE_DATA1 0x1a4 +#define A_MC4_CE_DATA2 0x1a8 +#define A_MC4_CE_DATA3 0x1ac +#define A_MC4_CE_DATA4 0x1b0 +#define A_MC4_UE_ADDR 0x1b4 + +#define S_MC4_UE_ADDR 4 +#define M_MC4_UE_ADDR 0xffffff +#define V_MC4_UE_ADDR(x) ((x) << S_MC4_UE_ADDR) +#define G_MC4_UE_ADDR(x) (((x) >> S_MC4_UE_ADDR) & M_MC4_UE_ADDR) + +#define A_MC4_UE_DATA0 0x1b8 +#define A_MC4_UE_DATA1 0x1bc +#define A_MC4_UE_DATA2 0x1c0 +#define A_MC4_UE_DATA3 0x1c4 +#define A_MC4_UE_DATA4 0x1c8 +#define A_MC4_BD_ADDR 0x1cc + +#define S_MC4_BACK_DOOR_ADDR 0 +#define M_MC4_BACK_DOOR_ADDR 0xfffffff +#define V_MC4_BACK_DOOR_ADDR(x) ((x) << S_MC4_BACK_DOOR_ADDR) +#define G_MC4_BACK_DOOR_ADDR(x) (((x) >> S_MC4_BACK_DOOR_ADDR) & M_MC4_BACK_DOOR_ADDR) + +#define A_MC4_BD_DATA0 0x1d0 +#define A_MC4_BD_DATA1 0x1d4 +#define A_MC4_BD_DATA2 0x1d8 +#define A_MC4_BD_DATA3 0x1dc +#define A_MC4_BD_DATA4 0x1e0 +#define A_MC4_BD_OP 0x1e4 + +#define S_OPERATION 0 +#define V_OPERATION(x) ((x) << S_OPERATION) +#define F_OPERATION V_OPERATION(1U) + +#define A_MC4_BIST_ADDR_BEG 0x1e8 +#define A_MC4_BIST_ADDR_END 0x1ec +#define A_MC4_BIST_DATA 0x1f0 +#define A_MC4_BIST_OP 0x1f4 +#define A_MC4_INT_ENABLE 0x1f8 + +#define S_MC4_CORR_ERR 0 +#define V_MC4_CORR_ERR(x) ((x) << S_MC4_CORR_ERR) +#define F_MC4_CORR_ERR V_MC4_CORR_ERR(1U) + +#define S_MC4_UNCORR_ERR 1 +#define V_MC4_UNCORR_ERR(x) ((x) << S_MC4_UNCORR_ERR) +#define F_MC4_UNCORR_ERR V_MC4_UNCORR_ERR(1U) + +#define S_MC4_ADDR_ERR 2 +#define V_MC4_ADDR_ERR(x) ((x) << S_MC4_ADDR_ERR) +#define F_MC4_ADDR_ERR V_MC4_ADDR_ERR(1U) + +#define A_MC4_INT_CAUSE 0x1fc +/* TPI registers */ #define A_TPI_ADDR 0x280 + +#define S_TPI_ADDRESS 0 +#define M_TPI_ADDRESS 0xffffff +#define V_TPI_ADDRESS(x) ((x) << S_TPI_ADDRESS) +#define G_TPI_ADDRESS(x) (((x) >> S_TPI_ADDRESS) & M_TPI_ADDRESS) + #define A_TPI_WR_DATA 0x284 #define A_TPI_RD_DATA 0x288 #define A_TPI_CSR 0x28c @@ -171,6 +627,10 @@ #define V_TPIRDY(x) ((x) << S_TPIRDY) #define F_TPIRDY V_TPIRDY(1U) +#define S_INT_DIR 31 +#define V_INT_DIR(x) ((x) << S_INT_DIR) +#define F_INT_DIR V_INT_DIR(1U) + #define A_TPI_PAR 0x29c #define S_TPIPAR 0 @@ -178,14 +638,26 @@ #define V_TPIPAR(x) ((x) << S_TPIPAR) #define G_TPIPAR(x) (((x) >> S_TPIPAR) & M_TPIPAR) -/* TP registers */ +/* TP registers */ #define A_TP_IN_CONFIG 0x300 +#define S_TP_IN_CSPI_TUNNEL 0 +#define V_TP_IN_CSPI_TUNNEL(x) ((x) << S_TP_IN_CSPI_TUNNEL) +#define F_TP_IN_CSPI_TUNNEL V_TP_IN_CSPI_TUNNEL(1U) + +#define S_TP_IN_CSPI_ETHERNET 1 +#define V_TP_IN_CSPI_ETHERNET(x) ((x) << S_TP_IN_CSPI_ETHERNET) +#define F_TP_IN_CSPI_ETHERNET V_TP_IN_CSPI_ETHERNET(1U) + #define S_TP_IN_CSPI_CPL 3 #define V_TP_IN_CSPI_CPL(x) ((x) << S_TP_IN_CSPI_CPL) #define F_TP_IN_CSPI_CPL V_TP_IN_CSPI_CPL(1U) +#define S_TP_IN_CSPI_POS 4 +#define V_TP_IN_CSPI_POS(x) ((x) << S_TP_IN_CSPI_POS) +#define F_TP_IN_CSPI_POS V_TP_IN_CSPI_POS(1U) + #define S_TP_IN_CSPI_CHECK_IP_CSUM 5 #define V_TP_IN_CSPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_IP_CSUM) #define F_TP_IN_CSPI_CHECK_IP_CSUM V_TP_IN_CSPI_CHECK_IP_CSUM(1U) @@ -194,10 +666,22 @@ #define V_TP_IN_CSPI_CHECK_TCP_CSUM(x) ((x) << S_TP_IN_CSPI_CHECK_TCP_CSUM) #define F_TP_IN_CSPI_CHECK_TCP_CSUM V_TP_IN_CSPI_CHECK_TCP_CSUM(1U) +#define S_TP_IN_ESPI_TUNNEL 7 +#define V_TP_IN_ESPI_TUNNEL(x) ((x) << S_TP_IN_ESPI_TUNNEL) +#define F_TP_IN_ESPI_TUNNEL V_TP_IN_ESPI_TUNNEL(1U) + #define S_TP_IN_ESPI_ETHERNET 8 #define V_TP_IN_ESPI_ETHERNET(x) ((x) << S_TP_IN_ESPI_ETHERNET) #define F_TP_IN_ESPI_ETHERNET V_TP_IN_ESPI_ETHERNET(1U) +#define S_TP_IN_ESPI_CPL 10 +#define V_TP_IN_ESPI_CPL(x) ((x) << S_TP_IN_ESPI_CPL) +#define F_TP_IN_ESPI_CPL V_TP_IN_ESPI_CPL(1U) + +#define S_TP_IN_ESPI_POS 11 +#define V_TP_IN_ESPI_POS(x) ((x) << S_TP_IN_ESPI_POS) +#define F_TP_IN_ESPI_POS V_TP_IN_ESPI_POS(1U) + #define S_TP_IN_ESPI_CHECK_IP_CSUM 12 #define V_TP_IN_ESPI_CHECK_IP_CSUM(x) ((x) << S_TP_IN_ESPI_CHECK_IP_CSUM) #define F_TP_IN_ESPI_CHECK_IP_CSUM V_TP_IN_ESPI_CHECK_IP_CSUM(1U) @@ -212,14 +696,42 @@ #define A_TP_OUT_CONFIG 0x304 +#define S_TP_OUT_C_ETH 0 +#define V_TP_OUT_C_ETH(x) ((x) << S_TP_OUT_C_ETH) +#define F_TP_OUT_C_ETH V_TP_OUT_C_ETH(1U) + #define S_TP_OUT_CSPI_CPL 2 #define V_TP_OUT_CSPI_CPL(x) ((x) << S_TP_OUT_CSPI_CPL) #define F_TP_OUT_CSPI_CPL V_TP_OUT_CSPI_CPL(1U) +#define S_TP_OUT_CSPI_POS 3 +#define V_TP_OUT_CSPI_POS(x) ((x) << S_TP_OUT_CSPI_POS) +#define F_TP_OUT_CSPI_POS V_TP_OUT_CSPI_POS(1U) + +#define S_TP_OUT_CSPI_GENERATE_IP_CSUM 4 +#define V_TP_OUT_CSPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_IP_CSUM) +#define F_TP_OUT_CSPI_GENERATE_IP_CSUM V_TP_OUT_CSPI_GENERATE_IP_CSUM(1U) + +#define S_TP_OUT_CSPI_GENERATE_TCP_CSUM 5 +#define V_TP_OUT_CSPI_GENERATE_TCP_CSUM(x) ((x) << S_TP_OUT_CSPI_GENERATE_TCP_CSUM) +#define F_TP_OUT_CSPI_GENERATE_TCP_CSUM V_TP_OUT_CSPI_GENERATE_TCP_CSUM(1U) + #define S_TP_OUT_ESPI_ETHERNET 6 #define V_TP_OUT_ESPI_ETHERNET(x) ((x) << S_TP_OUT_ESPI_ETHERNET) #define F_TP_OUT_ESPI_ETHERNET V_TP_OUT_ESPI_ETHERNET(1U) +#define S_TP_OUT_ESPI_TAG_ETHERNET 7 +#define V_TP_OUT_ESPI_TAG_ETHERNET(x) ((x) << S_TP_OUT_ESPI_TAG_ETHERNET) +#define F_TP_OUT_ESPI_TAG_ETHERNET V_TP_OUT_ESPI_TAG_ETHERNET(1U) + +#define S_TP_OUT_ESPI_CPL 8 +#define V_TP_OUT_ESPI_CPL(x) ((x) << S_TP_OUT_ESPI_CPL) +#define F_TP_OUT_ESPI_CPL V_TP_OUT_ESPI_CPL(1U) + +#define S_TP_OUT_ESPI_POS 9 +#define V_TP_OUT_ESPI_POS(x) ((x) << S_TP_OUT_ESPI_POS) +#define F_TP_OUT_ESPI_POS V_TP_OUT_ESPI_POS(1U) + #define S_TP_OUT_ESPI_GENERATE_IP_CSUM 10 #define V_TP_OUT_ESPI_GENERATE_IP_CSUM(x) ((x) << S_TP_OUT_ESPI_GENERATE_IP_CSUM) #define F_TP_OUT_ESPI_GENERATE_IP_CSUM V_TP_OUT_ESPI_GENERATE_IP_CSUM(1U) @@ -233,6 +745,16 @@ #define S_IP_TTL 0 #define M_IP_TTL 0xff #define V_IP_TTL(x) ((x) << S_IP_TTL) +#define G_IP_TTL(x) (((x) >> S_IP_TTL) & M_IP_TTL) + +#define S_TCAM_SERVER_REGION_USAGE 8 +#define M_TCAM_SERVER_REGION_USAGE 0x3 +#define V_TCAM_SERVER_REGION_USAGE(x) ((x) << S_TCAM_SERVER_REGION_USAGE) +#define G_TCAM_SERVER_REGION_USAGE(x) (((x) >> S_TCAM_SERVER_REGION_USAGE) & M_TCAM_SERVER_REGION_USAGE) + +#define S_QOS_MAPPING 10 +#define V_QOS_MAPPING(x) ((x) << S_QOS_MAPPING) +#define F_QOS_MAPPING V_QOS_MAPPING(1U) #define S_TCP_CSUM 11 #define V_TCP_CSUM(x) ((x) << S_TCP_CSUM) @@ -246,31 +768,476 @@ #define V_IP_CSUM(x) ((x) << S_IP_CSUM) #define F_IP_CSUM V_IP_CSUM(1U) +#define S_IP_ID_SPLIT 14 +#define V_IP_ID_SPLIT(x) ((x) << S_IP_ID_SPLIT) +#define F_IP_ID_SPLIT V_IP_ID_SPLIT(1U) + #define S_PATH_MTU 15 #define V_PATH_MTU(x) ((x) << S_PATH_MTU) #define F_PATH_MTU V_PATH_MTU(1U) #define S_5TUPLE_LOOKUP 17 +#define M_5TUPLE_LOOKUP 0x3 #define V_5TUPLE_LOOKUP(x) ((x) << S_5TUPLE_LOOKUP) +#define G_5TUPLE_LOOKUP(x) (((x) >> S_5TUPLE_LOOKUP) & M_5TUPLE_LOOKUP) + +#define S_IP_FRAGMENT_DROP 19 +#define V_IP_FRAGMENT_DROP(x) ((x) << S_IP_FRAGMENT_DROP) +#define F_IP_FRAGMENT_DROP V_IP_FRAGMENT_DROP(1U) + +#define S_PING_DROP 20 +#define V_PING_DROP(x) ((x) << S_PING_DROP) +#define F_PING_DROP V_PING_DROP(1U) + +#define S_PROTECT_MODE 21 +#define V_PROTECT_MODE(x) ((x) << S_PROTECT_MODE) +#define F_PROTECT_MODE V_PROTECT_MODE(1U) + +#define S_SYN_COOKIE_ALGORITHM 22 +#define V_SYN_COOKIE_ALGORITHM(x) ((x) << S_SYN_COOKIE_ALGORITHM) +#define F_SYN_COOKIE_ALGORITHM V_SYN_COOKIE_ALGORITHM(1U) + +#define S_ATTACK_FILTER 23 +#define V_ATTACK_FILTER(x) ((x) << S_ATTACK_FILTER) +#define F_ATTACK_FILTER V_ATTACK_FILTER(1U) + +#define S_INTERFACE_TYPE 24 +#define V_INTERFACE_TYPE(x) ((x) << S_INTERFACE_TYPE) +#define F_INTERFACE_TYPE V_INTERFACE_TYPE(1U) + +#define S_DISABLE_RX_FLOW_CONTROL 25 +#define V_DISABLE_RX_FLOW_CONTROL(x) ((x) << S_DISABLE_RX_FLOW_CONTROL) +#define F_DISABLE_RX_FLOW_CONTROL V_DISABLE_RX_FLOW_CONTROL(1U) #define S_SYN_COOKIE_PARAMETER 26 +#define M_SYN_COOKIE_PARAMETER 0x3f #define V_SYN_COOKIE_PARAMETER(x) ((x) << S_SYN_COOKIE_PARAMETER) +#define G_SYN_COOKIE_PARAMETER(x) (((x) >> S_SYN_COOKIE_PARAMETER) & M_SYN_COOKIE_PARAMETER) + +#define A_TP_GLOBAL_RX_CREDITS 0x30c +#define A_TP_CM_SIZE 0x310 +#define A_TP_CM_MM_BASE 0x314 + +#define S_CM_MEMMGR_BASE 0 +#define M_CM_MEMMGR_BASE 0xfffffff +#define V_CM_MEMMGR_BASE(x) ((x) << S_CM_MEMMGR_BASE) +#define G_CM_MEMMGR_BASE(x) (((x) >> S_CM_MEMMGR_BASE) & M_CM_MEMMGR_BASE) + +#define A_TP_CM_TIMER_BASE 0x318 + +#define S_CM_TIMER_BASE 0 +#define M_CM_TIMER_BASE 0xfffffff +#define V_CM_TIMER_BASE(x) ((x) << S_CM_TIMER_BASE) +#define G_CM_TIMER_BASE(x) (((x) >> S_CM_TIMER_BASE) & M_CM_TIMER_BASE) + +#define A_TP_PM_SIZE 0x31c +#define A_TP_PM_TX_BASE 0x320 +#define A_TP_PM_DEFRAG_BASE 0x324 +#define A_TP_PM_RX_BASE 0x328 +#define A_TP_PM_RX_PG_SIZE 0x32c +#define A_TP_PM_RX_MAX_PGS 0x330 +#define A_TP_PM_TX_PG_SIZE 0x334 +#define A_TP_PM_TX_MAX_PGS 0x338 +#define A_TP_TCP_OPTIONS 0x340 + +#define S_TIMESTAMP 0 +#define M_TIMESTAMP 0x3 +#define V_TIMESTAMP(x) ((x) << S_TIMESTAMP) +#define G_TIMESTAMP(x) (((x) >> S_TIMESTAMP) & M_TIMESTAMP) + +#define S_WINDOW_SCALE 2 +#define M_WINDOW_SCALE 0x3 +#define V_WINDOW_SCALE(x) ((x) << S_WINDOW_SCALE) +#define G_WINDOW_SCALE(x) (((x) >> S_WINDOW_SCALE) & M_WINDOW_SCALE) + +#define S_SACK 4 +#define M_SACK 0x3 +#define V_SACK(x) ((x) << S_SACK) +#define G_SACK(x) (((x) >> S_SACK) & M_SACK) + +#define S_ECN 6 +#define M_ECN 0x3 +#define V_ECN(x) ((x) << S_ECN) +#define G_ECN(x) (((x) >> S_ECN) & M_ECN) + +#define S_SACK_ALGORITHM 8 +#define M_SACK_ALGORITHM 0x3 +#define V_SACK_ALGORITHM(x) ((x) << S_SACK_ALGORITHM) +#define G_SACK_ALGORITHM(x) (((x) >> S_SACK_ALGORITHM) & M_SACK_ALGORITHM) + +#define S_MSS 10 +#define V_MSS(x) ((x) << S_MSS) +#define F_MSS V_MSS(1U) + +#define S_DEFAULT_PEER_MSS 16 +#define M_DEFAULT_PEER_MSS 0xffff +#define V_DEFAULT_PEER_MSS(x) ((x) << S_DEFAULT_PEER_MSS) +#define G_DEFAULT_PEER_MSS(x) (((x) >> S_DEFAULT_PEER_MSS) & M_DEFAULT_PEER_MSS) + +#define A_TP_DACK_CONFIG 0x344 + +#define S_DACK_MODE 0 +#define V_DACK_MODE(x) ((x) << S_DACK_MODE) +#define F_DACK_MODE V_DACK_MODE(1U) + +#define S_DACK_AUTO_MGMT 1 +#define V_DACK_AUTO_MGMT(x) ((x) << S_DACK_AUTO_MGMT) +#define F_DACK_AUTO_MGMT V_DACK_AUTO_MGMT(1U) + +#define S_DACK_AUTO_CAREFUL 2 +#define V_DACK_AUTO_CAREFUL(x) ((x) << S_DACK_AUTO_CAREFUL) +#define F_DACK_AUTO_CAREFUL V_DACK_AUTO_CAREFUL(1U) + +#define S_DACK_MSS_SELECTOR 3 +#define M_DACK_MSS_SELECTOR 0x3 +#define V_DACK_MSS_SELECTOR(x) ((x) << S_DACK_MSS_SELECTOR) +#define G_DACK_MSS_SELECTOR(x) (((x) >> S_DACK_MSS_SELECTOR) & M_DACK_MSS_SELECTOR) + +#define S_DACK_BYTE_THRESHOLD 5 +#define M_DACK_BYTE_THRESHOLD 0xfffff +#define V_DACK_BYTE_THRESHOLD(x) ((x) << S_DACK_BYTE_THRESHOLD) +#define G_DACK_BYTE_THRESHOLD(x) (((x) >> S_DACK_BYTE_THRESHOLD) & M_DACK_BYTE_THRESHOLD) #define A_TP_PC_CONFIG 0x348 + +#define S_TP_ACCESS_LATENCY 0 +#define M_TP_ACCESS_LATENCY 0xf +#define V_TP_ACCESS_LATENCY(x) ((x) << S_TP_ACCESS_LATENCY) +#define G_TP_ACCESS_LATENCY(x) (((x) >> S_TP_ACCESS_LATENCY) & M_TP_ACCESS_LATENCY) + +#define S_HELD_FIN_DISABLE 4 +#define V_HELD_FIN_DISABLE(x) ((x) << S_HELD_FIN_DISABLE) +#define F_HELD_FIN_DISABLE V_HELD_FIN_DISABLE(1U) + +#define S_DDP_FC_ENABLE 5 +#define V_DDP_FC_ENABLE(x) ((x) << S_DDP_FC_ENABLE) +#define F_DDP_FC_ENABLE V_DDP_FC_ENABLE(1U) + +#define S_RDMA_ERR_ENABLE 6 +#define V_RDMA_ERR_ENABLE(x) ((x) << S_RDMA_ERR_ENABLE) +#define F_RDMA_ERR_ENABLE V_RDMA_ERR_ENABLE(1U) + +#define S_FAST_PDU_DELIVERY 7 +#define V_FAST_PDU_DELIVERY(x) ((x) << S_FAST_PDU_DELIVERY) +#define F_FAST_PDU_DELIVERY V_FAST_PDU_DELIVERY(1U) + +#define S_CLEAR_FIN 8 +#define V_CLEAR_FIN(x) ((x) << S_CLEAR_FIN) +#define F_CLEAR_FIN V_CLEAR_FIN(1U) + #define S_DIS_TX_FILL_WIN_PUSH 12 #define V_DIS_TX_FILL_WIN_PUSH(x) ((x) << S_DIS_TX_FILL_WIN_PUSH) #define F_DIS_TX_FILL_WIN_PUSH V_DIS_TX_FILL_WIN_PUSH(1U) #define S_TP_PC_REV 30 #define M_TP_PC_REV 0x3 +#define V_TP_PC_REV(x) ((x) << S_TP_PC_REV) #define G_TP_PC_REV(x) (((x) >> S_TP_PC_REV) & M_TP_PC_REV) + +#define A_TP_BACKOFF0 0x350 + +#define S_ELEMENT0 0 +#define M_ELEMENT0 0xff +#define V_ELEMENT0(x) ((x) << S_ELEMENT0) +#define G_ELEMENT0(x) (((x) >> S_ELEMENT0) & M_ELEMENT0) + +#define S_ELEMENT1 8 +#define M_ELEMENT1 0xff +#define V_ELEMENT1(x) ((x) << S_ELEMENT1) +#define G_ELEMENT1(x) (((x) >> S_ELEMENT1) & M_ELEMENT1) + +#define S_ELEMENT2 16 +#define M_ELEMENT2 0xff +#define V_ELEMENT2(x) ((x) << S_ELEMENT2) +#define G_ELEMENT2(x) (((x) >> S_ELEMENT2) & M_ELEMENT2) + +#define S_ELEMENT3 24 +#define M_ELEMENT3 0xff +#define V_ELEMENT3(x) ((x) << S_ELEMENT3) +#define G_ELEMENT3(x) (((x) >> S_ELEMENT3) & M_ELEMENT3) + +#define A_TP_BACKOFF1 0x354 +#define A_TP_BACKOFF2 0x358 +#define A_TP_BACKOFF3 0x35c +#define A_TP_PARA_REG0 0x360 + +#define S_VAR_MULT 0 +#define M_VAR_MULT 0xf +#define V_VAR_MULT(x) ((x) << S_VAR_MULT) +#define G_VAR_MULT(x) (((x) >> S_VAR_MULT) & M_VAR_MULT) + +#define S_VAR_GAIN 4 +#define M_VAR_GAIN 0xf +#define V_VAR_GAIN(x) ((x) << S_VAR_GAIN) +#define G_VAR_GAIN(x) (((x) >> S_VAR_GAIN) & M_VAR_GAIN) + +#define S_SRTT_GAIN 8 +#define M_SRTT_GAIN 0xf +#define V_SRTT_GAIN(x) ((x) << S_SRTT_GAIN) +#define G_SRTT_GAIN(x) (((x) >> S_SRTT_GAIN) & M_SRTT_GAIN) + +#define S_RTTVAR_INIT 12 +#define M_RTTVAR_INIT 0xf +#define V_RTTVAR_INIT(x) ((x) << S_RTTVAR_INIT) +#define G_RTTVAR_INIT(x) (((x) >> S_RTTVAR_INIT) & M_RTTVAR_INIT) + +#define S_DUP_THRESH 20 +#define M_DUP_THRESH 0xf +#define V_DUP_THRESH(x) ((x) << S_DUP_THRESH) +#define G_DUP_THRESH(x) (((x) >> S_DUP_THRESH) & M_DUP_THRESH) + +#define S_INIT_CONG_WIN 24 +#define M_INIT_CONG_WIN 0x7 +#define V_INIT_CONG_WIN(x) ((x) << S_INIT_CONG_WIN) +#define G_INIT_CONG_WIN(x) (((x) >> S_INIT_CONG_WIN) & M_INIT_CONG_WIN) + +#define A_TP_PARA_REG1 0x364 + +#define S_INITIAL_SLOW_START_THRESHOLD 0 +#define M_INITIAL_SLOW_START_THRESHOLD 0xffff +#define V_INITIAL_SLOW_START_THRESHOLD(x) ((x) << S_INITIAL_SLOW_START_THRESHOLD) +#define G_INITIAL_SLOW_START_THRESHOLD(x) (((x) >> S_INITIAL_SLOW_START_THRESHOLD) & M_INITIAL_SLOW_START_THRESHOLD) + +#define S_RECEIVE_BUFFER_SIZE 16 +#define M_RECEIVE_BUFFER_SIZE 0xffff +#define V_RECEIVE_BUFFER_SIZE(x) ((x) << S_RECEIVE_BUFFER_SIZE) +#define G_RECEIVE_BUFFER_SIZE(x) (((x) >> S_RECEIVE_BUFFER_SIZE) & M_RECEIVE_BUFFER_SIZE) + +#define A_TP_PARA_REG2 0x368 + +#define S_RX_COALESCE_SIZE 0 +#define M_RX_COALESCE_SIZE 0xffff +#define V_RX_COALESCE_SIZE(x) ((x) << S_RX_COALESCE_SIZE) +#define G_RX_COALESCE_SIZE(x) (((x) >> S_RX_COALESCE_SIZE) & M_RX_COALESCE_SIZE) + +#define S_MAX_RX_SIZE 16 +#define M_MAX_RX_SIZE 0xffff +#define V_MAX_RX_SIZE(x) ((x) << S_MAX_RX_SIZE) +#define G_MAX_RX_SIZE(x) (((x) >> S_MAX_RX_SIZE) & M_MAX_RX_SIZE) + +#define A_TP_PARA_REG3 0x36c + +#define S_RX_COALESCING_PSH_DELIVER 0 +#define V_RX_COALESCING_PSH_DELIVER(x) ((x) << S_RX_COALESCING_PSH_DELIVER) +#define F_RX_COALESCING_PSH_DELIVER V_RX_COALESCING_PSH_DELIVER(1U) + +#define S_RX_COALESCING_ENABLE 1 +#define V_RX_COALESCING_ENABLE(x) ((x) << S_RX_COALESCING_ENABLE) +#define F_RX_COALESCING_ENABLE V_RX_COALESCING_ENABLE(1U) + +#define S_TAHOE_ENABLE 2 +#define V_TAHOE_ENABLE(x) ((x) << S_TAHOE_ENABLE) +#define F_TAHOE_ENABLE V_TAHOE_ENABLE(1U) + +#define S_MAX_REORDER_FRAGMENTS 12 +#define M_MAX_REORDER_FRAGMENTS 0x7 +#define V_MAX_REORDER_FRAGMENTS(x) ((x) << S_MAX_REORDER_FRAGMENTS) +#define G_MAX_REORDER_FRAGMENTS(x) (((x) >> S_MAX_REORDER_FRAGMENTS) & M_MAX_REORDER_FRAGMENTS) + +#define A_TP_TIMER_RESOLUTION 0x390 + +#define S_DELAYED_ACK_TIMER_RESOLUTION 0 +#define M_DELAYED_ACK_TIMER_RESOLUTION 0x3f +#define V_DELAYED_ACK_TIMER_RESOLUTION(x) ((x) << S_DELAYED_ACK_TIMER_RESOLUTION) +#define G_DELAYED_ACK_TIMER_RESOLUTION(x) (((x) >> S_DELAYED_ACK_TIMER_RESOLUTION) & M_DELAYED_ACK_TIMER_RESOLUTION) + +#define S_GENERIC_TIMER_RESOLUTION 16 +#define M_GENERIC_TIMER_RESOLUTION 0x3f +#define V_GENERIC_TIMER_RESOLUTION(x) ((x) << S_GENERIC_TIMER_RESOLUTION) +#define G_GENERIC_TIMER_RESOLUTION(x) (((x) >> S_GENERIC_TIMER_RESOLUTION) & M_GENERIC_TIMER_RESOLUTION) + +#define A_TP_2MSL 0x394 + +#define S_2MSL 0 +#define M_2MSL 0x3fffffff +#define V_2MSL(x) ((x) << S_2MSL) +#define G_2MSL(x) (((x) >> S_2MSL) & M_2MSL) + +#define A_TP_RXT_MIN 0x398 + +#define S_RETRANSMIT_TIMER_MIN 0 +#define M_RETRANSMIT_TIMER_MIN 0xffff +#define V_RETRANSMIT_TIMER_MIN(x) ((x) << S_RETRANSMIT_TIMER_MIN) +#define G_RETRANSMIT_TIMER_MIN(x) (((x) >> S_RETRANSMIT_TIMER_MIN) & M_RETRANSMIT_TIMER_MIN) + +#define A_TP_RXT_MAX 0x39c + +#define S_RETRANSMIT_TIMER_MAX 0 +#define M_RETRANSMIT_TIMER_MAX 0x3fffffff +#define V_RETRANSMIT_TIMER_MAX(x) ((x) << S_RETRANSMIT_TIMER_MAX) +#define G_RETRANSMIT_TIMER_MAX(x) (((x) >> S_RETRANSMIT_TIMER_MAX) & M_RETRANSMIT_TIMER_MAX) + +#define A_TP_PERS_MIN 0x3a0 + +#define S_PERSIST_TIMER_MIN 0 +#define M_PERSIST_TIMER_MIN 0xffff +#define V_PERSIST_TIMER_MIN(x) ((x) << S_PERSIST_TIMER_MIN) +#define G_PERSIST_TIMER_MIN(x) (((x) >> S_PERSIST_TIMER_MIN) & M_PERSIST_TIMER_MIN) + +#define A_TP_PERS_MAX 0x3a4 + +#define S_PERSIST_TIMER_MAX 0 +#define M_PERSIST_TIMER_MAX 0x3fffffff +#define V_PERSIST_TIMER_MAX(x) ((x) << S_PERSIST_TIMER_MAX) +#define G_PERSIST_TIMER_MAX(x) (((x) >> S_PERSIST_TIMER_MAX) & M_PERSIST_TIMER_MAX) + +#define A_TP_KEEP_IDLE 0x3ac + +#define S_KEEP_ALIVE_IDLE_TIME 0 +#define M_KEEP_ALIVE_IDLE_TIME 0x3fffffff +#define V_KEEP_ALIVE_IDLE_TIME(x) ((x) << S_KEEP_ALIVE_IDLE_TIME) +#define G_KEEP_ALIVE_IDLE_TIME(x) (((x) >> S_KEEP_ALIVE_IDLE_TIME) & M_KEEP_ALIVE_IDLE_TIME) + +#define A_TP_KEEP_INTVL 0x3b0 + +#define S_KEEP_ALIVE_INTERVAL_TIME 0 +#define M_KEEP_ALIVE_INTERVAL_TIME 0x3fffffff +#define V_KEEP_ALIVE_INTERVAL_TIME(x) ((x) << S_KEEP_ALIVE_INTERVAL_TIME) +#define G_KEEP_ALIVE_INTERVAL_TIME(x) (((x) >> S_KEEP_ALIVE_INTERVAL_TIME) & M_KEEP_ALIVE_INTERVAL_TIME) + +#define A_TP_INIT_SRTT 0x3b4 + +#define S_INITIAL_SRTT 0 +#define M_INITIAL_SRTT 0xffff +#define V_INITIAL_SRTT(x) ((x) << S_INITIAL_SRTT) +#define G_INITIAL_SRTT(x) (((x) >> S_INITIAL_SRTT) & M_INITIAL_SRTT) + +#define A_TP_DACK_TIME 0x3b8 + +#define S_DELAYED_ACK_TIME 0 +#define M_DELAYED_ACK_TIME 0x7ff +#define V_DELAYED_ACK_TIME(x) ((x) << S_DELAYED_ACK_TIME) +#define G_DELAYED_ACK_TIME(x) (((x) >> S_DELAYED_ACK_TIME) & M_DELAYED_ACK_TIME) + +#define A_TP_FINWAIT2_TIME 0x3bc + +#define S_FINWAIT2_TIME 0 +#define M_FINWAIT2_TIME 0x3fffffff +#define V_FINWAIT2_TIME(x) ((x) << S_FINWAIT2_TIME) +#define G_FINWAIT2_TIME(x) (((x) >> S_FINWAIT2_TIME) & M_FINWAIT2_TIME) + +#define A_TP_FAST_FINWAIT2_TIME 0x3c0 + +#define S_FAST_FINWAIT2_TIME 0 +#define M_FAST_FINWAIT2_TIME 0x3fffffff +#define V_FAST_FINWAIT2_TIME(x) ((x) << S_FAST_FINWAIT2_TIME) +#define G_FAST_FINWAIT2_TIME(x) (((x) >> S_FAST_FINWAIT2_TIME) & M_FAST_FINWAIT2_TIME) + +#define A_TP_SHIFT_CNT 0x3c4 + +#define S_KEEPALIVE_MAX 0 +#define M_KEEPALIVE_MAX 0xff +#define V_KEEPALIVE_MAX(x) ((x) << S_KEEPALIVE_MAX) +#define G_KEEPALIVE_MAX(x) (((x) >> S_KEEPALIVE_MAX) & M_KEEPALIVE_MAX) + +#define S_WINDOWPROBE_MAX 8 +#define M_WINDOWPROBE_MAX 0xff +#define V_WINDOWPROBE_MAX(x) ((x) << S_WINDOWPROBE_MAX) +#define G_WINDOWPROBE_MAX(x) (((x) >> S_WINDOWPROBE_MAX) & M_WINDOWPROBE_MAX) + +#define S_RETRANSMISSION_MAX 16 +#define M_RETRANSMISSION_MAX 0xff +#define V_RETRANSMISSION_MAX(x) ((x) << S_RETRANSMISSION_MAX) +#define G_RETRANSMISSION_MAX(x) (((x) >> S_RETRANSMISSION_MAX) & M_RETRANSMISSION_MAX) + +#define S_SYN_MAX 24 +#define M_SYN_MAX 0xff +#define V_SYN_MAX(x) ((x) << S_SYN_MAX) +#define G_SYN_MAX(x) (((x) >> S_SYN_MAX) & M_SYN_MAX) + +#define A_TP_QOS_REG0 0x3e0 + +#define S_L3_VALUE 0 +#define M_L3_VALUE 0x3f +#define V_L3_VALUE(x) ((x) << S_L3_VALUE) +#define G_L3_VALUE(x) (((x) >> S_L3_VALUE) & M_L3_VALUE) + +#define A_TP_QOS_REG1 0x3e4 +#define A_TP_QOS_REG2 0x3e8 +#define A_TP_QOS_REG3 0x3ec +#define A_TP_QOS_REG4 0x3f0 +#define A_TP_QOS_REG5 0x3f4 +#define A_TP_QOS_REG6 0x3f8 +#define A_TP_QOS_REG7 0x3fc +#define A_TP_MTU_REG0 0x404 +#define A_TP_MTU_REG1 0x408 +#define A_TP_MTU_REG2 0x40c +#define A_TP_MTU_REG3 0x410 +#define A_TP_MTU_REG4 0x414 +#define A_TP_MTU_REG5 0x418 +#define A_TP_MTU_REG6 0x41c +#define A_TP_MTU_REG7 0x420 #define A_TP_RESET 0x44c + #define S_TP_RESET 0 #define V_TP_RESET(x) ((x) << S_TP_RESET) #define F_TP_RESET V_TP_RESET(1U) +#define S_CM_MEMMGR_INIT 1 +#define V_CM_MEMMGR_INIT(x) ((x) << S_CM_MEMMGR_INIT) +#define F_CM_MEMMGR_INIT V_CM_MEMMGR_INIT(1U) + +#define A_TP_MIB_INDEX 0x450 +#define A_TP_MIB_DATA 0x454 +#define A_TP_SYNC_TIME_HI 0x458 +#define A_TP_SYNC_TIME_LO 0x45c +#define A_TP_CM_MM_RX_FLST_BASE 0x460 + +#define S_CM_MEMMGR_RX_FREE_LIST_BASE 0 +#define M_CM_MEMMGR_RX_FREE_LIST_BASE 0xfffffff +#define V_CM_MEMMGR_RX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_RX_FREE_LIST_BASE) +#define G_CM_MEMMGR_RX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_RX_FREE_LIST_BASE) & M_CM_MEMMGR_RX_FREE_LIST_BASE) + +#define A_TP_CM_MM_TX_FLST_BASE 0x464 + +#define S_CM_MEMMGR_TX_FREE_LIST_BASE 0 +#define M_CM_MEMMGR_TX_FREE_LIST_BASE 0xfffffff +#define V_CM_MEMMGR_TX_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_TX_FREE_LIST_BASE) +#define G_CM_MEMMGR_TX_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_TX_FREE_LIST_BASE) & M_CM_MEMMGR_TX_FREE_LIST_BASE) + +#define A_TP_CM_MM_P_FLST_BASE 0x468 + +#define S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE 0 +#define M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE 0xfffffff +#define V_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) ((x) << S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE) +#define G_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE(x) (((x) >> S_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE) & M_CM_MEMMGR_PSTRUCT_FREE_LIST_BASE) + +#define A_TP_CM_MM_MAX_P 0x46c + +#define S_CM_MEMMGR_MAX_PSTRUCT 0 +#define M_CM_MEMMGR_MAX_PSTRUCT 0xfffffff +#define V_CM_MEMMGR_MAX_PSTRUCT(x) ((x) << S_CM_MEMMGR_MAX_PSTRUCT) +#define G_CM_MEMMGR_MAX_PSTRUCT(x) (((x) >> S_CM_MEMMGR_MAX_PSTRUCT) & M_CM_MEMMGR_MAX_PSTRUCT) + #define A_TP_INT_ENABLE 0x470 + +#define S_TX_FREE_LIST_EMPTY 0 +#define V_TX_FREE_LIST_EMPTY(x) ((x) << S_TX_FREE_LIST_EMPTY) +#define F_TX_FREE_LIST_EMPTY V_TX_FREE_LIST_EMPTY(1U) + +#define S_RX_FREE_LIST_EMPTY 1 +#define V_RX_FREE_LIST_EMPTY(x) ((x) << S_RX_FREE_LIST_EMPTY) +#define F_RX_FREE_LIST_EMPTY V_RX_FREE_LIST_EMPTY(1U) + #define A_TP_INT_CAUSE 0x474 +#define A_TP_TIMER_SEPARATOR 0x4a4 + +#define S_DISABLE_PAST_TIMER_INSERTION 0 +#define V_DISABLE_PAST_TIMER_INSERTION(x) ((x) << S_DISABLE_PAST_TIMER_INSERTION) +#define F_DISABLE_PAST_TIMER_INSERTION V_DISABLE_PAST_TIMER_INSERTION(1U) + +#define S_MODULATION_TIMER_SEPARATOR 1 +#define M_MODULATION_TIMER_SEPARATOR 0x7fff +#define V_MODULATION_TIMER_SEPARATOR(x) ((x) << S_MODULATION_TIMER_SEPARATOR) +#define G_MODULATION_TIMER_SEPARATOR(x) (((x) >> S_MODULATION_TIMER_SEPARATOR) & M_MODULATION_TIMER_SEPARATOR) + +#define S_GLOBAL_TIMER_SEPARATOR 16 +#define M_GLOBAL_TIMER_SEPARATOR 0xffff +#define V_GLOBAL_TIMER_SEPARATOR(x) ((x) << S_GLOBAL_TIMER_SEPARATOR) +#define G_GLOBAL_TIMER_SEPARATOR(x) (((x) >> S_GLOBAL_TIMER_SEPARATOR) & M_GLOBAL_TIMER_SEPARATOR) + +#define A_TP_CM_FC_MODE 0x4b0 +#define A_TP_PC_CONGESTION_CNTL 0x4b4 #define A_TP_TX_DROP_CONFIG 0x4b8 #define S_ENABLE_TX_DROP 31 @@ -282,12 +1249,108 @@ #define F_ENABLE_TX_ERROR V_ENABLE_TX_ERROR(1U) #define S_DROP_TICKS_CNT 4 +#define M_DROP_TICKS_CNT 0x3ffffff #define V_DROP_TICKS_CNT(x) ((x) << S_DROP_TICKS_CNT) +#define G_DROP_TICKS_CNT(x) (((x) >> S_DROP_TICKS_CNT) & M_DROP_TICKS_CNT) #define S_NUM_PKTS_DROPPED 0 +#define M_NUM_PKTS_DROPPED 0xf #define V_NUM_PKTS_DROPPED(x) ((x) << S_NUM_PKTS_DROPPED) +#define G_NUM_PKTS_DROPPED(x) (((x) >> S_NUM_PKTS_DROPPED) & M_NUM_PKTS_DROPPED) + +#define A_TP_TX_DROP_COUNT 0x4bc + +/* RAT registers */ +#define A_RAT_ROUTE_CONTROL 0x580 + +#define S_USE_ROUTE_TABLE 0 +#define V_USE_ROUTE_TABLE(x) ((x) << S_USE_ROUTE_TABLE) +#define F_USE_ROUTE_TABLE V_USE_ROUTE_TABLE(1U) + +#define S_ENABLE_CSPI 1 +#define V_ENABLE_CSPI(x) ((x) << S_ENABLE_CSPI) +#define F_ENABLE_CSPI V_ENABLE_CSPI(1U) + +#define S_ENABLE_PCIX 2 +#define V_ENABLE_PCIX(x) ((x) << S_ENABLE_PCIX) +#define F_ENABLE_PCIX V_ENABLE_PCIX(1U) + +#define A_RAT_ROUTE_TABLE_INDEX 0x584 + +#define S_ROUTE_TABLE_INDEX 0 +#define M_ROUTE_TABLE_INDEX 0xf +#define V_ROUTE_TABLE_INDEX(x) ((x) << S_ROUTE_TABLE_INDEX) +#define G_ROUTE_TABLE_INDEX(x) (((x) >> S_ROUTE_TABLE_INDEX) & M_ROUTE_TABLE_INDEX) + +#define A_RAT_ROUTE_TABLE_DATA 0x588 +#define A_RAT_NO_ROUTE 0x58c + +#define S_CPL_OPCODE 0 +#define M_CPL_OPCODE 0xff +#define V_CPL_OPCODE(x) ((x) << S_CPL_OPCODE) +#define G_CPL_OPCODE(x) (((x) >> S_CPL_OPCODE) & M_CPL_OPCODE) + +#define A_RAT_INTR_ENABLE 0x590 + +#define S_ZEROROUTEERROR 0 +#define V_ZEROROUTEERROR(x) ((x) << S_ZEROROUTEERROR) +#define F_ZEROROUTEERROR V_ZEROROUTEERROR(1U) + +#define S_CSPIFRAMINGERROR 1 +#define V_CSPIFRAMINGERROR(x) ((x) << S_CSPIFRAMINGERROR) +#define F_CSPIFRAMINGERROR V_CSPIFRAMINGERROR(1U) + +#define S_SGEFRAMINGERROR 2 +#define V_SGEFRAMINGERROR(x) ((x) << S_SGEFRAMINGERROR) +#define F_SGEFRAMINGERROR V_SGEFRAMINGERROR(1U) + +#define S_TPFRAMINGERROR 3 +#define V_TPFRAMINGERROR(x) ((x) << S_TPFRAMINGERROR) +#define F_TPFRAMINGERROR V_TPFRAMINGERROR(1U) + +#define A_RAT_INTR_CAUSE 0x594 /* CSPI registers */ +#define A_CSPI_RX_AE_WM 0x810 +#define A_CSPI_RX_AF_WM 0x814 +#define A_CSPI_CALENDAR_LEN 0x818 + +#define S_CALENDARLENGTH 0 +#define M_CALENDARLENGTH 0xffff +#define V_CALENDARLENGTH(x) ((x) << S_CALENDARLENGTH) +#define G_CALENDARLENGTH(x) (((x) >> S_CALENDARLENGTH) & M_CALENDARLENGTH) + +#define A_CSPI_FIFO_STATUS_ENABLE 0x820 + +#define S_FIFOSTATUSENABLE 0 +#define V_FIFOSTATUSENABLE(x) ((x) << S_FIFOSTATUSENABLE) +#define F_FIFOSTATUSENABLE V_FIFOSTATUSENABLE(1U) + +#define A_CSPI_MAXBURST1_MAXBURST2 0x828 + +#define S_MAXBURST1 0 +#define M_MAXBURST1 0xffff +#define V_MAXBURST1(x) ((x) << S_MAXBURST1) +#define G_MAXBURST1(x) (((x) >> S_MAXBURST1) & M_MAXBURST1) + +#define S_MAXBURST2 16 +#define M_MAXBURST2 0xffff +#define V_MAXBURST2(x) ((x) << S_MAXBURST2) +#define G_MAXBURST2(x) (((x) >> S_MAXBURST2) & M_MAXBURST2) + +#define A_CSPI_TRAIN 0x82c + +#define S_CSPI_TRAIN_ALPHA 0 +#define M_CSPI_TRAIN_ALPHA 0xffff +#define V_CSPI_TRAIN_ALPHA(x) ((x) << S_CSPI_TRAIN_ALPHA) +#define G_CSPI_TRAIN_ALPHA(x) (((x) >> S_CSPI_TRAIN_ALPHA) & M_CSPI_TRAIN_ALPHA) + +#define S_CSPI_TRAIN_DATA_MAXT 16 +#define M_CSPI_TRAIN_DATA_MAXT 0xffff +#define V_CSPI_TRAIN_DATA_MAXT(x) ((x) << S_CSPI_TRAIN_DATA_MAXT) +#define G_CSPI_TRAIN_DATA_MAXT(x) (((x) >> S_CSPI_TRAIN_DATA_MAXT) & M_CSPI_TRAIN_DATA_MAXT) + +#define A_CSPI_INTR_STATUS 0x848 #define S_DIP4ERR 0 #define V_DIP4ERR(x) ((x) << S_DIP4ERR) @@ -309,22 +1372,63 @@ #define V_RAMPARITYERR(x) ((x) << S_RAMPARITYERR) #define F_RAMPARITYERR V_RAMPARITYERR(1U) -/* ESPI registers */ +#define A_CSPI_INTR_ENABLE 0x84c +/* ESPI registers */ #define A_ESPI_SCH_TOKEN0 0x880 + +#define S_SCHTOKEN0 0 +#define M_SCHTOKEN0 0xffff +#define V_SCHTOKEN0(x) ((x) << S_SCHTOKEN0) +#define G_SCHTOKEN0(x) (((x) >> S_SCHTOKEN0) & M_SCHTOKEN0) + #define A_ESPI_SCH_TOKEN1 0x884 + +#define S_SCHTOKEN1 0 +#define M_SCHTOKEN1 0xffff +#define V_SCHTOKEN1(x) ((x) << S_SCHTOKEN1) +#define G_SCHTOKEN1(x) (((x) >> S_SCHTOKEN1) & M_SCHTOKEN1) + #define A_ESPI_SCH_TOKEN2 0x888 + +#define S_SCHTOKEN2 0 +#define M_SCHTOKEN2 0xffff +#define V_SCHTOKEN2(x) ((x) << S_SCHTOKEN2) +#define G_SCHTOKEN2(x) (((x) >> S_SCHTOKEN2) & M_SCHTOKEN2) + #define A_ESPI_SCH_TOKEN3 0x88c + +#define S_SCHTOKEN3 0 +#define M_SCHTOKEN3 0xffff +#define V_SCHTOKEN3(x) ((x) << S_SCHTOKEN3) +#define G_SCHTOKEN3(x) (((x) >> S_SCHTOKEN3) & M_SCHTOKEN3) + #define A_ESPI_RX_FIFO_ALMOST_EMPTY_WATERMARK 0x890 + +#define S_ALMOSTEMPTY 0 +#define M_ALMOSTEMPTY 0xffff +#define V_ALMOSTEMPTY(x) ((x) << S_ALMOSTEMPTY) +#define G_ALMOSTEMPTY(x) (((x) >> S_ALMOSTEMPTY) & M_ALMOSTEMPTY) + #define A_ESPI_RX_FIFO_ALMOST_FULL_WATERMARK 0x894 + +#define S_ALMOSTFULL 0 +#define M_ALMOSTFULL 0xffff +#define V_ALMOSTFULL(x) ((x) << S_ALMOSTFULL) +#define G_ALMOSTFULL(x) (((x) >> S_ALMOSTFULL) & M_ALMOSTFULL) + #define A_ESPI_CALENDAR_LENGTH 0x898 #define A_PORT_CONFIG 0x89c #define S_RX_NPORTS 0 +#define M_RX_NPORTS 0xff #define V_RX_NPORTS(x) ((x) << S_RX_NPORTS) +#define G_RX_NPORTS(x) (((x) >> S_RX_NPORTS) & M_RX_NPORTS) #define S_TX_NPORTS 8 +#define M_TX_NPORTS 0xff #define V_TX_NPORTS(x) ((x) << S_TX_NPORTS) +#define G_TX_NPORTS(x) (((x) >> S_TX_NPORTS) & M_TX_NPORTS) #define A_ESPI_FIFO_STATUS_ENABLE 0x8a0 @@ -332,12 +1436,124 @@ #define V_RXSTATUSENABLE(x) ((x) << S_RXSTATUSENABLE) #define F_RXSTATUSENABLE V_RXSTATUSENABLE(1U) +#define S_TXDROPENABLE 1 +#define V_TXDROPENABLE(x) ((x) << S_TXDROPENABLE) +#define F_TXDROPENABLE V_TXDROPENABLE(1U) + +#define S_RXENDIANMODE 2 +#define V_RXENDIANMODE(x) ((x) << S_RXENDIANMODE) +#define F_RXENDIANMODE V_RXENDIANMODE(1U) + +#define S_TXENDIANMODE 3 +#define V_TXENDIANMODE(x) ((x) << S_TXENDIANMODE) +#define F_TXENDIANMODE V_TXENDIANMODE(1U) + #define S_INTEL1010MODE 4 #define V_INTEL1010MODE(x) ((x) << S_INTEL1010MODE) #define F_INTEL1010MODE V_INTEL1010MODE(1U) #define A_ESPI_MAXBURST1_MAXBURST2 0x8a8 #define A_ESPI_TRAIN 0x8ac + +#define S_MAXTRAINALPHA 0 +#define M_MAXTRAINALPHA 0xffff +#define V_MAXTRAINALPHA(x) ((x) << S_MAXTRAINALPHA) +#define G_MAXTRAINALPHA(x) (((x) >> S_MAXTRAINALPHA) & M_MAXTRAINALPHA) + +#define S_MAXTRAINDATA 16 +#define M_MAXTRAINDATA 0xffff +#define V_MAXTRAINDATA(x) ((x) << S_MAXTRAINDATA) +#define G_MAXTRAINDATA(x) (((x) >> S_MAXTRAINDATA) & M_MAXTRAINDATA) + +#define A_RAM_STATUS 0x8b0 + +#define S_RXFIFOPARITYERROR 0 +#define M_RXFIFOPARITYERROR 0x3ff +#define V_RXFIFOPARITYERROR(x) ((x) << S_RXFIFOPARITYERROR) +#define G_RXFIFOPARITYERROR(x) (((x) >> S_RXFIFOPARITYERROR) & M_RXFIFOPARITYERROR) + +#define S_TXFIFOPARITYERROR 10 +#define M_TXFIFOPARITYERROR 0x3ff +#define V_TXFIFOPARITYERROR(x) ((x) << S_TXFIFOPARITYERROR) +#define G_TXFIFOPARITYERROR(x) (((x) >> S_TXFIFOPARITYERROR) & M_TXFIFOPARITYERROR) + +#define S_RXFIFOOVERFLOW 20 +#define M_RXFIFOOVERFLOW 0x3ff +#define V_RXFIFOOVERFLOW(x) ((x) << S_RXFIFOOVERFLOW) +#define G_RXFIFOOVERFLOW(x) (((x) >> S_RXFIFOOVERFLOW) & M_RXFIFOOVERFLOW) + +#define A_TX_DROP_COUNT0 0x8b4 + +#define S_TXPORT0DROPCNT 0 +#define M_TXPORT0DROPCNT 0xffff +#define V_TXPORT0DROPCNT(x) ((x) << S_TXPORT0DROPCNT) +#define G_TXPORT0DROPCNT(x) (((x) >> S_TXPORT0DROPCNT) & M_TXPORT0DROPCNT) + +#define S_TXPORT1DROPCNT 16 +#define M_TXPORT1DROPCNT 0xffff +#define V_TXPORT1DROPCNT(x) ((x) << S_TXPORT1DROPCNT) +#define G_TXPORT1DROPCNT(x) (((x) >> S_TXPORT1DROPCNT) & M_TXPORT1DROPCNT) + +#define A_TX_DROP_COUNT1 0x8b8 + +#define S_TXPORT2DROPCNT 0 +#define M_TXPORT2DROPCNT 0xffff +#define V_TXPORT2DROPCNT(x) ((x) << S_TXPORT2DROPCNT) +#define G_TXPORT2DROPCNT(x) (((x) >> S_TXPORT2DROPCNT) & M_TXPORT2DROPCNT) + +#define S_TXPORT3DROPCNT 16 +#define M_TXPORT3DROPCNT 0xffff +#define V_TXPORT3DROPCNT(x) ((x) << S_TXPORT3DROPCNT) +#define G_TXPORT3DROPCNT(x) (((x) >> S_TXPORT3DROPCNT) & M_TXPORT3DROPCNT) + +#define A_RX_DROP_COUNT0 0x8bc + +#define S_RXPORT0DROPCNT 0 +#define M_RXPORT0DROPCNT 0xffff +#define V_RXPORT0DROPCNT(x) ((x) << S_RXPORT0DROPCNT) +#define G_RXPORT0DROPCNT(x) (((x) >> S_RXPORT0DROPCNT) & M_RXPORT0DROPCNT) + +#define S_RXPORT1DROPCNT 16 +#define M_RXPORT1DROPCNT 0xffff +#define V_RXPORT1DROPCNT(x) ((x) << S_RXPORT1DROPCNT) +#define G_RXPORT1DROPCNT(x) (((x) >> S_RXPORT1DROPCNT) & M_RXPORT1DROPCNT) + +#define A_RX_DROP_COUNT1 0x8c0 + +#define S_RXPORT2DROPCNT 0 +#define M_RXPORT2DROPCNT 0xffff +#define V_RXPORT2DROPCNT(x) ((x) << S_RXPORT2DROPCNT) +#define G_RXPORT2DROPCNT(x) (((x) >> S_RXPORT2DROPCNT) & M_RXPORT2DROPCNT) + +#define S_RXPORT3DROPCNT 16 +#define M_RXPORT3DROPCNT 0xffff +#define V_RXPORT3DROPCNT(x) ((x) << S_RXPORT3DROPCNT) +#define G_RXPORT3DROPCNT(x) (((x) >> S_RXPORT3DROPCNT) & M_RXPORT3DROPCNT) + +#define A_DIP4_ERROR_COUNT 0x8c4 + +#define S_DIP4ERRORCNT 0 +#define M_DIP4ERRORCNT 0xfff +#define V_DIP4ERRORCNT(x) ((x) << S_DIP4ERRORCNT) +#define G_DIP4ERRORCNT(x) (((x) >> S_DIP4ERRORCNT) & M_DIP4ERRORCNT) + +#define S_DIP4ERRORCNTSHADOW 12 +#define M_DIP4ERRORCNTSHADOW 0xfff +#define V_DIP4ERRORCNTSHADOW(x) ((x) << S_DIP4ERRORCNTSHADOW) +#define G_DIP4ERRORCNTSHADOW(x) (((x) >> S_DIP4ERRORCNTSHADOW) & M_DIP4ERRORCNTSHADOW) + +#define S_TRICN_RX_TRAIN_ERR 24 +#define V_TRICN_RX_TRAIN_ERR(x) ((x) << S_TRICN_RX_TRAIN_ERR) +#define F_TRICN_RX_TRAIN_ERR V_TRICN_RX_TRAIN_ERR(1U) + +#define S_TRICN_RX_TRAINING 25 +#define V_TRICN_RX_TRAINING(x) ((x) << S_TRICN_RX_TRAINING) +#define F_TRICN_RX_TRAINING V_TRICN_RX_TRAINING(1U) + +#define S_TRICN_RX_TRAIN_OK 26 +#define V_TRICN_RX_TRAIN_OK(x) ((x) << S_TRICN_RX_TRAIN_OK) +#define F_TRICN_RX_TRAIN_OK V_TRICN_RX_TRAIN_OK(1U) + #define A_ESPI_INTR_STATUS 0x8c8 #define S_DIP2PARITYERR 5 @@ -347,19 +1563,56 @@ #define A_ESPI_INTR_ENABLE 0x8cc #define A_RX_DROP_THRESHOLD 0x8d0 #define A_ESPI_RX_RESET 0x8ec + +#define S_ESPI_RX_LNK_RST 0 +#define V_ESPI_RX_LNK_RST(x) ((x) << S_ESPI_RX_LNK_RST) +#define F_ESPI_RX_LNK_RST V_ESPI_RX_LNK_RST(1U) + +#define S_ESPI_RX_CORE_RST 1 +#define V_ESPI_RX_CORE_RST(x) ((x) << S_ESPI_RX_CORE_RST) +#define F_ESPI_RX_CORE_RST V_ESPI_RX_CORE_RST(1U) + +#define S_RX_CLK_STATUS 2 +#define V_RX_CLK_STATUS(x) ((x) << S_RX_CLK_STATUS) +#define F_RX_CLK_STATUS V_RX_CLK_STATUS(1U) + #define A_ESPI_MISC_CONTROL 0x8f0 #define S_OUT_OF_SYNC_COUNT 0 +#define M_OUT_OF_SYNC_COUNT 0xf #define V_OUT_OF_SYNC_COUNT(x) ((x) << S_OUT_OF_SYNC_COUNT) +#define G_OUT_OF_SYNC_COUNT(x) (((x) >> S_OUT_OF_SYNC_COUNT) & M_OUT_OF_SYNC_COUNT) + +#define S_DIP2_COUNT_MODE_ENABLE 4 +#define V_DIP2_COUNT_MODE_ENABLE(x) ((x) << S_DIP2_COUNT_MODE_ENABLE) +#define F_DIP2_COUNT_MODE_ENABLE V_DIP2_COUNT_MODE_ENABLE(1U) #define S_DIP2_PARITY_ERR_THRES 5 +#define M_DIP2_PARITY_ERR_THRES 0xf #define V_DIP2_PARITY_ERR_THRES(x) ((x) << S_DIP2_PARITY_ERR_THRES) +#define G_DIP2_PARITY_ERR_THRES(x) (((x) >> S_DIP2_PARITY_ERR_THRES) & M_DIP2_PARITY_ERR_THRES) #define S_DIP4_THRES 9 +#define M_DIP4_THRES 0xfff #define V_DIP4_THRES(x) ((x) << S_DIP4_THRES) +#define G_DIP4_THRES(x) (((x) >> S_DIP4_THRES) & M_DIP4_THRES) + +#define S_DIP4_THRES_ENABLE 21 +#define V_DIP4_THRES_ENABLE(x) ((x) << S_DIP4_THRES_ENABLE) +#define F_DIP4_THRES_ENABLE V_DIP4_THRES_ENABLE(1U) + +#define S_FORCE_DISABLE_STATUS 22 +#define V_FORCE_DISABLE_STATUS(x) ((x) << S_FORCE_DISABLE_STATUS) +#define F_FORCE_DISABLE_STATUS V_FORCE_DISABLE_STATUS(1U) + +#define S_DYNAMIC_DESKEW 23 +#define V_DYNAMIC_DESKEW(x) ((x) << S_DYNAMIC_DESKEW) +#define F_DYNAMIC_DESKEW V_DYNAMIC_DESKEW(1U) #define S_MONITORED_PORT_NUM 25 +#define M_MONITORED_PORT_NUM 0x3 #define V_MONITORED_PORT_NUM(x) ((x) << S_MONITORED_PORT_NUM) +#define G_MONITORED_PORT_NUM(x) (((x) >> S_MONITORED_PORT_NUM) & M_MONITORED_PORT_NUM) #define S_MONITORED_DIRECTION 27 #define V_MONITORED_DIRECTION(x) ((x) << S_MONITORED_DIRECTION) @@ -370,33 +1623,125 @@ #define F_MONITORED_INTERFACE V_MONITORED_INTERFACE(1U) #define A_ESPI_DIP2_ERR_COUNT 0x8f4 + +#define S_DIP2_ERR_CNT 0 +#define M_DIP2_ERR_CNT 0xf +#define V_DIP2_ERR_CNT(x) ((x) << S_DIP2_ERR_CNT) +#define G_DIP2_ERR_CNT(x) (((x) >> S_DIP2_ERR_CNT) & M_DIP2_ERR_CNT) + #define A_ESPI_CMD_ADDR 0x8f8 #define S_WRITE_DATA 0 +#define M_WRITE_DATA 0xff #define V_WRITE_DATA(x) ((x) << S_WRITE_DATA) +#define G_WRITE_DATA(x) (((x) >> S_WRITE_DATA) & M_WRITE_DATA) #define S_REGISTER_OFFSET 8 +#define M_REGISTER_OFFSET 0xf #define V_REGISTER_OFFSET(x) ((x) << S_REGISTER_OFFSET) +#define G_REGISTER_OFFSET(x) (((x) >> S_REGISTER_OFFSET) & M_REGISTER_OFFSET) #define S_CHANNEL_ADDR 12 +#define M_CHANNEL_ADDR 0xf #define V_CHANNEL_ADDR(x) ((x) << S_CHANNEL_ADDR) +#define G_CHANNEL_ADDR(x) (((x) >> S_CHANNEL_ADDR) & M_CHANNEL_ADDR) #define S_MODULE_ADDR 16 +#define M_MODULE_ADDR 0x3 #define V_MODULE_ADDR(x) ((x) << S_MODULE_ADDR) +#define G_MODULE_ADDR(x) (((x) >> S_MODULE_ADDR) & M_MODULE_ADDR) #define S_BUNDLE_ADDR 20 +#define M_BUNDLE_ADDR 0x3 #define V_BUNDLE_ADDR(x) ((x) << S_BUNDLE_ADDR) +#define G_BUNDLE_ADDR(x) (((x) >> S_BUNDLE_ADDR) & M_BUNDLE_ADDR) #define S_SPI4_COMMAND 24 +#define M_SPI4_COMMAND 0xff #define V_SPI4_COMMAND(x) ((x) << S_SPI4_COMMAND) +#define G_SPI4_COMMAND(x) (((x) >> S_SPI4_COMMAND) & M_SPI4_COMMAND) #define A_ESPI_GOSTAT 0x8fc + +#define S_READ_DATA 0 +#define M_READ_DATA 0xff +#define V_READ_DATA(x) ((x) << S_READ_DATA) +#define G_READ_DATA(x) (((x) >> S_READ_DATA) & M_READ_DATA) + #define S_ESPI_CMD_BUSY 8 #define V_ESPI_CMD_BUSY(x) ((x) << S_ESPI_CMD_BUSY) #define F_ESPI_CMD_BUSY V_ESPI_CMD_BUSY(1U) -/* PL registers */ +#define S_ERROR_ACK 9 +#define V_ERROR_ACK(x) ((x) << S_ERROR_ACK) +#define F_ERROR_ACK V_ERROR_ACK(1U) + +#define S_UNMAPPED_ERR 10 +#define V_UNMAPPED_ERR(x) ((x) << S_UNMAPPED_ERR) +#define F_UNMAPPED_ERR V_UNMAPPED_ERR(1U) + +#define S_TRANSACTION_TIMER 16 +#define M_TRANSACTION_TIMER 0xff +#define V_TRANSACTION_TIMER(x) ((x) << S_TRANSACTION_TIMER) +#define G_TRANSACTION_TIMER(x) (((x) >> S_TRANSACTION_TIMER) & M_TRANSACTION_TIMER) + + +/* ULP registers */ +#define A_ULP_ULIMIT 0x980 +#define A_ULP_TAGMASK 0x984 +#define A_ULP_HREG_INDEX 0x988 +#define A_ULP_HREG_DATA 0x98c +#define A_ULP_INT_ENABLE 0x990 +#define A_ULP_INT_CAUSE 0x994 +#define S_HREG_PAR_ERR 0 +#define V_HREG_PAR_ERR(x) ((x) << S_HREG_PAR_ERR) +#define F_HREG_PAR_ERR V_HREG_PAR_ERR(1U) + +#define S_EGRS_DATA_PAR_ERR 1 +#define V_EGRS_DATA_PAR_ERR(x) ((x) << S_EGRS_DATA_PAR_ERR) +#define F_EGRS_DATA_PAR_ERR V_EGRS_DATA_PAR_ERR(1U) + +#define S_INGRS_DATA_PAR_ERR 2 +#define V_INGRS_DATA_PAR_ERR(x) ((x) << S_INGRS_DATA_PAR_ERR) +#define F_INGRS_DATA_PAR_ERR V_INGRS_DATA_PAR_ERR(1U) + +#define S_PM_INTR 3 +#define V_PM_INTR(x) ((x) << S_PM_INTR) +#define F_PM_INTR V_PM_INTR(1U) + +#define S_PM_E2C_SYNC_ERR 4 +#define V_PM_E2C_SYNC_ERR(x) ((x) << S_PM_E2C_SYNC_ERR) +#define F_PM_E2C_SYNC_ERR V_PM_E2C_SYNC_ERR(1U) + +#define S_PM_C2E_SYNC_ERR 5 +#define V_PM_C2E_SYNC_ERR(x) ((x) << S_PM_C2E_SYNC_ERR) +#define F_PM_C2E_SYNC_ERR V_PM_C2E_SYNC_ERR(1U) + +#define S_PM_E2C_EMPTY_ERR 6 +#define V_PM_E2C_EMPTY_ERR(x) ((x) << S_PM_E2C_EMPTY_ERR) +#define F_PM_E2C_EMPTY_ERR V_PM_E2C_EMPTY_ERR(1U) + +#define S_PM_C2E_EMPTY_ERR 7 +#define V_PM_C2E_EMPTY_ERR(x) ((x) << S_PM_C2E_EMPTY_ERR) +#define F_PM_C2E_EMPTY_ERR V_PM_C2E_EMPTY_ERR(1U) + +#define S_PM_PAR_ERR 8 +#define M_PM_PAR_ERR 0xffff +#define V_PM_PAR_ERR(x) ((x) << S_PM_PAR_ERR) +#define G_PM_PAR_ERR(x) (((x) >> S_PM_PAR_ERR) & M_PM_PAR_ERR) + +#define S_PM_E2C_WRT_FULL 24 +#define V_PM_E2C_WRT_FULL(x) ((x) << S_PM_E2C_WRT_FULL) +#define F_PM_E2C_WRT_FULL V_PM_E2C_WRT_FULL(1U) + +#define S_PM_C2E_WRT_FULL 25 +#define V_PM_C2E_WRT_FULL(x) ((x) << S_PM_C2E_WRT_FULL) +#define F_PM_C2E_WRT_FULL V_PM_C2E_WRT_FULL(1U) + +#define A_ULP_PIO_CTRL 0x998 + +/* PL registers */ #define A_PL_ENABLE 0xa00 #define S_PL_INTR_SGE_ERR 0 @@ -407,14 +1752,38 @@ #define V_PL_INTR_SGE_DATA(x) ((x) << S_PL_INTR_SGE_DATA) #define F_PL_INTR_SGE_DATA V_PL_INTR_SGE_DATA(1U) +#define S_PL_INTR_MC3 2 +#define V_PL_INTR_MC3(x) ((x) << S_PL_INTR_MC3) +#define F_PL_INTR_MC3 V_PL_INTR_MC3(1U) + +#define S_PL_INTR_MC4 3 +#define V_PL_INTR_MC4(x) ((x) << S_PL_INTR_MC4) +#define F_PL_INTR_MC4 V_PL_INTR_MC4(1U) + +#define S_PL_INTR_MC5 4 +#define V_PL_INTR_MC5(x) ((x) << S_PL_INTR_MC5) +#define F_PL_INTR_MC5 V_PL_INTR_MC5(1U) + +#define S_PL_INTR_RAT 5 +#define V_PL_INTR_RAT(x) ((x) << S_PL_INTR_RAT) +#define F_PL_INTR_RAT V_PL_INTR_RAT(1U) + #define S_PL_INTR_TP 6 #define V_PL_INTR_TP(x) ((x) << S_PL_INTR_TP) #define F_PL_INTR_TP V_PL_INTR_TP(1U) +#define S_PL_INTR_ULP 7 +#define V_PL_INTR_ULP(x) ((x) << S_PL_INTR_ULP) +#define F_PL_INTR_ULP V_PL_INTR_ULP(1U) + #define S_PL_INTR_ESPI 8 #define V_PL_INTR_ESPI(x) ((x) << S_PL_INTR_ESPI) #define F_PL_INTR_ESPI V_PL_INTR_ESPI(1U) +#define S_PL_INTR_CSPI 9 +#define V_PL_INTR_CSPI(x) ((x) << S_PL_INTR_CSPI) +#define F_PL_INTR_CSPI V_PL_INTR_CSPI(1U) + #define S_PL_INTR_PCIX 10 #define V_PL_INTR_PCIX(x) ((x) << S_PL_INTR_PCIX) #define F_PL_INTR_PCIX V_PL_INTR_PCIX(1U) @@ -426,43 +1795,374 @@ #define A_PL_CAUSE 0xa04 /* MC5 registers */ - #define A_MC5_CONFIG 0xc04 +#define S_MODE 0 +#define V_MODE(x) ((x) << S_MODE) +#define F_MODE V_MODE(1U) + #define S_TCAM_RESET 1 #define V_TCAM_RESET(x) ((x) << S_TCAM_RESET) #define F_TCAM_RESET V_TCAM_RESET(1U) +#define S_TCAM_READY 2 +#define V_TCAM_READY(x) ((x) << S_TCAM_READY) +#define F_TCAM_READY V_TCAM_READY(1U) + +#define S_DBGI_ENABLE 4 +#define V_DBGI_ENABLE(x) ((x) << S_DBGI_ENABLE) +#define F_DBGI_ENABLE V_DBGI_ENABLE(1U) + #define S_M_BUS_ENABLE 5 #define V_M_BUS_ENABLE(x) ((x) << S_M_BUS_ENABLE) #define F_M_BUS_ENABLE V_M_BUS_ENABLE(1U) -/* PCICFG registers */ +#define S_PARITY_ENABLE 6 +#define V_PARITY_ENABLE(x) ((x) << S_PARITY_ENABLE) +#define F_PARITY_ENABLE V_PARITY_ENABLE(1U) + +#define S_SYN_ISSUE_MODE 7 +#define M_SYN_ISSUE_MODE 0x3 +#define V_SYN_ISSUE_MODE(x) ((x) << S_SYN_ISSUE_MODE) +#define G_SYN_ISSUE_MODE(x) (((x) >> S_SYN_ISSUE_MODE) & M_SYN_ISSUE_MODE) + +#define S_BUILD 16 +#define V_BUILD(x) ((x) << S_BUILD) +#define F_BUILD V_BUILD(1U) + +#define S_COMPRESSION_ENABLE 17 +#define V_COMPRESSION_ENABLE(x) ((x) << S_COMPRESSION_ENABLE) +#define F_COMPRESSION_ENABLE V_COMPRESSION_ENABLE(1U) + +#define S_NUM_LIP 18 +#define M_NUM_LIP 0x3f +#define V_NUM_LIP(x) ((x) << S_NUM_LIP) +#define G_NUM_LIP(x) (((x) >> S_NUM_LIP) & M_NUM_LIP) + +#define S_TCAM_PART_CNT 24 +#define M_TCAM_PART_CNT 0x3 +#define V_TCAM_PART_CNT(x) ((x) << S_TCAM_PART_CNT) +#define G_TCAM_PART_CNT(x) (((x) >> S_TCAM_PART_CNT) & M_TCAM_PART_CNT) + +#define S_TCAM_PART_TYPE 26 +#define M_TCAM_PART_TYPE 0x3 +#define V_TCAM_PART_TYPE(x) ((x) << S_TCAM_PART_TYPE) +#define G_TCAM_PART_TYPE(x) (((x) >> S_TCAM_PART_TYPE) & M_TCAM_PART_TYPE) + +#define S_TCAM_PART_SIZE 28 +#define M_TCAM_PART_SIZE 0x3 +#define V_TCAM_PART_SIZE(x) ((x) << S_TCAM_PART_SIZE) +#define G_TCAM_PART_SIZE(x) (((x) >> S_TCAM_PART_SIZE) & M_TCAM_PART_SIZE) + +#define S_TCAM_PART_TYPE_HI 30 +#define V_TCAM_PART_TYPE_HI(x) ((x) << S_TCAM_PART_TYPE_HI) +#define F_TCAM_PART_TYPE_HI V_TCAM_PART_TYPE_HI(1U) + +#define A_MC5_SIZE 0xc08 + +#define S_SIZE 0 +#define M_SIZE 0x3fffff +#define V_SIZE(x) ((x) << S_SIZE) +#define G_SIZE(x) (((x) >> S_SIZE) & M_SIZE) + +#define A_MC5_ROUTING_TABLE_INDEX 0xc0c +#define S_START_OF_ROUTING_TABLE 0 +#define M_START_OF_ROUTING_TABLE 0x3fffff +#define V_START_OF_ROUTING_TABLE(x) ((x) << S_START_OF_ROUTING_TABLE) +#define G_START_OF_ROUTING_TABLE(x) (((x) >> S_START_OF_ROUTING_TABLE) & M_START_OF_ROUTING_TABLE) + +#define A_MC5_SERVER_INDEX 0xc14 + +#define S_START_OF_SERVER_INDEX 0 +#define M_START_OF_SERVER_INDEX 0x3fffff +#define V_START_OF_SERVER_INDEX(x) ((x) << S_START_OF_SERVER_INDEX) +#define G_START_OF_SERVER_INDEX(x) (((x) >> S_START_OF_SERVER_INDEX) & M_START_OF_SERVER_INDEX) + +#define A_MC5_LIP_RAM_ADDR 0xc18 + +#define S_LOCAL_IP_RAM_ADDR 0 +#define M_LOCAL_IP_RAM_ADDR 0x3f +#define V_LOCAL_IP_RAM_ADDR(x) ((x) << S_LOCAL_IP_RAM_ADDR) +#define G_LOCAL_IP_RAM_ADDR(x) (((x) >> S_LOCAL_IP_RAM_ADDR) & M_LOCAL_IP_RAM_ADDR) + +#define S_RAM_WRITE_ENABLE 8 +#define V_RAM_WRITE_ENABLE(x) ((x) << S_RAM_WRITE_ENABLE) +#define F_RAM_WRITE_ENABLE V_RAM_WRITE_ENABLE(1U) + +#define A_MC5_LIP_RAM_DATA 0xc1c +#define A_MC5_RSP_LATENCY 0xc20 + +#define S_SEARCH_RESPONSE_LATENCY 0 +#define M_SEARCH_RESPONSE_LATENCY 0x1f +#define V_SEARCH_RESPONSE_LATENCY(x) ((x) << S_SEARCH_RESPONSE_LATENCY) +#define G_SEARCH_RESPONSE_LATENCY(x) (((x) >> S_SEARCH_RESPONSE_LATENCY) & M_SEARCH_RESPONSE_LATENCY) + +#define S_LEARN_RESPONSE_LATENCY 8 +#define M_LEARN_RESPONSE_LATENCY 0x1f +#define V_LEARN_RESPONSE_LATENCY(x) ((x) << S_LEARN_RESPONSE_LATENCY) +#define G_LEARN_RESPONSE_LATENCY(x) (((x) >> S_LEARN_RESPONSE_LATENCY) & M_LEARN_RESPONSE_LATENCY) + +#define A_MC5_PARITY_LATENCY 0xc24 + +#define S_SRCHLAT 0 +#define M_SRCHLAT 0x1f +#define V_SRCHLAT(x) ((x) << S_SRCHLAT) +#define G_SRCHLAT(x) (((x) >> S_SRCHLAT) & M_SRCHLAT) + +#define S_PARLAT 8 +#define M_PARLAT 0x1f +#define V_PARLAT(x) ((x) << S_PARLAT) +#define G_PARLAT(x) (((x) >> S_PARLAT) & M_PARLAT) + +#define A_MC5_WR_LRN_VERIFY 0xc28 + +#define S_POVEREN 0 +#define V_POVEREN(x) ((x) << S_POVEREN) +#define F_POVEREN V_POVEREN(1U) + +#define S_LRNVEREN 1 +#define V_LRNVEREN(x) ((x) << S_LRNVEREN) +#define F_LRNVEREN V_LRNVEREN(1U) + +#define S_VWVEREN 2 +#define V_VWVEREN(x) ((x) << S_VWVEREN) +#define F_VWVEREN V_VWVEREN(1U) + +#define A_MC5_PART_ID_INDEX 0xc2c + +#define S_IDINDEX 0 +#define M_IDINDEX 0xf +#define V_IDINDEX(x) ((x) << S_IDINDEX) +#define G_IDINDEX(x) (((x) >> S_IDINDEX) & M_IDINDEX) + +#define A_MC5_RESET_MAX 0xc30 + +#define S_RSTMAX 0 +#define M_RSTMAX 0x1ff +#define V_RSTMAX(x) ((x) << S_RSTMAX) +#define G_RSTMAX(x) (((x) >> S_RSTMAX) & M_RSTMAX) + +#define A_MC5_INT_ENABLE 0xc40 + +#define S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR 0 +#define V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR) +#define F_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR V_MC5_INT_HIT_OUT_ACTIVE_REGION_ERR(1U) + +#define S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR 1 +#define V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_ACTIVE_REGION_ERR) +#define F_MC5_INT_HIT_IN_ACTIVE_REGION_ERR V_MC5_INT_HIT_IN_ACTIVE_REGION_ERR(1U) + +#define S_MC5_INT_HIT_IN_RT_REGION_ERR 2 +#define V_MC5_INT_HIT_IN_RT_REGION_ERR(x) ((x) << S_MC5_INT_HIT_IN_RT_REGION_ERR) +#define F_MC5_INT_HIT_IN_RT_REGION_ERR V_MC5_INT_HIT_IN_RT_REGION_ERR(1U) + +#define S_MC5_INT_MISS_ERR 3 +#define V_MC5_INT_MISS_ERR(x) ((x) << S_MC5_INT_MISS_ERR) +#define F_MC5_INT_MISS_ERR V_MC5_INT_MISS_ERR(1U) + +#define S_MC5_INT_LIP0_ERR 4 +#define V_MC5_INT_LIP0_ERR(x) ((x) << S_MC5_INT_LIP0_ERR) +#define F_MC5_INT_LIP0_ERR V_MC5_INT_LIP0_ERR(1U) + +#define S_MC5_INT_LIP_MISS_ERR 5 +#define V_MC5_INT_LIP_MISS_ERR(x) ((x) << S_MC5_INT_LIP_MISS_ERR) +#define F_MC5_INT_LIP_MISS_ERR V_MC5_INT_LIP_MISS_ERR(1U) + +#define S_MC5_INT_PARITY_ERR 6 +#define V_MC5_INT_PARITY_ERR(x) ((x) << S_MC5_INT_PARITY_ERR) +#define F_MC5_INT_PARITY_ERR V_MC5_INT_PARITY_ERR(1U) + +#define S_MC5_INT_ACTIVE_REGION_FULL 7 +#define V_MC5_INT_ACTIVE_REGION_FULL(x) ((x) << S_MC5_INT_ACTIVE_REGION_FULL) +#define F_MC5_INT_ACTIVE_REGION_FULL V_MC5_INT_ACTIVE_REGION_FULL(1U) + +#define S_MC5_INT_NFA_SRCH_ERR 8 +#define V_MC5_INT_NFA_SRCH_ERR(x) ((x) << S_MC5_INT_NFA_SRCH_ERR) +#define F_MC5_INT_NFA_SRCH_ERR V_MC5_INT_NFA_SRCH_ERR(1U) + +#define S_MC5_INT_SYN_COOKIE 9 +#define V_MC5_INT_SYN_COOKIE(x) ((x) << S_MC5_INT_SYN_COOKIE) +#define F_MC5_INT_SYN_COOKIE V_MC5_INT_SYN_COOKIE(1U) + +#define S_MC5_INT_SYN_COOKIE_BAD 10 +#define V_MC5_INT_SYN_COOKIE_BAD(x) ((x) << S_MC5_INT_SYN_COOKIE_BAD) +#define F_MC5_INT_SYN_COOKIE_BAD V_MC5_INT_SYN_COOKIE_BAD(1U) + +#define S_MC5_INT_SYN_COOKIE_OFF 11 +#define V_MC5_INT_SYN_COOKIE_OFF(x) ((x) << S_MC5_INT_SYN_COOKIE_OFF) +#define F_MC5_INT_SYN_COOKIE_OFF V_MC5_INT_SYN_COOKIE_OFF(1U) + +#define S_MC5_INT_UNKNOWN_CMD 15 +#define V_MC5_INT_UNKNOWN_CMD(x) ((x) << S_MC5_INT_UNKNOWN_CMD) +#define F_MC5_INT_UNKNOWN_CMD V_MC5_INT_UNKNOWN_CMD(1U) + +#define S_MC5_INT_REQUESTQ_PARITY_ERR 16 +#define V_MC5_INT_REQUESTQ_PARITY_ERR(x) ((x) << S_MC5_INT_REQUESTQ_PARITY_ERR) +#define F_MC5_INT_REQUESTQ_PARITY_ERR V_MC5_INT_REQUESTQ_PARITY_ERR(1U) + +#define S_MC5_INT_DISPATCHQ_PARITY_ERR 17 +#define V_MC5_INT_DISPATCHQ_PARITY_ERR(x) ((x) << S_MC5_INT_DISPATCHQ_PARITY_ERR) +#define F_MC5_INT_DISPATCHQ_PARITY_ERR V_MC5_INT_DISPATCHQ_PARITY_ERR(1U) + +#define S_MC5_INT_DEL_ACT_EMPTY 18 +#define V_MC5_INT_DEL_ACT_EMPTY(x) ((x) << S_MC5_INT_DEL_ACT_EMPTY) +#define F_MC5_INT_DEL_ACT_EMPTY V_MC5_INT_DEL_ACT_EMPTY(1U) + +#define A_MC5_INT_CAUSE 0xc44 +#define A_MC5_INT_TID 0xc48 +#define A_MC5_INT_PTID 0xc4c +#define A_MC5_DBGI_CONFIG 0xc74 +#define A_MC5_DBGI_REQ_CMD 0xc78 + +#define S_CMDMODE 0 +#define M_CMDMODE 0x7 +#define V_CMDMODE(x) ((x) << S_CMDMODE) +#define G_CMDMODE(x) (((x) >> S_CMDMODE) & M_CMDMODE) + +#define S_SADRSEL 4 +#define V_SADRSEL(x) ((x) << S_SADRSEL) +#define F_SADRSEL V_SADRSEL(1U) + +#define S_WRITE_BURST_SIZE 22 +#define M_WRITE_BURST_SIZE 0x3ff +#define V_WRITE_BURST_SIZE(x) ((x) << S_WRITE_BURST_SIZE) +#define G_WRITE_BURST_SIZE(x) (((x) >> S_WRITE_BURST_SIZE) & M_WRITE_BURST_SIZE) + +#define A_MC5_DBGI_REQ_ADDR0 0xc7c +#define A_MC5_DBGI_REQ_ADDR1 0xc80 +#define A_MC5_DBGI_REQ_ADDR2 0xc84 +#define A_MC5_DBGI_REQ_DATA0 0xc88 +#define A_MC5_DBGI_REQ_DATA1 0xc8c +#define A_MC5_DBGI_REQ_DATA2 0xc90 +#define A_MC5_DBGI_REQ_DATA3 0xc94 +#define A_MC5_DBGI_REQ_DATA4 0xc98 +#define A_MC5_DBGI_REQ_MASK0 0xc9c +#define A_MC5_DBGI_REQ_MASK1 0xca0 +#define A_MC5_DBGI_REQ_MASK2 0xca4 +#define A_MC5_DBGI_REQ_MASK3 0xca8 +#define A_MC5_DBGI_REQ_MASK4 0xcac +#define A_MC5_DBGI_RSP_STATUS 0xcb0 + +#define S_DBGI_RSP_VALID 0 +#define V_DBGI_RSP_VALID(x) ((x) << S_DBGI_RSP_VALID) +#define F_DBGI_RSP_VALID V_DBGI_RSP_VALID(1U) + +#define S_DBGI_RSP_HIT 1 +#define V_DBGI_RSP_HIT(x) ((x) << S_DBGI_RSP_HIT) +#define F_DBGI_RSP_HIT V_DBGI_RSP_HIT(1U) + +#define S_DBGI_RSP_ERR 2 +#define V_DBGI_RSP_ERR(x) ((x) << S_DBGI_RSP_ERR) +#define F_DBGI_RSP_ERR V_DBGI_RSP_ERR(1U) + +#define S_DBGI_RSP_ERR_REASON 8 +#define M_DBGI_RSP_ERR_REASON 0x7 +#define V_DBGI_RSP_ERR_REASON(x) ((x) << S_DBGI_RSP_ERR_REASON) +#define G_DBGI_RSP_ERR_REASON(x) (((x) >> S_DBGI_RSP_ERR_REASON) & M_DBGI_RSP_ERR_REASON) + +#define A_MC5_DBGI_RSP_DATA0 0xcb4 +#define A_MC5_DBGI_RSP_DATA1 0xcb8 +#define A_MC5_DBGI_RSP_DATA2 0xcbc +#define A_MC5_DBGI_RSP_DATA3 0xcc0 +#define A_MC5_DBGI_RSP_DATA4 0xcc4 +#define A_MC5_DBGI_RSP_LAST_CMD 0xcc8 +#define A_MC5_POPEN_DATA_WR_CMD 0xccc +#define A_MC5_POPEN_MASK_WR_CMD 0xcd0 +#define A_MC5_AOPEN_SRCH_CMD 0xcd4 +#define A_MC5_AOPEN_LRN_CMD 0xcd8 +#define A_MC5_SYN_SRCH_CMD 0xcdc +#define A_MC5_SYN_LRN_CMD 0xce0 +#define A_MC5_ACK_SRCH_CMD 0xce4 +#define A_MC5_ACK_LRN_CMD 0xce8 +#define A_MC5_ILOOKUP_CMD 0xcec +#define A_MC5_ELOOKUP_CMD 0xcf0 +#define A_MC5_DATA_WRITE_CMD 0xcf4 +#define A_MC5_DATA_READ_CMD 0xcf8 +#define A_MC5_MASK_WRITE_CMD 0xcfc + +/* PCICFG registers */ #define A_PCICFG_PM_CSR 0x44 #define A_PCICFG_VPD_ADDR 0x4a +#define S_VPD_ADDR 0 +#define M_VPD_ADDR 0x7fff +#define V_VPD_ADDR(x) ((x) << S_VPD_ADDR) +#define G_VPD_ADDR(x) (((x) >> S_VPD_ADDR) & M_VPD_ADDR) + #define S_VPD_OP_FLAG 15 #define V_VPD_OP_FLAG(x) ((x) << S_VPD_OP_FLAG) #define F_VPD_OP_FLAG V_VPD_OP_FLAG(1U) #define A_PCICFG_VPD_DATA 0x4c - +#define A_PCICFG_PCIX_CMD 0x60 #define A_PCICFG_INTR_ENABLE 0xf4 -#define A_PCICFG_INTR_CAUSE 0xf8 +#define S_MASTER_PARITY_ERR 0 +#define V_MASTER_PARITY_ERR(x) ((x) << S_MASTER_PARITY_ERR) +#define F_MASTER_PARITY_ERR V_MASTER_PARITY_ERR(1U) + +#define S_SIG_TARGET_ABORT 1 +#define V_SIG_TARGET_ABORT(x) ((x) << S_SIG_TARGET_ABORT) +#define F_SIG_TARGET_ABORT V_SIG_TARGET_ABORT(1U) + +#define S_RCV_TARGET_ABORT 2 +#define V_RCV_TARGET_ABORT(x) ((x) << S_RCV_TARGET_ABORT) +#define F_RCV_TARGET_ABORT V_RCV_TARGET_ABORT(1U) + +#define S_RCV_MASTER_ABORT 3 +#define V_RCV_MASTER_ABORT(x) ((x) << S_RCV_MASTER_ABORT) +#define F_RCV_MASTER_ABORT V_RCV_MASTER_ABORT(1U) + +#define S_SIG_SYS_ERR 4 +#define V_SIG_SYS_ERR(x) ((x) << S_SIG_SYS_ERR) +#define F_SIG_SYS_ERR V_SIG_SYS_ERR(1U) + +#define S_DET_PARITY_ERR 5 +#define V_DET_PARITY_ERR(x) ((x) << S_DET_PARITY_ERR) +#define F_DET_PARITY_ERR V_DET_PARITY_ERR(1U) + +#define S_PIO_PARITY_ERR 6 +#define V_PIO_PARITY_ERR(x) ((x) << S_PIO_PARITY_ERR) +#define F_PIO_PARITY_ERR V_PIO_PARITY_ERR(1U) + +#define S_WF_PARITY_ERR 7 +#define V_WF_PARITY_ERR(x) ((x) << S_WF_PARITY_ERR) +#define F_WF_PARITY_ERR V_WF_PARITY_ERR(1U) + +#define S_RF_PARITY_ERR 8 +#define M_RF_PARITY_ERR 0x3 +#define V_RF_PARITY_ERR(x) ((x) << S_RF_PARITY_ERR) +#define G_RF_PARITY_ERR(x) (((x) >> S_RF_PARITY_ERR) & M_RF_PARITY_ERR) + +#define S_CF_PARITY_ERR 10 +#define M_CF_PARITY_ERR 0x3 +#define V_CF_PARITY_ERR(x) ((x) << S_CF_PARITY_ERR) +#define G_CF_PARITY_ERR(x) (((x) >> S_CF_PARITY_ERR) & M_CF_PARITY_ERR) + +#define A_PCICFG_INTR_CAUSE 0xf8 #define A_PCICFG_MODE 0xfc #define S_PCI_MODE_64BIT 0 #define V_PCI_MODE_64BIT(x) ((x) << S_PCI_MODE_64BIT) #define F_PCI_MODE_64BIT V_PCI_MODE_64BIT(1U) +#define S_PCI_MODE_66MHZ 1 +#define V_PCI_MODE_66MHZ(x) ((x) << S_PCI_MODE_66MHZ) +#define F_PCI_MODE_66MHZ V_PCI_MODE_66MHZ(1U) + +#define S_PCI_MODE_PCIX_INITPAT 2 +#define M_PCI_MODE_PCIX_INITPAT 0x7 +#define V_PCI_MODE_PCIX_INITPAT(x) ((x) << S_PCI_MODE_PCIX_INITPAT) +#define G_PCI_MODE_PCIX_INITPAT(x) (((x) >> S_PCI_MODE_PCIX_INITPAT) & M_PCI_MODE_PCIX_INITPAT) + #define S_PCI_MODE_PCIX 5 #define V_PCI_MODE_PCIX(x) ((x) << S_PCI_MODE_PCIX) #define F_PCI_MODE_PCIX V_PCI_MODE_PCIX(1U) #define S_PCI_MODE_CLK 6 #define M_PCI_MODE_CLK 0x3 +#define V_PCI_MODE_CLK(x) ((x) << S_PCI_MODE_CLK) #define G_PCI_MODE_CLK(x) (((x) >> S_PCI_MODE_CLK) & M_PCI_MODE_CLK) #endif /* _CXGB_REGS_H_ */ diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 9fb77c6d6c6b..26df2049d849 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -42,12 +42,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -57,10 +59,8 @@ #include "regs.h" #include "espi.h" - -#ifdef NETIF_F_TSO -#include -#endif +/* This belongs in if_ether.h */ +#define ETH_P_CPL5 0xf #define SGE_CMDQ_N 2 #define SGE_FREELQ_N 2 @@ -73,6 +73,7 @@ #define SGE_INTRTIMER_NRES 1000 #define SGE_RX_COPY_THRES 256 #define SGE_RX_SM_BUF_SIZE 1536 +#define SGE_TX_DESC_MAX_PLEN 16384 # define SGE_RX_DROP_THRES 2 @@ -184,17 +185,17 @@ struct cmdQ { unsigned long status; /* HW DMA fetch status */ unsigned int in_use; /* # of in-use command descriptors */ unsigned int size; /* # of descriptors */ - unsigned int processed; /* total # of descs HW has processed */ - unsigned int cleaned; /* total # of descs SW has reclaimed */ - unsigned int stop_thres; /* SW TX queue suspend threshold */ + unsigned int processed; /* total # of descs HW has processed */ + unsigned int cleaned; /* total # of descs SW has reclaimed */ + unsigned int stop_thres; /* SW TX queue suspend threshold */ u16 pidx; /* producer index (SW) */ u16 cidx; /* consumer index (HW) */ u8 genbit; /* current generation (=valid) bit */ - u8 sop; /* is next entry start of packet? */ + u8 sop; /* is next entry start of packet? */ struct cmdQ_e *entries; /* HW command descriptor Q */ struct cmdQ_ce *centries; /* SW command context descriptor Q */ - spinlock_t lock; /* Lock to protect cmdQ enqueuing */ dma_addr_t dma_addr; /* DMA addr HW command descriptor Q */ + spinlock_t lock; /* Lock to protect cmdQ enqueuing */ }; struct freelQ { @@ -203,8 +204,8 @@ struct freelQ { u16 pidx; /* producer index (SW) */ u16 cidx; /* consumer index (HW) */ u16 rx_buffer_size; /* Buffer size on this free list */ - u16 dma_offset; /* DMA offset to align IP headers */ - u16 recycleq_idx; /* skb recycle q to use */ + u16 dma_offset; /* DMA offset to align IP headers */ + u16 recycleq_idx; /* skb recycle q to use */ u8 genbit; /* current generation (=valid) bit */ struct freelQ_e *entries; /* HW freelist descriptor Q */ struct freelQ_ce *centries; /* SW freelist context descriptor Q */ @@ -226,6 +227,29 @@ enum { CMDQ_STAT_LAST_PKT_DB = 2 /* last packet rung the doorbell */ }; +/* T204 TX SW scheduler */ + +/* Per T204 TX port */ +struct sched_port { + unsigned int avail; /* available bits - quota */ + unsigned int drain_bits_per_1024ns; /* drain rate */ + unsigned int speed; /* drain rate, mbps */ + unsigned int mtu; /* mtu size */ + struct sk_buff_head skbq; /* pending skbs */ +}; + +/* Per T204 device */ +struct sched { + ktime_t last_updated; /* last time quotas were computed */ + unsigned int max_avail; /* max bits to be sent to any port */ + unsigned int port; /* port index (round robin ports) */ + unsigned int num; /* num skbs in per port queues */ + struct sched_port p[MAX_NPORTS]; + struct tasklet_struct sched_tsk;/* tasklet used to run scheduler */ +}; +static void restart_sched(unsigned long); + + /* * Main SGE data structure * @@ -243,17 +267,239 @@ struct sge { unsigned int rx_pkt_pad; /* RX padding for L2 packets */ unsigned int jumbo_fl; /* jumbo freelist Q index */ unsigned int intrtimer_nres; /* no-resource interrupt timer */ - unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */ + unsigned int fixed_intrtimer;/* non-adaptive interrupt timer */ struct timer_list tx_reclaim_timer; /* reclaims TX buffers */ struct timer_list espibug_timer; - unsigned int espibug_timeout; - struct sk_buff *espibug_skb; + unsigned long espibug_timeout; + struct sk_buff *espibug_skb[MAX_NPORTS]; u32 sge_control; /* shadow value of sge control reg */ struct sge_intr_counts stats; struct sge_port_stats port_stats[MAX_NPORTS]; + struct sched *tx_sched; struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp; }; +/* + * stop tasklet and free all pending skb's + */ +static void tx_sched_stop(struct sge *sge) +{ + struct sched *s = sge->tx_sched; + int i; + + tasklet_kill(&s->sched_tsk); + + for (i = 0; i < MAX_NPORTS; i++) + __skb_queue_purge(&s->p[s->port].skbq); +} + +/* + * t1_sched_update_parms() is called when the MTU or link speed changes. It + * re-computes scheduler parameters to scope with the change. + */ +unsigned int t1_sched_update_parms(struct sge *sge, unsigned int port, + unsigned int mtu, unsigned int speed) +{ + struct sched *s = sge->tx_sched; + struct sched_port *p = &s->p[port]; + unsigned int max_avail_segs; + + pr_debug("t1_sched_update_params mtu=%d speed=%d\n", mtu, speed); + if (speed) + p->speed = speed; + if (mtu) + p->mtu = mtu; + + if (speed || mtu) { + unsigned long long drain = 1024ULL * p->speed * (p->mtu - 40); + do_div(drain, (p->mtu + 50) * 1000); + p->drain_bits_per_1024ns = (unsigned int) drain; + + if (p->speed < 1000) + p->drain_bits_per_1024ns = + 90 * p->drain_bits_per_1024ns / 100; + } + + if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204) { + p->drain_bits_per_1024ns -= 16; + s->max_avail = max(4096U, p->mtu + 16 + 14 + 4); + max_avail_segs = max(1U, 4096 / (p->mtu - 40)); + } else { + s->max_avail = 16384; + max_avail_segs = max(1U, 9000 / (p->mtu - 40)); + } + + pr_debug("t1_sched_update_parms: mtu %u speed %u max_avail %u " + "max_avail_segs %u drain_bits_per_1024ns %u\n", p->mtu, + p->speed, s->max_avail, max_avail_segs, + p->drain_bits_per_1024ns); + + return max_avail_segs * (p->mtu - 40); +} + +/* + * t1_sched_max_avail_bytes() tells the scheduler the maximum amount of + * data that can be pushed per port. + */ +void t1_sched_set_max_avail_bytes(struct sge *sge, unsigned int val) +{ + struct sched *s = sge->tx_sched; + unsigned int i; + + s->max_avail = val; + for (i = 0; i < MAX_NPORTS; i++) + t1_sched_update_parms(sge, i, 0, 0); +} + +/* + * t1_sched_set_drain_bits_per_us() tells the scheduler at which rate a port + * is draining. + */ +void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port, + unsigned int val) +{ + struct sched *s = sge->tx_sched; + struct sched_port *p = &s->p[port]; + p->drain_bits_per_1024ns = val * 1024 / 1000; + t1_sched_update_parms(sge, port, 0, 0); +} + + +/* + * get_clock() implements a ns clock (see ktime_get) + */ +static inline ktime_t get_clock(void) +{ + struct timespec ts; + + ktime_get_ts(&ts); + return timespec_to_ktime(ts); +} + +/* + * tx_sched_init() allocates resources and does basic initialization. + */ +static int tx_sched_init(struct sge *sge) +{ + struct sched *s; + int i; + + s = kzalloc(sizeof (struct sched), GFP_KERNEL); + if (!s) + return -ENOMEM; + + pr_debug("tx_sched_init\n"); + tasklet_init(&s->sched_tsk, restart_sched, (unsigned long) sge); + sge->tx_sched = s; + + for (i = 0; i < MAX_NPORTS; i++) { + skb_queue_head_init(&s->p[i].skbq); + t1_sched_update_parms(sge, i, 1500, 1000); + } + + return 0; +} + +/* + * sched_update_avail() computes the delta since the last time it was called + * and updates the per port quota (number of bits that can be sent to the any + * port). + */ +static inline int sched_update_avail(struct sge *sge) +{ + struct sched *s = sge->tx_sched; + ktime_t now = get_clock(); + unsigned int i; + long long delta_time_ns; + + delta_time_ns = ktime_to_ns(ktime_sub(now, s->last_updated)); + + pr_debug("sched_update_avail delta=%lld\n", delta_time_ns); + if (delta_time_ns < 15000) + return 0; + + for (i = 0; i < MAX_NPORTS; i++) { + struct sched_port *p = &s->p[i]; + unsigned int delta_avail; + + delta_avail = (p->drain_bits_per_1024ns * delta_time_ns) >> 13; + p->avail = min(p->avail + delta_avail, s->max_avail); + } + + s->last_updated = now; + + return 1; +} + +/* + * sched_skb() is called from two different places. In the tx path, any + * packet generating load on an output port will call sched_skb() + * (skb != NULL). In addition, sched_skb() is called from the irq/soft irq + * context (skb == NULL). + * The scheduler only returns a skb (which will then be sent) if the + * length of the skb is <= the current quota of the output port. + */ +static struct sk_buff *sched_skb(struct sge *sge, struct sk_buff *skb, + unsigned int credits) +{ + struct sched *s = sge->tx_sched; + struct sk_buff_head *skbq; + unsigned int i, len, update = 1; + + pr_debug("sched_skb %p\n", skb); + if (!skb) { + if (!s->num) + return NULL; + } else { + skbq = &s->p[skb->dev->if_port].skbq; + __skb_queue_tail(skbq, skb); + s->num++; + skb = NULL; + } + + if (credits < MAX_SKB_FRAGS + 1) + goto out; + + again: + for (i = 0; i < MAX_NPORTS; i++) { + s->port = ++s->port & (MAX_NPORTS - 1); + skbq = &s->p[s->port].skbq; + + skb = skb_peek(skbq); + + if (!skb) + continue; + + len = skb->len; + if (len <= s->p[s->port].avail) { + s->p[s->port].avail -= len; + s->num--; + __skb_unlink(skb, skbq); + goto out; + } + skb = NULL; + } + + if (update-- && sched_update_avail(sge)) + goto again; + + out: + /* If there are more pending skbs, we use the hardware to schedule us + * again. + */ + if (s->num && !skb) { + struct cmdQ *q = &sge->cmdQ[0]; + clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status); + if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) { + set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status); + writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL); + } + } + pr_debug("sched_skb ret %p\n", skb); + + return skb; +} + /* * PIO to indicate that memory mapped Q contains valid descriptor(s). */ @@ -350,8 +596,11 @@ static int alloc_rx_resources(struct sge *sge, struct sge_params *p) sge->freelQ[!sge->jumbo_fl].rx_buffer_size = SGE_RX_SM_BUF_SIZE + sizeof(struct cpl_rx_data) + sge->freelQ[!sge->jumbo_fl].dma_offset; - sge->freelQ[sge->jumbo_fl].rx_buffer_size = (16 * 1024) - - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + size = (16 * 1024) - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + + sge->freelQ[sge->jumbo_fl].rx_buffer_size = size; /* * Setup which skb recycle Q should be used when recycling buffers from @@ -388,17 +637,23 @@ static void free_cmdQ_buffers(struct sge *sge, struct cmdQ *q, unsigned int n) q->in_use -= n; ce = &q->centries[cidx]; while (n--) { - if (q->sop) - pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr), - pci_unmap_len(ce, dma_len), - PCI_DMA_TODEVICE); - else - pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr), - pci_unmap_len(ce, dma_len), - PCI_DMA_TODEVICE); - q->sop = 0; + if (q->sop) { + if (likely(pci_unmap_len(ce, dma_len))) { + pci_unmap_single(pdev, + pci_unmap_addr(ce, dma_addr), + pci_unmap_len(ce, dma_len), + PCI_DMA_TODEVICE); + q->sop = 0; + } + } else { + if (likely(pci_unmap_len(ce, dma_len))) { + pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr), + pci_unmap_len(ce, dma_len), + PCI_DMA_TODEVICE); + } + } if (ce->skb) { - dev_kfree_skb(ce->skb); + dev_kfree_skb_any(ce->skb); q->sop = 1; } ce++; @@ -504,7 +759,7 @@ void t1_set_vlan_accel(struct adapter *adapter, int on_off) sge->sge_control |= F_VLAN_XTRACT; if (adapter->open_device_map) { writel(sge->sge_control, adapter->regs + A_SG_CONTROL); - readl(adapter->regs + A_SG_CONTROL); /* flush */ + readl(adapter->regs + A_SG_CONTROL); /* flush */ } } @@ -538,7 +793,6 @@ static void configure_sge(struct sge *sge, struct sge_params *p) sge->sge_control = F_CMDQ0_ENABLE | F_CMDQ1_ENABLE | F_FL0_ENABLE | F_FL1_ENABLE | F_CPL_ENABLE | F_RESPONSE_QUEUE_ENABLE | V_CMDQ_PRIORITY(2) | F_DISABLE_CMDQ1_GTS | F_ISCSI_COALESCE | - F_DISABLE_FL0_GTS | F_DISABLE_FL1_GTS | V_RX_PKT_OFFSET(sge->rx_pkt_pad); #if defined(__BIG_ENDIAN_BITFIELD) @@ -566,9 +820,7 @@ static inline unsigned int jumbo_payload_capacity(const struct sge *sge) */ void t1_sge_destroy(struct sge *sge) { - if (sge->espibug_skb) - kfree_skb(sge->espibug_skb); - + kfree(sge->tx_sched); free_tx_resources(sge); free_rx_resources(sge); kfree(sge); @@ -853,6 +1105,99 @@ static void unexpected_offload(struct adapter *adapter, struct freelQ *fl) recycle_fl_buf(fl, fl->cidx); } +/* + * T1/T2 SGE limits the maximum DMA size per TX descriptor to + * SGE_TX_DESC_MAX_PLEN (16KB). If the PAGE_SIZE is larger than 16KB, the + * stack might send more than SGE_TX_DESC_MAX_PLEN in a contiguous manner. + * Note that the *_large_page_tx_descs stuff will be optimized out when + * PAGE_SIZE <= SGE_TX_DESC_MAX_PLEN. + * + * compute_large_page_descs() computes how many additional descriptors are + * required to break down the stack's request. + */ +static inline unsigned int compute_large_page_tx_descs(struct sk_buff *skb) +{ + unsigned int count = 0; + if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) { + unsigned int nfrags = skb_shinfo(skb)->nr_frags; + unsigned int i, len = skb->len - skb->data_len; + while (len > SGE_TX_DESC_MAX_PLEN) { + count++; + len -= SGE_TX_DESC_MAX_PLEN; + } + for (i = 0; nfrags--; i++) { + skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + len = frag->size; + while (len > SGE_TX_DESC_MAX_PLEN) { + count++; + len -= SGE_TX_DESC_MAX_PLEN; + } + } + } + return count; +} + +/* + * Write a cmdQ entry. + * + * Since this function writes the 'flags' field, it must not be used to + * write the first cmdQ entry. + */ +static inline void write_tx_desc(struct cmdQ_e *e, dma_addr_t mapping, + unsigned int len, unsigned int gen, + unsigned int eop) +{ + if (unlikely(len > SGE_TX_DESC_MAX_PLEN)) + BUG(); + e->addr_lo = (u32)mapping; + e->addr_hi = (u64)mapping >> 32; + e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen); + e->flags = F_CMD_DATAVALID | V_CMD_EOP(eop) | V_CMD_GEN2(gen); +} + +/* + * See comment for previous function. + * + * write_tx_descs_large_page() writes additional SGE tx descriptors if + * *desc_len exceeds HW's capability. + */ +static inline unsigned int write_large_page_tx_descs(unsigned int pidx, + struct cmdQ_e **e, + struct cmdQ_ce **ce, + unsigned int *gen, + dma_addr_t *desc_mapping, + unsigned int *desc_len, + unsigned int nfrags, + struct cmdQ *q) +{ + if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN) { + struct cmdQ_e *e1 = *e; + struct cmdQ_ce *ce1 = *ce; + + while (*desc_len > SGE_TX_DESC_MAX_PLEN) { + *desc_len -= SGE_TX_DESC_MAX_PLEN; + write_tx_desc(e1, *desc_mapping, SGE_TX_DESC_MAX_PLEN, + *gen, nfrags == 0 && *desc_len == 0); + ce1->skb = NULL; + pci_unmap_len_set(ce1, dma_len, 0); + *desc_mapping += SGE_TX_DESC_MAX_PLEN; + if (*desc_len) { + ce1++; + e1++; + if (++pidx == q->size) { + pidx = 0; + *gen ^= 1; + ce1 = q->centries; + e1 = q->entries; + } + } + } + *e = e1; + *ce = ce1; + } + return pidx; +} + /* * Write the command descriptors to transmit the given skb starting at * descriptor pidx with the given generation. @@ -861,50 +1206,84 @@ static inline void write_tx_descs(struct adapter *adapter, struct sk_buff *skb, unsigned int pidx, unsigned int gen, struct cmdQ *q) { - dma_addr_t mapping; + dma_addr_t mapping, desc_mapping; struct cmdQ_e *e, *e1; struct cmdQ_ce *ce; - unsigned int i, flags, nfrags = skb_shinfo(skb)->nr_frags; + unsigned int i, flags, first_desc_len, desc_len, + nfrags = skb_shinfo(skb)->nr_frags; - mapping = pci_map_single(adapter->pdev, skb->data, - skb->len - skb->data_len, PCI_DMA_TODEVICE); + e = e1 = &q->entries[pidx]; ce = &q->centries[pidx]; + + mapping = pci_map_single(adapter->pdev, skb->data, + skb->len - skb->data_len, PCI_DMA_TODEVICE); + + desc_mapping = mapping; + desc_len = skb->len - skb->data_len; + + flags = F_CMD_DATAVALID | F_CMD_SOP | + V_CMD_EOP(nfrags == 0 && desc_len <= SGE_TX_DESC_MAX_PLEN) | + V_CMD_GEN2(gen); + first_desc_len = (desc_len <= SGE_TX_DESC_MAX_PLEN) ? + desc_len : SGE_TX_DESC_MAX_PLEN; + e->addr_lo = (u32)desc_mapping; + e->addr_hi = (u64)desc_mapping >> 32; + e->len_gen = V_CMD_LEN(first_desc_len) | V_CMD_GEN1(gen); + ce->skb = NULL; + pci_unmap_len_set(ce, dma_len, 0); + + if (PAGE_SIZE > SGE_TX_DESC_MAX_PLEN && + desc_len > SGE_TX_DESC_MAX_PLEN) { + desc_mapping += first_desc_len; + desc_len -= first_desc_len; + e1++; + ce++; + if (++pidx == q->size) { + pidx = 0; + gen ^= 1; + e1 = q->entries; + ce = q->centries; + } + pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen, + &desc_mapping, &desc_len, + nfrags, q); + + if (likely(desc_len)) + write_tx_desc(e1, desc_mapping, desc_len, gen, + nfrags == 0); + } + ce->skb = NULL; pci_unmap_addr_set(ce, dma_addr, mapping); pci_unmap_len_set(ce, dma_len, skb->len - skb->data_len); - flags = F_CMD_DATAVALID | F_CMD_SOP | V_CMD_EOP(nfrags == 0) | - V_CMD_GEN2(gen); - e = &q->entries[pidx]; - e->addr_lo = (u32)mapping; - e->addr_hi = (u64)mapping >> 32; - e->len_gen = V_CMD_LEN(skb->len - skb->data_len) | V_CMD_GEN1(gen); - for (e1 = e, i = 0; nfrags--; i++) { + for (i = 0; nfrags--; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - ce++; e1++; + ce++; if (++pidx == q->size) { pidx = 0; gen ^= 1; - ce = q->centries; e1 = q->entries; + ce = q->centries; } mapping = pci_map_page(adapter->pdev, frag->page, frag->page_offset, frag->size, PCI_DMA_TODEVICE); + desc_mapping = mapping; + desc_len = frag->size; + + pidx = write_large_page_tx_descs(pidx, &e1, &ce, &gen, + &desc_mapping, &desc_len, + nfrags, q); + if (likely(desc_len)) + write_tx_desc(e1, desc_mapping, desc_len, gen, + nfrags == 0); ce->skb = NULL; pci_unmap_addr_set(ce, dma_addr, mapping); pci_unmap_len_set(ce, dma_len, frag->size); - - e1->addr_lo = (u32)mapping; - e1->addr_hi = (u64)mapping >> 32; - e1->len_gen = V_CMD_LEN(frag->size) | V_CMD_GEN1(gen); - e1->flags = F_CMD_DATAVALID | V_CMD_EOP(nfrags == 0) | - V_CMD_GEN2(gen); } - ce->skb = skb; wmb(); e->flags = flags; @@ -918,14 +1297,56 @@ static inline void reclaim_completed_tx(struct sge *sge, struct cmdQ *q) unsigned int reclaim = q->processed - q->cleaned; if (reclaim) { + pr_debug("reclaim_completed_tx processed:%d cleaned:%d\n", + q->processed, q->cleaned); free_cmdQ_buffers(sge, q, reclaim); q->cleaned += reclaim; } } -#ifndef SET_ETHTOOL_OPS -# define __netif_rx_complete(dev) netif_rx_complete(dev) -#endif +/* + * Called from tasklet. Checks the scheduler for any + * pending skbs that can be sent. + */ +static void restart_sched(unsigned long arg) +{ + struct sge *sge = (struct sge *) arg; + struct adapter *adapter = sge->adapter; + struct cmdQ *q = &sge->cmdQ[0]; + struct sk_buff *skb; + unsigned int credits, queued_skb = 0; + + spin_lock(&q->lock); + reclaim_completed_tx(sge, q); + + credits = q->size - q->in_use; + pr_debug("restart_sched credits=%d\n", credits); + while ((skb = sched_skb(sge, NULL, credits)) != NULL) { + unsigned int genbit, pidx, count; + count = 1 + skb_shinfo(skb)->nr_frags; + count += compute_large_page_tx_descs(skb); + q->in_use += count; + genbit = q->genbit; + pidx = q->pidx; + q->pidx += count; + if (q->pidx >= q->size) { + q->pidx -= q->size; + q->genbit ^= 1; + } + write_tx_descs(adapter, skb, pidx, genbit, q); + credits = q->size - q->in_use; + queued_skb = 1; + } + + if (queued_skb) { + clear_bit(CMDQ_STAT_LAST_PKT_DB, &q->status); + if (test_and_set_bit(CMDQ_STAT_RUNNING, &q->status) == 0) { + set_bit(CMDQ_STAT_LAST_PKT_DB, &q->status); + writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL); + } + } + spin_unlock(&q->lock); +} /** * sge_rx - process an ingress ethernet packet @@ -953,6 +1374,11 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) p = (struct cpl_rx_pkt *)skb->data; skb_pull(skb, sizeof(*p)); skb->dev = adapter->port[p->iff].dev; + if (p->iff >= adapter->params.nports) { + kfree_skb(skb); + return 0; + } + skb->dev->last_rx = jiffies; skb->protocol = eth_type_trans(skb, skb->dev); if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && @@ -1025,18 +1451,24 @@ static unsigned int update_tx_info(struct adapter *adapter, struct cmdQ *cmdq = &sge->cmdQ[0]; cmdq->processed += pr0; - + if (flags & (F_FL0_ENABLE | F_FL1_ENABLE)) { + freelQs_empty(sge); + flags &= ~(F_FL0_ENABLE | F_FL1_ENABLE); + } if (flags & F_CMDQ0_ENABLE) { clear_bit(CMDQ_STAT_RUNNING, &cmdq->status); - + if (cmdq->cleaned + cmdq->in_use != cmdq->processed && !test_and_set_bit(CMDQ_STAT_LAST_PKT_DB, &cmdq->status)) { set_bit(CMDQ_STAT_RUNNING, &cmdq->status); writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL); } - flags &= ~F_CMDQ0_ENABLE; + if (sge->tx_sched) + tasklet_hi_schedule(&sge->tx_sched->sched_tsk); + + flags &= ~F_CMDQ0_ENABLE; } - + if (unlikely(sge->stopped_tx_queues != 0)) restart_tx_queues(sge); @@ -1233,14 +1665,15 @@ static irqreturn_t t1_interrupt_napi(int irq, void *data) printk(KERN_INFO "NAPI schedule failure!\n"); } else - writel(q->cidx, adapter->regs + A_SG_SLEEPING); + writel(q->cidx, adapter->regs + A_SG_SLEEPING); + handled = 1; goto unlock; } else - writel(q->cidx, adapter->regs + A_SG_SLEEPING); - } else - if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) - printk(KERN_ERR "data interrupt while NAPI running\n"); + writel(q->cidx, adapter->regs + A_SG_SLEEPING); + } else if (readl(adapter->regs + A_PL_CAUSE) & F_PL_INTR_SGE_DATA) { + printk(KERN_ERR "data interrupt while NAPI running\n"); + } handled = t1_slow_intr_handler(adapter); if (!handled) @@ -1321,7 +1754,7 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, { struct sge *sge = adapter->sge; struct cmdQ *q = &sge->cmdQ[qid]; - unsigned int credits, pidx, genbit, count; + unsigned int credits, pidx, genbit, count, use_sched_skb = 0; spin_lock(&q->lock); reclaim_completed_tx(sge, q); @@ -1329,26 +1762,49 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, pidx = q->pidx; credits = q->size - q->in_use; count = 1 + skb_shinfo(skb)->nr_frags; + count += compute_large_page_tx_descs(skb); - { /* Ethernet packet */ - if (unlikely(credits < count)) { + /* Ethernet packet */ + if (unlikely(credits < count)) { + if (!netif_queue_stopped(dev)) { netif_stop_queue(dev); set_bit(dev->if_port, &sge->stopped_tx_queues); sge->stats.cmdQ_full[2]++; - spin_unlock(&q->lock); - if (!netif_queue_stopped(dev)) - CH_ERR("%s: Tx ring full while queue awake!\n", - adapter->name); - return NETDEV_TX_BUSY; + CH_ERR("%s: Tx ring full while queue awake!\n", + adapter->name); } - if (unlikely(credits - count < q->stop_thres)) { - sge->stats.cmdQ_full[2]++; - netif_stop_queue(dev); - set_bit(dev->if_port, &sge->stopped_tx_queues); + spin_unlock(&q->lock); + return NETDEV_TX_BUSY; + } + + if (unlikely(credits - count < q->stop_thres)) { + netif_stop_queue(dev); + set_bit(dev->if_port, &sge->stopped_tx_queues); + sge->stats.cmdQ_full[2]++; + } + + /* T204 cmdQ0 skbs that are destined for a certain port have to go + * through the scheduler. + */ + if (sge->tx_sched && !qid && skb->dev) { + use_sched: + use_sched_skb = 1; + /* Note that the scheduler might return a different skb than + * the one passed in. + */ + skb = sched_skb(sge, skb, credits); + if (!skb) { + spin_unlock(&q->lock); + return NETDEV_TX_OK; } + pidx = q->pidx; + count = 1 + skb_shinfo(skb)->nr_frags; + count += compute_large_page_tx_descs(skb); } + q->in_use += count; genbit = q->genbit; + pidx = q->pidx; q->pidx += count; if (q->pidx >= q->size) { q->pidx -= q->size; @@ -1374,6 +1830,14 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, writel(F_CMDQ0_ENABLE, adapter->regs + A_SG_DOORBELL); } } + + if (use_sched_skb) { + if (spin_trylock(&q->lock)) { + credits = q->size - q->in_use; + skb = NULL; + goto use_sched; + } + } return NETDEV_TX_OK; } @@ -1402,8 +1866,10 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) struct sge *sge = adapter->sge; struct cpl_tx_pkt *cpl; -#ifdef NETIF_F_TSO - if (skb_is_gso(skb)) { + if (skb->protocol == htons(ETH_P_CPL5)) + goto send; + + if (skb_shinfo(skb)->gso_size) { int eth_type; struct cpl_tx_pkt_lso *hdr; @@ -1418,13 +1884,11 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr->ip_hdr_words = skb->nh.iph->ihl; hdr->tcp_hdr_words = skb->h.th->doff; hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type, - skb_shinfo(skb)->gso_size)); + skb_shinfo(skb)->gso_size)); hdr->len = htonl(skb->len - sizeof(*hdr)); cpl = (struct cpl_tx_pkt *)hdr; sge->stats.tx_lso_pkts++; - } else -#endif - { + } else { /* * Packets shorter than ETH_HLEN can break the MAC, drop them * early. Also, we may get oversized packets because some @@ -1433,6 +1897,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) */ if (unlikely(skb->len < ETH_HLEN || skb->len > dev->mtu + eth_hdr_len(skb->data))) { + pr_debug("%s: packet size %d hdr %d mtu%d\n", dev->name, + skb->len, eth_hdr_len(skb->data), dev->mtu); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -1442,10 +1908,12 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) * components, such as pktgen, do not handle it right. * Complain when this happens but try to fix things up. */ - if (unlikely(skb_headroom(skb) < - dev->hard_header_len - ETH_HLEN)) { + if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { struct sk_buff *orig_skb = skb; + pr_debug("%s: headroom %d header_len %d\n", dev->name, + skb_headroom(skb), dev->hard_header_len); + if (net_ratelimit()) printk(KERN_ERR "%s: inadequate headroom in " "Tx packet\n", dev->name); @@ -1457,19 +1925,21 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) if (!(adapter->flags & UDP_CSUM_CAPABLE) && skb->ip_summed == CHECKSUM_PARTIAL && - skb->nh.iph->protocol == IPPROTO_UDP) + skb->nh.iph->protocol == IPPROTO_UDP) { if (unlikely(skb_checksum_help(skb))) { + pr_debug("%s: unable to do udp checksum\n", dev->name); dev_kfree_skb_any(skb); return NETDEV_TX_OK; } + } /* Hmmm, assuming to catch the gratious arp... and we'll use * it to flush out stuck espi packets... - */ - if (unlikely(!adapter->sge->espibug_skb)) { + */ + if ((unlikely(!adapter->sge->espibug_skb[dev->if_port]))) { if (skb->protocol == htons(ETH_P_ARP) && skb->nh.arph->ar_op == htons(ARPOP_REQUEST)) { - adapter->sge->espibug_skb = skb; + adapter->sge->espibug_skb[dev->if_port] = skb; /* We want to re-use this skb later. We * simply bump the reference count and it * will not be freed... @@ -1499,6 +1969,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) #endif cpl->vlan_valid = 0; +send: dev->trans_start = jiffies; return t1_sge_tx(skb, adapter, 0, dev); } @@ -1518,10 +1989,9 @@ static void sge_tx_reclaim_cb(unsigned long data) continue; reclaim_completed_tx(sge, q); - if (i == 0 && q->in_use) /* flush pending credits */ - writel(F_CMDQ0_ENABLE, - sge->adapter->regs + A_SG_DOORBELL); - + if (i == 0 && q->in_use) { /* flush pending credits */ + writel(F_CMDQ0_ENABLE, sge->adapter->regs + A_SG_DOORBELL); + } spin_unlock(&q->lock); } mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); @@ -1568,11 +2038,20 @@ int t1_sge_configure(struct sge *sge, struct sge_params *p) */ void t1_sge_stop(struct sge *sge) { + int i; writel(0, sge->adapter->regs + A_SG_CONTROL); - (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */ + readl(sge->adapter->regs + A_SG_CONTROL); /* flush */ + if (is_T2(sge->adapter)) del_timer_sync(&sge->espibug_timer); + del_timer_sync(&sge->tx_reclaim_timer); + if (sge->tx_sched) + tx_sched_stop(sge); + + for (i = 0; i < MAX_NPORTS; i++) + if (sge->espibug_skb[i]) + kfree_skb(sge->espibug_skb[i]); } /* @@ -1585,48 +2064,86 @@ void t1_sge_start(struct sge *sge) writel(sge->sge_control, sge->adapter->regs + A_SG_CONTROL); doorbell_pio(sge->adapter, F_FL0_ENABLE | F_FL1_ENABLE); - (void) readl(sge->adapter->regs + A_SG_CONTROL); /* flush */ + readl(sge->adapter->regs + A_SG_CONTROL); /* flush */ mod_timer(&sge->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD); - if (is_T2(sge->adapter)) + if (is_T2(sge->adapter)) mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout); } /* * Callback for the T2 ESPI 'stuck packet feature' workaorund */ -static void espibug_workaround(void *data) +static void espibug_workaround_t204(unsigned long data) { struct adapter *adapter = (struct adapter *)data; struct sge *sge = adapter->sge; + unsigned int nports = adapter->params.nports; + u32 seop[MAX_NPORTS]; - if (netif_running(adapter->port[0].dev)) { - struct sk_buff *skb = sge->espibug_skb; - - u32 seop = t1_espi_get_mon(adapter, 0x930, 0); - - if ((seop & 0xfff0fff) == 0xfff && skb) { - if (!skb->cb[0]) { - u8 ch_mac_addr[ETH_ALEN] = - {0x0, 0x7, 0x43, 0x0, 0x0, 0x0}; - memcpy(skb->data + sizeof(struct cpl_tx_pkt), - ch_mac_addr, ETH_ALEN); - memcpy(skb->data + skb->len - 10, ch_mac_addr, - ETH_ALEN); - skb->cb[0] = 0xff; + if (adapter->open_device_map & PORT_MASK) { + int i; + if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0) { + return; + } + for (i = 0; i < nports; i++) { + struct sk_buff *skb = sge->espibug_skb[i]; + if ( (netif_running(adapter->port[i].dev)) && + !(netif_queue_stopped(adapter->port[i].dev)) && + (seop[i] && ((seop[i] & 0xfff) == 0)) && + skb ) { + if (!skb->cb[0]) { + u8 ch_mac_addr[ETH_ALEN] = + {0x0, 0x7, 0x43, 0x0, 0x0, 0x0}; + memcpy(skb->data + sizeof(struct cpl_tx_pkt), + ch_mac_addr, ETH_ALEN); + memcpy(skb->data + skb->len - 10, + ch_mac_addr, ETH_ALEN); + skb->cb[0] = 0xff; + } + + /* bump the reference count to avoid freeing of + * the skb once the DMA has completed. + */ + skb = skb_get(skb); + t1_sge_tx(skb, adapter, 0, adapter->port[i].dev); } - - /* bump the reference count to avoid freeing of the - * skb once the DMA has completed. - */ - skb = skb_get(skb); - t1_sge_tx(skb, adapter, 0, adapter->port[0].dev); } } mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout); } +static void espibug_workaround(unsigned long data) +{ + struct adapter *adapter = (struct adapter *)data; + struct sge *sge = adapter->sge; + + if (netif_running(adapter->port[0].dev)) { + struct sk_buff *skb = sge->espibug_skb[0]; + u32 seop = t1_espi_get_mon(adapter, 0x930, 0); + + if ((seop & 0xfff0fff) == 0xfff && skb) { + if (!skb->cb[0]) { + u8 ch_mac_addr[ETH_ALEN] = + {0x0, 0x7, 0x43, 0x0, 0x0, 0x0}; + memcpy(skb->data + sizeof(struct cpl_tx_pkt), + ch_mac_addr, ETH_ALEN); + memcpy(skb->data + skb->len - 10, ch_mac_addr, + ETH_ALEN); + skb->cb[0] = 0xff; + } + + /* bump the reference count to avoid freeing of the + * skb once the DMA has completed. + */ + skb = skb_get(skb); + t1_sge_tx(skb, adapter, 0, adapter->port[0].dev); + } + } + mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout); +} + /* * Creates a t1_sge structure and returns suggested resource parameters. */ @@ -1649,9 +2166,19 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, if (is_T2(sge->adapter)) { init_timer(&sge->espibug_timer); - sge->espibug_timer.function = (void *)&espibug_workaround; + + if (adapter->params.nports > 1) { + tx_sched_init(sge); + sge->espibug_timer.function = espibug_workaround_t204; + } else { + sge->espibug_timer.function = espibug_workaround; + } sge->espibug_timer.data = (unsigned long)sge->adapter; + sge->espibug_timeout = 1; + /* for T204, every 10ms */ + if (adapter->params.nports > 1) + sge->espibug_timeout = HZ/100; } @@ -1659,7 +2186,14 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, p->cmdQ_size[1] = SGE_CMDQ1_E_N; p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE; p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE; - p->rx_coalesce_usecs = 50; + if (sge->tx_sched) { + if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204) + p->rx_coalesce_usecs = 15; + else + p->rx_coalesce_usecs = 50; + } else + p->rx_coalesce_usecs = 50; + p->coalesce_enable = 0; p->sample_interval_usecs = 0; p->polling = 0; diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 91af47bab7be..4691c4f58e7f 100644 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h @@ -92,5 +92,9 @@ void t1_sge_intr_disable(struct sge *); void t1_sge_intr_clear(struct sge *); const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge); const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port); +void t1_sched_set_max_avail_bytes(struct sge *, unsigned int); +void t1_sched_set_drain_bits_per_us(struct sge *, unsigned int, unsigned int); +unsigned int t1_sched_update_parms(struct sge *, unsigned int, unsigned int, + unsigned int); #endif /* _CXGB_SGE_H_ */ diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index e4473ec43d26..d41d15a71e4d 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -43,6 +43,7 @@ #include "gmac.h" #include "cphy.h" #include "sge.h" +#include "tp.h" #include "espi.h" /** @@ -59,7 +60,7 @@ * otherwise. */ static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity, - int attempts, int delay) + int attempts, int delay) { while (1) { u32 val = readl(adapter->regs + reg) & mask; @@ -78,7 +79,7 @@ static int t1_wait_op_done(adapter_t *adapter, int reg, u32 mask, int polarity, /* * Write a register over the TPI interface (unlocked and locked versions). */ -static int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) +int __t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) { int tpi_busy; @@ -98,16 +99,16 @@ int t1_tpi_write(adapter_t *adapter, u32 addr, u32 value) { int ret; - spin_lock(&(adapter)->tpi_lock); + spin_lock(&adapter->tpi_lock); ret = __t1_tpi_write(adapter, addr, value); - spin_unlock(&(adapter)->tpi_lock); + spin_unlock(&adapter->tpi_lock); return ret; } /* * Read a register over the TPI interface (unlocked and locked versions). */ -static int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) +int __t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) { int tpi_busy; @@ -128,18 +129,26 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) { int ret; - spin_lock(&(adapter)->tpi_lock); + spin_lock(&adapter->tpi_lock); ret = __t1_tpi_read(adapter, addr, valp); - spin_unlock(&(adapter)->tpi_lock); + spin_unlock(&adapter->tpi_lock); return ret; } +/* + * Set a TPI parameter. + */ +static void t1_tpi_par(adapter_t *adapter, u32 value) +{ + writel(V_TPIPAR(value), adapter->regs + A_TPI_PAR); +} + /* * Called when a port's link settings change to propagate the new values to the * associated PHY and MAC. After performing the common tasks it invokes an * OS-specific handler. */ -/* static */ void link_changed(adapter_t *adapter, int port_id) +void t1_link_changed(adapter_t *adapter, int port_id) { int link_ok, speed, duplex, fc; struct cphy *phy = adapter->port[port_id].phy; @@ -159,7 +168,7 @@ int t1_tpi_read(adapter_t *adapter, u32 addr, u32 *valp) mac->ops->set_speed_duplex_fc(mac, speed, duplex, fc); lc->fc = (unsigned char)fc; } - t1_link_changed(adapter, port_id, link_ok, speed, duplex, fc); + t1_link_negotiated(adapter, port_id, link_ok, speed, duplex, fc); } static int t1_pci_intr_handler(adapter_t *adapter) @@ -217,7 +226,7 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, { u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); - spin_lock(&(adapter)->tpi_lock); + spin_lock(&adapter->tpi_lock); /* Write the address we want. */ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); @@ -227,12 +236,13 @@ static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); /* Write the operation we want. */ - __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ); + __t1_tpi_write(adapter, + A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_READ); mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); /* Read the data. */ __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); - spin_unlock(&(adapter)->tpi_lock); + spin_unlock(&adapter->tpi_lock); return 0; } @@ -241,7 +251,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, { u32 addr = V_MI1_REG_ADDR(mmd_addr) | V_MI1_PHY_ADDR(phy_addr); - spin_lock(&(adapter)->tpi_lock); + spin_lock(&adapter->tpi_lock); /* Write the address we want. */ __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); @@ -254,7 +264,7 @@ static int mi1_mdio_ext_write(adapter_t *adapter, int phy_addr, int mmd_addr, __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_OP, MI1_OP_INDIRECT_WRITE); mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); - spin_unlock(&(adapter)->tpi_lock); + spin_unlock(&adapter->tpi_lock); return 0; } @@ -265,12 +275,25 @@ static struct mdio_ops mi1_mdio_ext_ops = { }; enum { + CH_BRD_T110_1CU, CH_BRD_N110_1F, CH_BRD_N210_1F, + CH_BRD_T210_1F, + CH_BRD_T210_1CU, + CH_BRD_N204_4CU, }; static struct board_info t1_board[] = { +{ CHBT_BOARD_CHT110, 1/*ports#*/, + SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T1, + CHBT_MAC_PM3393, CHBT_PHY_MY3126, + 125000000/*clk-core*/, 150000000/*clk-mc3*/, 125000000/*clk-mc4*/, + 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/, + 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops, + &t1_my3126_ops, &mi1_mdio_ext_ops, + "Chelsio T110 1x10GBase-CX4 TOE" }, + { CHBT_BOARD_N110, 1/*ports#*/, SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE /*caps*/, CHBT_TERM_T1, CHBT_MAC_PM3393, CHBT_PHY_88X2010, @@ -289,12 +312,36 @@ static struct board_info t1_board[] = { &t1_mv88x201x_ops, &mi1_mdio_ext_ops, "Chelsio N210 1x10GBaseX NIC" }, +{ CHBT_BOARD_CHT210, 1/*ports#*/, + SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2, + CHBT_MAC_PM3393, CHBT_PHY_88X2010, + 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/, + 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/, + 0/*mdiinv*/, 1/*mdc*/, 0/*phybaseaddr*/, &t1_pm3393_ops, + &t1_mv88x201x_ops, &mi1_mdio_ext_ops, + "Chelsio T210 1x10GBaseX TOE" }, + +{ CHBT_BOARD_CHT210, 1/*ports#*/, + SUPPORTED_10000baseT_Full /*caps*/, CHBT_TERM_T2, + CHBT_MAC_PM3393, CHBT_PHY_MY3126, + 125000000/*clk-core*/, 133000000/*clk-mc3*/, 125000000/*clk-mc4*/, + 1/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 1/*mdien*/, + 1/*mdiinv*/, 1/*mdc*/, 1/*phybaseaddr*/, &t1_pm3393_ops, + &t1_my3126_ops, &mi1_mdio_ext_ops, + "Chelsio T210 1x10GBase-CX4 TOE" }, + + }; struct pci_device_id t1_pci_tbl[] = { + CH_DEVICE(8, 0, CH_BRD_T110_1CU), + CH_DEVICE(8, 1, CH_BRD_T110_1CU), CH_DEVICE(7, 0, CH_BRD_N110_1F), CH_DEVICE(10, 1, CH_BRD_N210_1F), - { 0, } + CH_DEVICE(11, 1, CH_BRD_T210_1F), + CH_DEVICE(14, 1, CH_BRD_T210_1CU), + CH_DEVICE(16, 1, CH_BRD_N204_4CU), + { 0 } }; MODULE_DEVICE_TABLE(pci, t1_pci_tbl); @@ -390,9 +437,14 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) if (lc->supported & SUPPORTED_Autoneg) { lc->advertising &= ~(ADVERTISED_ASYM_PAUSE | ADVERTISED_PAUSE); if (fc) { - lc->advertising |= ADVERTISED_ASYM_PAUSE; - if (fc == (PAUSE_RX | PAUSE_TX)) + if (fc == ((PAUSE_RX | PAUSE_TX) & + (mac->adapter->params.nports < 2))) lc->advertising |= ADVERTISED_PAUSE; + else { + lc->advertising |= ADVERTISED_ASYM_PAUSE; + if (fc == PAUSE_RX) + lc->advertising |= ADVERTISED_PAUSE; + } } phy->ops->advertise(phy, lc->advertising); @@ -403,11 +455,15 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) mac->ops->set_speed_duplex_fc(mac, lc->speed, lc->duplex, fc); /* Also disables autoneg */ + phy->state = PHY_AUTONEG_RDY; phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex); phy->ops->reset(phy, 0); - } else + } else { + phy->state = PHY_AUTONEG_EN; phy->ops->autoneg_enable(phy); /* also resets PHY */ + } } else { + phy->state = PHY_AUTONEG_RDY; mac->ops->set_speed_duplex_fc(mac, -1, -1, fc); lc->fc = (unsigned char)fc; phy->ops->reset(phy, 0); @@ -418,7 +474,7 @@ int t1_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc) /* * External interrupt handler for boards using elmer0. */ -int elmer0_ext_intr_handler(adapter_t *adapter) +int t1_elmer0_ext_intr_handler(adapter_t *adapter) { struct cphy *phy; int phy_cause; @@ -427,14 +483,33 @@ int elmer0_ext_intr_handler(adapter_t *adapter) t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); switch (board_info(adapter)->board) { + case CHBT_BOARD_CHT210: case CHBT_BOARD_N210: case CHBT_BOARD_N110: if (cause & ELMER0_GP_BIT6) { /* Marvell 88x2010 interrupt */ phy = adapter->port[0].phy; phy_cause = phy->ops->interrupt_handler(phy); if (phy_cause & cphy_cause_link_change) - link_changed(adapter, 0); + t1_link_changed(adapter, 0); + } + break; + case CHBT_BOARD_8000: + case CHBT_BOARD_CHT110: + CH_DBG(adapter, INTR, "External interrupt cause 0x%x\n", + cause); + if (cause & ELMER0_GP_BIT1) { /* PMC3393 INTB */ + struct cmac *mac = adapter->port[0].mac; + + mac->ops->interrupt_handler(mac); } + if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */ + u32 mod_detect; + + t1_tpi_read(adapter, + A_ELMER0_GPI_STAT, &mod_detect); + CH_MSG(adapter, INFO, LINK, "XPAK %s\n", + mod_detect ? "removed" : "inserted"); + } break; } t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); @@ -445,11 +520,11 @@ int elmer0_ext_intr_handler(adapter_t *adapter) void t1_interrupts_enable(adapter_t *adapter) { unsigned int i; - u32 pl_intr; - adapter->slow_intr_mask = F_PL_INTR_SGE_ERR; + adapter->slow_intr_mask = F_PL_INTR_SGE_ERR | F_PL_INTR_TP; t1_sge_intr_enable(adapter->sge); + t1_tp_intr_enable(adapter->tp); if (adapter->espi) { adapter->slow_intr_mask |= F_PL_INTR_ESPI; t1_espi_intr_enable(adapter->espi); @@ -462,15 +537,17 @@ void t1_interrupts_enable(adapter_t *adapter) } /* Enable PCIX & external chip interrupts on ASIC boards. */ - pl_intr = readl(adapter->regs + A_PL_ENABLE); + if (t1_is_asic(adapter)) { + u32 pl_intr = readl(adapter->regs + A_PL_ENABLE); - /* PCI-X interrupts */ - pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, - 0xffffffff); + /* PCI-X interrupts */ + pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, + 0xffffffff); - adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX; - pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX; - writel(pl_intr, adapter->regs + A_PL_ENABLE); + adapter->slow_intr_mask |= F_PL_INTR_EXT | F_PL_INTR_PCIX; + pl_intr |= F_PL_INTR_EXT | F_PL_INTR_PCIX; + writel(pl_intr, adapter->regs + A_PL_ENABLE); + } } /* Disables all interrupts. */ @@ -479,6 +556,7 @@ void t1_interrupts_disable(adapter_t* adapter) unsigned int i; t1_sge_intr_disable(adapter->sge); + t1_tp_intr_disable(adapter->tp); if (adapter->espi) t1_espi_intr_disable(adapter->espi); @@ -489,7 +567,8 @@ void t1_interrupts_disable(adapter_t* adapter) } /* Disable PCIX & external chip interrupts. */ - writel(0, adapter->regs + A_PL_ENABLE); + if (t1_is_asic(adapter)) + writel(0, adapter->regs + A_PL_ENABLE); /* PCI-X interrupts */ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_ENABLE, 0); @@ -501,10 +580,9 @@ void t1_interrupts_disable(adapter_t* adapter) void t1_interrupts_clear(adapter_t* adapter) { unsigned int i; - u32 pl_intr; - t1_sge_intr_clear(adapter->sge); + t1_tp_intr_clear(adapter->tp); if (adapter->espi) t1_espi_intr_clear(adapter->espi); @@ -515,10 +593,12 @@ void t1_interrupts_clear(adapter_t* adapter) } /* Enable interrupts for external devices. */ - pl_intr = readl(adapter->regs + A_PL_CAUSE); + if (t1_is_asic(adapter)) { + u32 pl_intr = readl(adapter->regs + A_PL_CAUSE); - writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX, - adapter->regs + A_PL_CAUSE); + writel(pl_intr | F_PL_INTR_EXT | F_PL_INTR_PCIX, + adapter->regs + A_PL_CAUSE); + } /* PCI-X interrupts */ pci_write_config_dword(adapter->pdev, A_PCICFG_INTR_CAUSE, 0xffffffff); @@ -527,7 +607,7 @@ void t1_interrupts_clear(adapter_t* adapter) /* * Slow path interrupt handler for ASICs. */ -int t1_slow_intr_handler(adapter_t *adapter) +static int asic_slow_intr(adapter_t *adapter) { u32 cause = readl(adapter->regs + A_PL_CAUSE); @@ -536,89 +616,50 @@ int t1_slow_intr_handler(adapter_t *adapter) return 0; if (cause & F_PL_INTR_SGE_ERR) t1_sge_intr_error_handler(adapter->sge); + if (cause & F_PL_INTR_TP) + t1_tp_intr_handler(adapter->tp); if (cause & F_PL_INTR_ESPI) t1_espi_intr_handler(adapter->espi); if (cause & F_PL_INTR_PCIX) t1_pci_intr_handler(adapter); if (cause & F_PL_INTR_EXT) - t1_elmer0_ext_intr(adapter); + t1_elmer0_ext_intr_handler(adapter); /* Clear the interrupts just processed. */ writel(cause, adapter->regs + A_PL_CAUSE); - (void)readl(adapter->regs + A_PL_CAUSE); /* flush writes */ + readl(adapter->regs + A_PL_CAUSE); /* flush writes */ return 1; } -/* Pause deadlock avoidance parameters */ -#define DROP_MSEC 16 -#define DROP_PKTS_CNT 1 - -static void set_csum_offload(adapter_t *adapter, u32 csum_bit, int enable) -{ - u32 val = readl(adapter->regs + A_TP_GLOBAL_CONFIG); - - if (enable) - val |= csum_bit; - else - val &= ~csum_bit; - writel(val, adapter->regs + A_TP_GLOBAL_CONFIG); -} - -void t1_tp_set_ip_checksum_offload(adapter_t *adapter, int enable) -{ - set_csum_offload(adapter, F_IP_CSUM, enable); -} - -void t1_tp_set_udp_checksum_offload(adapter_t *adapter, int enable) +int t1_slow_intr_handler(adapter_t *adapter) { - set_csum_offload(adapter, F_UDP_CSUM, enable); + return asic_slow_intr(adapter); } -void t1_tp_set_tcp_checksum_offload(adapter_t *adapter, int enable) +/* Power sequencing is a work-around for Intel's XPAKs. */ +static void power_sequence_xpak(adapter_t* adapter) { - set_csum_offload(adapter, F_TCP_CSUM, enable); -} + u32 mod_detect; + u32 gpo; -static void t1_tp_reset(adapter_t *adapter, unsigned int tp_clk) -{ - u32 val; - - val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | - F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; - val |= F_TP_IN_ESPI_CHECK_IP_CSUM | - F_TP_IN_ESPI_CHECK_TCP_CSUM; - writel(val, adapter->regs + A_TP_IN_CONFIG); - writel(F_TP_OUT_CSPI_CPL | - F_TP_OUT_ESPI_ETHERNET | - F_TP_OUT_ESPI_GENERATE_IP_CSUM | - F_TP_OUT_ESPI_GENERATE_TCP_CSUM, - adapter->regs + A_TP_OUT_CONFIG); - - val = readl(adapter->regs + A_TP_GLOBAL_CONFIG); - val &= ~(F_IP_CSUM | F_UDP_CSUM | F_TCP_CSUM); - writel(val, adapter->regs + A_TP_GLOBAL_CONFIG); - - /* - * Enable pause frame deadlock prevention. - */ - if (is_T2(adapter)) { - u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); - - writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | - V_DROP_TICKS_CNT(drop_ticks) | - V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), - adapter->regs + A_TP_TX_DROP_CONFIG); + /* Check for XPAK */ + t1_tpi_read(adapter, A_ELMER0_GPI_STAT, &mod_detect); + if (!(ELMER0_GP_BIT5 & mod_detect)) { + /* XPAK is present */ + t1_tpi_read(adapter, A_ELMER0_GPO, &gpo); + gpo |= ELMER0_GP_BIT18; + t1_tpi_write(adapter, A_ELMER0_GPO, gpo); } - - writel(F_TP_RESET, adapter->regs + A_TP_RESET); } int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, struct adapter_params *p) { p->chip_version = bi->chip_term; + p->is_asic = (p->chip_version != CHBT_TERM_FPGA); if (p->chip_version == CHBT_TERM_T1 || - p->chip_version == CHBT_TERM_T2) { + p->chip_version == CHBT_TERM_T2 || + p->chip_version == CHBT_TERM_FPGA) { u32 val = readl(adapter->regs + A_TP_PC_CONFIG); val = G_TP_PC_REV(val); @@ -640,10 +681,22 @@ int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi, static int board_init(adapter_t *adapter, const struct board_info *bi) { switch (bi->board) { + case CHBT_BOARD_8000: case CHBT_BOARD_N110: case CHBT_BOARD_N210: - writel(V_TPIPAR(0xf), adapter->regs + A_TPI_PAR); - t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); + case CHBT_BOARD_CHT210: + case CHBT_BOARD_COUGAR: + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x800); + break; + case CHBT_BOARD_CHT110: + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x1800); + + /* TBD XXX Might not need. This fixes a problem + * described in the Intel SR XPAK errata. + */ + power_sequence_xpak(adapter); break; } return 0; @@ -670,7 +723,8 @@ int t1_init_hw_modules(adapter_t *adapter) bi->espi_nports)) goto out_err; - t1_tp_reset(adapter, bi->clock_core); + if (t1_tp_reset(adapter->tp, &adapter->params.tp, bi->clock_core)) + goto out_err; err = t1_sge_configure(adapter->sge, &adapter->params.sge); if (err) @@ -714,6 +768,8 @@ void t1_free_sw_modules(adapter_t *adapter) if (adapter->sge) t1_sge_destroy(adapter->sge); + if (adapter->tp) + t1_tp_destroy(adapter->tp); if (adapter->espi) t1_espi_destroy(adapter->espi); } @@ -762,6 +818,13 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, goto error; } + adapter->tp = t1_tp_create(adapter, &adapter->params.tp); + if (!adapter->tp) { + CH_ERR("%s: TP initialization failed\n", + adapter->name); + goto error; + } + board_init(adapter, bi); bi->mdio_ops->init(adapter, bi); if (bi->gphy->reset) @@ -793,7 +856,9 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, * Get the port's MAC addresses either from the EEPROM if one * exists or the one hardcoded in the MAC. */ - if (vpd_macaddress_get(adapter, i, hw_addr)) { + if (!t1_is_asic(adapter) || bi->chip_mac == CHBT_MAC_DUMMY) + mac->ops->macaddress_get(mac, hw_addr); + else if (vpd_macaddress_get(adapter, i, hw_addr)) { CH_ERR("%s: could not read MAC address from VPD ROM\n", adapter->port[i].dev->name); goto error; @@ -806,7 +871,7 @@ int __devinit t1_init_sw_modules(adapter_t *adapter, t1_interrupts_clear(adapter); return 0; - error: +error: t1_free_sw_modules(adapter); return -1; } diff --git a/drivers/net/chelsio/suni1x10gexp_regs.h b/drivers/net/chelsio/suni1x10gexp_regs.h index 81816c2b708a..269d097dd927 100644 --- a/drivers/net/chelsio/suni1x10gexp_regs.h +++ b/drivers/net/chelsio/suni1x10gexp_regs.h @@ -32,6 +32,30 @@ #ifndef _CXGB_SUNI1x10GEXP_REGS_H_ #define _CXGB_SUNI1x10GEXP_REGS_H_ +/* +** Space allocated for each Exact Match Filter +** There are 8 filter configurations +*/ +#define SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER 0x0003 + +#define mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId) ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_FILTER ) + +/* +** Space allocated for VLAN-Id Filter +** There are 8 filter configurations +*/ +#define SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER 0x0001 + +#define mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId) ( (filterId) * SUNI1x10GEXP_REG_SIZEOF_MAC_VID_FILTER ) + +/* +** Space allocated for each MSTAT Counter +*/ +#define SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT 0x0004 + +#define mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId) ( (countId) * SUNI1x10GEXP_REG_SIZEOF_MSTAT_COUNT ) + + /******************************************************************************/ /** S/UNI-1x10GE-XP REGISTER ADDRESS MAP **/ /******************************************************************************/ @@ -39,33 +63,125 @@ /* to the S/UNI-1x10GE-XP Data Sheet for the signification of each bit */ /******************************************************************************/ + +#define SUNI1x10GEXP_REG_IDENTIFICATION 0x0000 +#define SUNI1x10GEXP_REG_PRODUCT_REVISION 0x0001 +#define SUNI1x10GEXP_REG_CONFIG_AND_RESET_CONTROL 0x0002 +#define SUNI1x10GEXP_REG_LOOPBACK_MISC_CTRL 0x0003 #define SUNI1x10GEXP_REG_DEVICE_STATUS 0x0004 +#define SUNI1x10GEXP_REG_GLOBAL_PERFORMANCE_MONITOR_UPDATE 0x0005 + +#define SUNI1x10GEXP_REG_MDIO_COMMAND 0x0006 +#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_ENABLE 0x0007 +#define SUNI1x10GEXP_REG_MDIO_INTERRUPT_STATUS 0x0008 +#define SUNI1x10GEXP_REG_MMD_PHY_ADDRESS 0x0009 +#define SUNI1x10GEXP_REG_MMD_CONTROL_ADDRESS_DATA 0x000A +#define SUNI1x10GEXP_REG_MDIO_READ_STATUS_DATA 0x000B + +#define SUNI1x10GEXP_REG_OAM_INTF_CTRL 0x000C #define SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS 0x000D #define SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE 0x000E +#define SUNI1x10GEXP_REG_FREE 0x000F + +#define SUNI1x10GEXP_REG_XTEF_MISC_CTRL 0x0010 +#define SUNI1x10GEXP_REG_XRF_MISC_CTRL 0x0011 + +#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_1 0x0100 +#define SUNI1x10GEXP_REG_SERDES_3125_CONFIG_2 0x0101 #define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE 0x0102 +#define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_VISIBLE 0x0103 #define SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS 0x0104 +#define SUNI1x10GEXP_REG_SERDES_3125_TEST_CONFIG 0x0107 + #define SUNI1x10GEXP_REG_RXXG_CONFIG_1 0x2040 +#define SUNI1x10GEXP_REG_RXXG_CONFIG_2 0x2041 #define SUNI1x10GEXP_REG_RXXG_CONFIG_3 0x2042 #define SUNI1x10GEXP_REG_RXXG_INTERRUPT 0x2043 #define SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH 0x2045 #define SUNI1x10GEXP_REG_RXXG_SA_15_0 0x2046 #define SUNI1x10GEXP_REG_RXXG_SA_31_16 0x2047 #define SUNI1x10GEXP_REG_RXXG_SA_47_32 0x2048 +#define SUNI1x10GEXP_REG_RXXG_RECEIVE_FIFO_THRESHOLD 0x2049 +#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_LOW(filterId) (0x204A + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId)) +#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_MID(filterId) (0x204B + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId)) +#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_HIGH(filterId)(0x204C + mSUNI1x10GEXP_MAC_FILTER_OFFSET(filterId)) +#define mSUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID(filterId) (0x2062 + mSUNI1x10GEXP_MAC_VID_FILTER_OFFSET(filterId) +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_LOW 0x204A +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_MID 0x204B +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_0_HIGH 0x204C #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW 0x204D #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID 0x204E #define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH 0x204F +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_LOW 0x2050 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_MID 0x2051 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_2_HIGH 0x2052 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_LOW 0x2053 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_MID 0x2054 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_3_HIGH 0x2055 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_LOW 0x2056 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_MID 0x2057 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_4_HIGH 0x2058 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_LOW 0x2059 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_MID 0x205A +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_5_HIGH 0x205B +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_LOW 0x205C +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_MID 0x205D +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_6_HIGH 0x205E +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_LOW 0x205F +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_MID 0x2060 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_7_HIGH 0x2061 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_0 0x2062 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_1 0x2063 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_2 0x2064 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_3 0x2065 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_4 0x2066 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_5 0x2067 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_6 0x2068 +#define SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_VID_7 0x2069 #define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW 0x206A #define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW 0x206B #define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH 0x206C #define SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH 0x206D #define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0 0x206E +#define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_1 0x206F #define SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2 0x2070 + +#define SUNI1x10GEXP_REG_XRF_PATTERN_GEN_CTRL 0x2081 +#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_0 0x2084 +#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_1 0x2085 +#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_2 0x2086 +#define SUNI1x10GEXP_REG_XRF_8BTB_ERR_COUNT_LANE_3 0x2087 #define SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE 0x2088 #define SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS 0x2089 +#define SUNI1x10GEXP_REG_XRF_ERR_STATUS 0x208A #define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE 0x208B #define SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS 0x208C +#define SUNI1x10GEXP_REG_XRF_CODE_ERR_THRES 0x2092 + +#define SUNI1x10GEXP_REG_RXOAM_CONFIG 0x20C0 +#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_CONFIG 0x20C1 +#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_CONFIG 0x20C2 +#define SUNI1x10GEXP_REG_RXOAM_CONFIG_2 0x20C3 +#define SUNI1x10GEXP_REG_RXOAM_HEC_CONFIG 0x20C4 +#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_THRES 0x20C5 #define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE 0x20C7 #define SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS 0x20C8 +#define SUNI1x10GEXP_REG_RXOAM_STATUS 0x20C9 +#define SUNI1x10GEXP_REG_RXOAM_HEC_ERR_COUNT 0x20CA +#define SUNI1x10GEXP_REG_RXOAM_FIFO_OVERFLOW_COUNT 0x20CB +#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_LSB 0x20CC +#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_COUNT_MSB 0x20CD +#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_LSB 0x20CE +#define SUNI1x10GEXP_REG_RXOAM_FILTER_1_MISMATCH_COUNT_MSB 0x20CF +#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_LSB 0x20D0 +#define SUNI1x10GEXP_REG_RXOAM_FILTER_2_MISMATCH_COUNT_MSB 0x20D1 +#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_LSB 0x20D2 +#define SUNI1x10GEXP_REG_RXOAM_OAM_EXTRACT_COUNT_MSB 0x20D3 +#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_LSB 0x20D4 +#define SUNI1x10GEXP_REG_RXOAM_MINI_PACKET_COUNT_MSB 0x20D5 +#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_LSB 0x20D6 +#define SUNI1x10GEXP_REG_RXOAM_FILTER_MISMATCH_THRES_MSB 0x20D7 + #define SUNI1x10GEXP_REG_MSTAT_CONTROL 0x2100 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0 0x2101 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1 0x2102 @@ -75,50 +191,321 @@ #define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1 0x2106 #define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2 0x2107 #define SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3 0x2108 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_ADDRESS 0x2109 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_LOW 0x210A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_MIDDLE 0x210B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_WRITE_DATA_HIGH 0x210C +#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_LOW(countId) (0x2110 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId)) +#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_MID(countId) (0x2111 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId)) +#define mSUNI1x10GEXP_REG_MSTAT_COUNTER_HIGH(countId) (0x2112 + mSUNI1x10GEXP_MSTAT_COUNT_OFFSET(countId)) #define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW 0x2110 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_MID 0x2111 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_HIGH 0x2112 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_0_RESVD 0x2113 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW 0x2114 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_MID 0x2115 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_HIGH 0x2116 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_1_RESVD 0x2117 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_LOW 0x2118 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_MID 0x2119 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_HIGH 0x211A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_2_RESVD 0x211B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_LOW 0x211C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_MID 0x211D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_HIGH 0x211E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_3_RESVD 0x211F #define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW 0x2120 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_MID 0x2121 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_HIGH 0x2122 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_4_RESVD 0x2123 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW 0x2124 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_MID 0x2125 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_HIGH 0x2126 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_5_RESVD 0x2127 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW 0x2128 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_MID 0x2129 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_HIGH 0x212A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_6_RESVD 0x212B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_LOW 0x212C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_MID 0x212D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_HIGH 0x212E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_7_RESVD 0x212F #define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW 0x2130 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_MID 0x2131 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_HIGH 0x2132 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_8_RESVD 0x2133 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_LOW 0x2134 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_MID 0x2135 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_HIGH 0x2136 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_9_RESVD 0x2137 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW 0x2138 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_MID 0x2139 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_HIGH 0x213A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_10_RESVD 0x213B #define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW 0x213C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_MID 0x213D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_HIGH 0x213E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_11_RESVD 0x213F #define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW 0x2140 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_MID 0x2141 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_HIGH 0x2142 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_12_RESVD 0x2143 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW 0x2144 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_MID 0x2145 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_HIGH 0x2146 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_13_RESVD 0x2147 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_LOW 0x2148 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_MID 0x2149 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_HIGH 0x214A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_14_RESVD 0x214B #define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW 0x214C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_MID 0x214D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_HIGH 0x214E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_15_RESVD 0x214F #define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW 0x2150 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_MID 0x2151 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_HIGH 0x2152 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_16_RESVD 0x2153 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW 0x2154 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_MID 0x2155 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_HIGH 0x2156 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_17_RESVD 0x2157 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW 0x2158 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_MID 0x2159 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_HIGH 0x215A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_18_RESVD 0x215B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_LOW 0x215C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_MID 0x215D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_HIGH 0x215E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_19_RESVD 0x215F +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_LOW 0x2160 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_MID 0x2161 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_HIGH 0x2162 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_20_RESVD 0x2163 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_LOW 0x2164 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_MID 0x2165 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_HIGH 0x2166 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_21_RESVD 0x2167 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_LOW 0x2168 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_MID 0x2169 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_HIGH 0x216A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_22_RESVD 0x216B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_LOW 0x216C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_MID 0x216D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_HIGH 0x216E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_23_RESVD 0x216F +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_LOW 0x2170 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_MID 0x2171 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_HIGH 0x2172 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_24_RESVD 0x2173 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW 0x2174 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_MID 0x2175 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_HIGH 0x2176 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_25_RESVD 0x2177 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW 0x2178 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_MID 0x2179 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_HIGH 0x217a +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_26_RESVD 0x217b +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_LOW 0x217c +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_MID 0x217d +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_HIGH 0x217e +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_27_RESVD 0x217f +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_LOW 0x2180 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_MID 0x2181 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_HIGH 0x2182 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_28_RESVD 0x2183 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_LOW 0x2184 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_MID 0x2185 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_HIGH 0x2186 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_29_RESVD 0x2187 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_LOW 0x2188 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_MID 0x2189 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_HIGH 0x218A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_30_RESVD 0x218B +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_LOW 0x218C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_MID 0x218D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_HIGH 0x218E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_31_RESVD 0x218F +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_LOW 0x2190 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_MID 0x2191 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_HIGH 0x2192 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_32_RESVD 0x2193 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW 0x2194 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_MID 0x2195 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_HIGH 0x2196 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_33_RESVD 0x2197 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_LOW 0x2198 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_MID 0x2199 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_HIGH 0x219A +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_34_RESVD 0x219B #define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW 0x219C +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_MID 0x219D +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_HIGH 0x219E +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_35_RESVD 0x219F #define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW 0x21A0 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_MID 0x21A1 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_HIGH 0x21A2 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_36_RESVD 0x21A3 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_LOW 0x21A4 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_MID 0x21A5 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_HIGH 0x21A6 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_37_RESVD 0x21A7 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW 0x21A8 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_MID 0x21A9 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_HIGH 0x21AA +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_38_RESVD 0x21AB +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_LOW 0x21AC +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_MID 0x21AD +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_HIGH 0x21AE +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_39_RESVD 0x21AF #define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW 0x21B0 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_MID 0x21B1 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_HIGH 0x21B2 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_40_RESVD 0x21B3 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_LOW 0x21B4 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_MID 0x21B5 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_HIGH 0x21B6 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_41_RESVD 0x21B7 #define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW 0x21B8 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_MID 0x21B9 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_HIGH 0x21BA +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_42_RESVD 0x21BB #define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW 0x21BC +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_MID 0x21BD +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_HIGH 0x21BE +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_43_RESVD 0x21BF +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_LOW 0x21C0 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_MID 0x21C1 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_HIGH 0x21C2 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_44_RESVD 0x21C3 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_LOW 0x21C4 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_MID 0x21C5 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_HIGH 0x21C6 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_45_RESVD 0x21C7 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_LOW 0x21C8 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_MID 0x21C9 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_HIGH 0x21CA +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_46_RESVD 0x21CB +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_LOW 0x21CC +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_MID 0x21CD +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_HIGH 0x21CE +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_47_RESVD 0x21CF +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_LOW 0x21D0 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_MID 0x21D1 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_HIGH 0x21D2 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_48_RESVD 0x21D3 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_LOW 0x21D4 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_MID 0x21D5 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_HIGH 0x21D6 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_49_RESVD 0x21D7 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_LOW 0x21D8 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_MID 0x21D9 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_HIGH 0x21DA +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_50_RESVD 0x21DB +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW 0x21DC +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_MID 0x21DD +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_HIGH 0x21DE +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_51_RESVD 0x21DF +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW 0x21E0 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_MID 0x21E1 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_HIGH 0x21E2 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_52_RESVD 0x21E3 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_LOW 0x21E4 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_MID 0x21E5 +#define SUNI1x10GEXP_REG_MSTAT_COUNTER_53_HIGH 0x21E6 +#define SUNI1x10GEXP_CNTR_MAC_ETHERNET_NUM 51 + +#define SUNI1x10GEXP_REG_IFLX_GLOBAL_CONFIG 0x2200 +#define SUNI1x10GEXP_REG_IFLX_CHANNEL_PROVISION 0x2201 #define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE 0x2209 #define SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT 0x220A +#define SUNI1x10GEXP_REG_IFLX_INDIR_CHANNEL_ADDRESS 0x220D +#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_LOW_LIMIT_PROVISION 0x220E +#define SUNI1x10GEXP_REG_IFLX_INDIR_LOGICAL_FIFO_HIGH_LIMIT 0x220F +#define SUNI1x10GEXP_REG_IFLX_INDIR_FULL_ALMOST_FULL_STATUS_LIMIT 0x2210 +#define SUNI1x10GEXP_REG_IFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_LIMIT 0x2211 + +#define SUNI1x10GEXP_REG_PL4MOS_CONFIG 0x2240 +#define SUNI1x10GEXP_REG_PL4MOS_MASK 0x2241 +#define SUNI1x10GEXP_REG_PL4MOS_FAIRNESS_MASKING 0x2242 +#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST1 0x2243 +#define SUNI1x10GEXP_REG_PL4MOS_MAXBURST2 0x2244 +#define SUNI1x10GEXP_REG_PL4MOS_TRANSFER_SIZE 0x2245 + +#define SUNI1x10GEXP_REG_PL4ODP_CONFIG 0x2280 #define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK 0x2282 #define SUNI1x10GEXP_REG_PL4ODP_INTERRUPT 0x2283 +#define SUNI1x10GEXP_REG_PL4ODP_CONFIG_MAX_T 0x2284 + #define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS 0x2300 #define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE 0x2301 #define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK 0x2302 +#define SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_LIMITS 0x2303 +#define SUNI1x10GEXP_REG_PL4IO_CALENDAR_REPETITIONS 0x2304 +#define SUNI1x10GEXP_REG_PL4IO_CONFIG 0x2305 + #define SUNI1x10GEXP_REG_TXXG_CONFIG_1 0x3040 +#define SUNI1x10GEXP_REG_TXXG_CONFIG_2 0x3041 #define SUNI1x10GEXP_REG_TXXG_CONFIG_3 0x3042 #define SUNI1x10GEXP_REG_TXXG_INTERRUPT 0x3043 +#define SUNI1x10GEXP_REG_TXXG_STATUS 0x3044 #define SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE 0x3045 +#define SUNI1x10GEXP_REG_TXXG_MIN_FRAME_SIZE 0x3046 #define SUNI1x10GEXP_REG_TXXG_SA_15_0 0x3047 #define SUNI1x10GEXP_REG_TXXG_SA_31_16 0x3048 #define SUNI1x10GEXP_REG_TXXG_SA_47_32 0x3049 +#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER 0x304D +#define SUNI1x10GEXP_REG_TXXG_PAUSE_TIMER_INTERVAL 0x304E +#define SUNI1x10GEXP_REG_TXXG_FILTER_ERROR_COUNTER 0x3051 +#define SUNI1x10GEXP_REG_TXXG_PAUSE_QUANTUM_CONFIG 0x3052 + +#define SUNI1x10GEXP_REG_XTEF_CTRL 0x3080 #define SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS 0x3084 #define SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE 0x3085 +#define SUNI1x10GEXP_REG_XTEF_VISIBILITY 0x3086 + +#define SUNI1x10GEXP_REG_TXOAM_OAM_CONFIG 0x30C0 +#define SUNI1x10GEXP_REG_TXOAM_MINI_RATE_CONFIG 0x30C1 +#define SUNI1x10GEXP_REG_TXOAM_MINI_GAP_FIFO_CONFIG 0x30C2 +#define SUNI1x10GEXP_REG_TXOAM_P1P2_STATIC_VALUES 0x30C3 +#define SUNI1x10GEXP_REG_TXOAM_P3P4_STATIC_VALUES 0x30C4 +#define SUNI1x10GEXP_REG_TXOAM_P5P6_STATIC_VALUES 0x30C5 #define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE 0x30C6 #define SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS 0x30C7 +#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_LSB 0x30C8 +#define SUNI1x10GEXP_REG_TXOAM_INSERT_COUNT_MSB 0x30C9 +#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_LSB 0x30CA +#define SUNI1x10GEXP_REG_TXOAM_OAM_MINI_COUNT_MSB 0x30CB +#define SUNI1x10GEXP_REG_TXOAM_P1P2_MINI_MASK 0x30CC +#define SUNI1x10GEXP_REG_TXOAM_P3P4_MINI_MASK 0x30CD +#define SUNI1x10GEXP_REG_TXOAM_P5P6_MINI_MASK 0x30CE +#define SUNI1x10GEXP_REG_TXOAM_COSET 0x30CF +#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_LSB 0x30D0 +#define SUNI1x10GEXP_REG_TXOAM_EMPTY_FIFO_INS_OP_CNT_MSB 0x30D1 +#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_LSB 0x30D2 +#define SUNI1x10GEXP_REG_TXOAM_STATIC_VALUE_MINI_COUNT_MSB 0x30D3 + + +#define SUNI1x10GEXP_REG_EFLX_GLOBAL_CONFIG 0x3200 +#define SUNI1x10GEXP_REG_EFLX_ERCU_GLOBAL_STATUS 0x3201 +#define SUNI1x10GEXP_REG_EFLX_INDIR_CHANNEL_ADDRESS 0x3202 +#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_LOW_LIMIT 0x3203 +#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_HIGH_LIMIT 0x3204 +#define SUNI1x10GEXP_REG_EFLX_INDIR_FULL_ALMOST_FULL_STATUS_AND_LIMIT 0x3205 +#define SUNI1x10GEXP_REG_EFLX_INDIR_EMPTY_ALMOST_EMPTY_STATUS_AND_LIMIT 0x3206 +#define SUNI1x10GEXP_REG_EFLX_INDIR_FIFO_CUT_THROUGH_THRESHOLD 0x3207 #define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE 0x320C #define SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION 0x320D +#define SUNI1x10GEXP_REG_EFLX_CHANNEL_PROVISION 0x3210 + +#define SUNI1x10GEXP_REG_PL4IDU_CONFIG 0x3280 #define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK 0x3282 #define SUNI1x10GEXP_REG_PL4IDU_INTERRUPT 0x3283 + +/*----------------------------------------*/ +#define SUNI1x10GEXP_REG_MAX_OFFSET 0x3480 + /******************************************************************************/ /* -- End register offset definitions -- */ /******************************************************************************/ @@ -127,6 +514,81 @@ /** SUNI-1x10GE-XP REGISTER BIT MASKS **/ /******************************************************************************/ +#define SUNI1x10GEXP_BITMSK_BITS_1 0x00001 +#define SUNI1x10GEXP_BITMSK_BITS_2 0x00003 +#define SUNI1x10GEXP_BITMSK_BITS_3 0x00007 +#define SUNI1x10GEXP_BITMSK_BITS_4 0x0000f +#define SUNI1x10GEXP_BITMSK_BITS_5 0x0001f +#define SUNI1x10GEXP_BITMSK_BITS_6 0x0003f +#define SUNI1x10GEXP_BITMSK_BITS_7 0x0007f +#define SUNI1x10GEXP_BITMSK_BITS_8 0x000ff +#define SUNI1x10GEXP_BITMSK_BITS_9 0x001ff +#define SUNI1x10GEXP_BITMSK_BITS_10 0x003ff +#define SUNI1x10GEXP_BITMSK_BITS_11 0x007ff +#define SUNI1x10GEXP_BITMSK_BITS_12 0x00fff +#define SUNI1x10GEXP_BITMSK_BITS_13 0x01fff +#define SUNI1x10GEXP_BITMSK_BITS_14 0x03fff +#define SUNI1x10GEXP_BITMSK_BITS_15 0x07fff +#define SUNI1x10GEXP_BITMSK_BITS_16 0x0ffff + +#define mSUNI1x10GEXP_CLR_MSBITS_1(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_15) +#define mSUNI1x10GEXP_CLR_MSBITS_2(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_14) +#define mSUNI1x10GEXP_CLR_MSBITS_3(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_13) +#define mSUNI1x10GEXP_CLR_MSBITS_4(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_12) +#define mSUNI1x10GEXP_CLR_MSBITS_5(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_11) +#define mSUNI1x10GEXP_CLR_MSBITS_6(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_10) +#define mSUNI1x10GEXP_CLR_MSBITS_7(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_9) +#define mSUNI1x10GEXP_CLR_MSBITS_8(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_8) +#define mSUNI1x10GEXP_CLR_MSBITS_9(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_7) +#define mSUNI1x10GEXP_CLR_MSBITS_10(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_6) +#define mSUNI1x10GEXP_CLR_MSBITS_11(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_5) +#define mSUNI1x10GEXP_CLR_MSBITS_12(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_4) +#define mSUNI1x10GEXP_CLR_MSBITS_13(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_3) +#define mSUNI1x10GEXP_CLR_MSBITS_14(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_2) +#define mSUNI1x10GEXP_CLR_MSBITS_15(v) ((v) & SUNI1x10GEXP_BITMSK_BITS_1) + +#define mSUNI1x10GEXP_GET_BIT(val, bitMsk) (((val)&(bitMsk)) ? 1:0) + + + +/*---------------------------------------------------------------------------- + * Register 0x0001: S/UNI-1x10GE-XP Product Revision + * Bit 3-0 REVISION + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_REVISION 0x000F + +/*---------------------------------------------------------------------------- + * Register 0x0002: S/UNI-1x10GE-XP Configuration and Reset Control + * Bit 2 XAUI_ARESETB + * Bit 1 PL4_ARESETB + * Bit 0 DRESETB + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_XAUI_ARESET 0x0004 +#define SUNI1x10GEXP_BITMSK_PL4_ARESET 0x0002 +#define SUNI1x10GEXP_BITMSK_DRESETB 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0003: S/UNI-1x10GE-XP Loop Back and Miscellaneous Control + * Bit 11 PL4IO_OUTCLKSEL + * Bit 9 SYSPCSLB + * Bit 8 LINEPCSLB + * Bit 7 MSTAT_BYPASS + * Bit 6 RXXG_BYPASS + * Bit 5 TXXG_BYPASS + * Bit 4 SOP_PAD_EN + * Bit 1 LOS_INV + * Bit 0 OVERRIDE_LOS + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_OUTCLKSEL 0x0800 +#define SUNI1x10GEXP_BITMSK_SYSPCSLB 0x0200 +#define SUNI1x10GEXP_BITMSK_LINEPCSLB 0x0100 +#define SUNI1x10GEXP_BITMSK_MSTAT_BYPASS 0x0080 +#define SUNI1x10GEXP_BITMSK_RXXG_BYPASS 0x0040 +#define SUNI1x10GEXP_BITMSK_TXXG_BYPASS 0x0020 +#define SUNI1x10GEXP_BITMSK_SOP_PAD_EN 0x0010 +#define SUNI1x10GEXP_BITMSK_LOS_INV 0x0002 +#define SUNI1x10GEXP_BITMSK_OVERRIDE_LOS 0x0001 + /*---------------------------------------------------------------------------- * Register 0x0004: S/UNI-1x10GE-XP Device Status * Bit 9 TOP_SXRA_EXPIRED @@ -141,19 +603,229 @@ * Bit 0 TOP_PL4_OUT_ROOL *----------------------------------------------------------------------------*/ #define SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED 0x0200 +#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY 0x0100 +#define SUNI1x10GEXP_BITMSK_TOP_DTRB 0x0080 #define SUNI1x10GEXP_BITMSK_TOP_EXPIRED 0x0040 +#define SUNI1x10GEXP_BITMSK_TOP_PAUSED 0x0020 #define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL 0x0010 #define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_DOOL 0x0008 #define SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL 0x0004 #define SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL 0x0002 #define SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL 0x0001 +/*---------------------------------------------------------------------------- + * Register 0x0005: Global Performance Update and Clock Monitors + * Bit 15 TIP + * Bit 8 XAUI_REF_CLKA + * Bit 7 RXLANE3CLKA + * Bit 6 RXLANE2CLKA + * Bit 5 RXLANE1CLKA + * Bit 4 RXLANE0CLKA + * Bit 3 CSUCLKA + * Bit 2 TDCLKA + * Bit 1 RSCLKA + * Bit 0 RDCLKA + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TIP 0x8000 +#define SUNI1x10GEXP_BITMSK_XAUI_REF_CLKA 0x0100 +#define SUNI1x10GEXP_BITMSK_RXLANE3CLKA 0x0080 +#define SUNI1x10GEXP_BITMSK_RXLANE2CLKA 0x0040 +#define SUNI1x10GEXP_BITMSK_RXLANE1CLKA 0x0020 +#define SUNI1x10GEXP_BITMSK_RXLANE0CLKA 0x0010 +#define SUNI1x10GEXP_BITMSK_CSUCLKA 0x0008 +#define SUNI1x10GEXP_BITMSK_TDCLKA 0x0004 +#define SUNI1x10GEXP_BITMSK_RSCLKA 0x0002 +#define SUNI1x10GEXP_BITMSK_RDCLKA 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0006: MDIO Command + * Bit 4 MDIO_RDINC + * Bit 3 MDIO_RSTAT + * Bit 2 MDIO_LCTLD + * Bit 1 MDIO_LCTLA + * Bit 0 MDIO_SPRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MDIO_RDINC 0x0010 +#define SUNI1x10GEXP_BITMSK_MDIO_RSTAT 0x0008 +#define SUNI1x10GEXP_BITMSK_MDIO_LCTLD 0x0004 +#define SUNI1x10GEXP_BITMSK_MDIO_LCTLA 0x0002 +#define SUNI1x10GEXP_BITMSK_MDIO_SPRE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0007: MDIO Interrupt Enable + * Bit 0 MDIO_BUSY_EN + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MDIO_BUSY_EN 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0008: MDIO Interrupt Status + * Bit 0 MDIO_BUSYI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MDIO_BUSYI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0009: MMD PHY Address + * Bit 12-8 MDIO_DEVADR + * Bit 4-0 MDIO_PRTADR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MDIO_DEVADR 0x1F00 +#define SUNI1x10GEXP_BITOFF_MDIO_DEVADR 8 +#define SUNI1x10GEXP_BITMSK_MDIO_PRTADR 0x001F +#define SUNI1x10GEXP_BITOFF_MDIO_PRTADR 0 + +/*---------------------------------------------------------------------------- + * Register 0x000C: OAM Interface Control + * Bit 6 MDO_OD_ENB + * Bit 5 MDI_INV + * Bit 4 MDI_SEL + * Bit 3 RXOAMEN + * Bit 2 RXOAMCLKEN + * Bit 1 TXOAMEN + * Bit 0 TXOAMCLKEN + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MDO_OD_ENB 0x0040 +#define SUNI1x10GEXP_BITMSK_MDI_INV 0x0020 +#define SUNI1x10GEXP_BITMSK_MDI_SEL 0x0010 +#define SUNI1x10GEXP_BITMSK_RXOAMEN 0x0008 +#define SUNI1x10GEXP_BITMSK_RXOAMCLKEN 0x0004 +#define SUNI1x10GEXP_BITMSK_TXOAMEN 0x0002 +#define SUNI1x10GEXP_BITMSK_TXOAMCLKEN 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x000D: S/UNI-1x10GE-XP Master Interrupt Status + * Bit 15 TOP_PL4IO_INT + * Bit 14 TOP_IRAM_INT + * Bit 13 TOP_ERAM_INT + * Bit 12 TOP_XAUI_INT + * Bit 11 TOP_MSTAT_INT + * Bit 10 TOP_RXXG_INT + * Bit 9 TOP_TXXG_INT + * Bit 8 TOP_XRF_INT + * Bit 7 TOP_XTEF_INT + * Bit 6 TOP_MDIO_BUSY_INT + * Bit 5 TOP_RXOAM_INT + * Bit 4 TOP_TXOAM_INT + * Bit 3 TOP_IFLX_INT + * Bit 2 TOP_EFLX_INT + * Bit 1 TOP_PL4ODP_INT + * Bit 0 TOP_PL4IDU_INT + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TOP_PL4IO_INT 0x8000 +#define SUNI1x10GEXP_BITMSK_TOP_IRAM_INT 0x4000 +#define SUNI1x10GEXP_BITMSK_TOP_ERAM_INT 0x2000 +#define SUNI1x10GEXP_BITMSK_TOP_XAUI_INT 0x1000 +#define SUNI1x10GEXP_BITMSK_TOP_MSTAT_INT 0x0800 +#define SUNI1x10GEXP_BITMSK_TOP_RXXG_INT 0x0400 +#define SUNI1x10GEXP_BITMSK_TOP_TXXG_INT 0x0200 +#define SUNI1x10GEXP_BITMSK_TOP_XRF_INT 0x0100 +#define SUNI1x10GEXP_BITMSK_TOP_XTEF_INT 0x0080 +#define SUNI1x10GEXP_BITMSK_TOP_MDIO_BUSY_INT 0x0040 +#define SUNI1x10GEXP_BITMSK_TOP_RXOAM_INT 0x0020 +#define SUNI1x10GEXP_BITMSK_TOP_TXOAM_INT 0x0010 +#define SUNI1x10GEXP_BITMSK_TOP_IFLX_INT 0x0008 +#define SUNI1x10GEXP_BITMSK_TOP_EFLX_INT 0x0004 +#define SUNI1x10GEXP_BITMSK_TOP_PL4ODP_INT 0x0002 +#define SUNI1x10GEXP_BITMSK_TOP_PL4IDU_INT 0x0001 + /*---------------------------------------------------------------------------- * Register 0x000E:PM3393 Global interrupt enable * Bit 15 TOP_INTE *----------------------------------------------------------------------------*/ #define SUNI1x10GEXP_BITMSK_TOP_INTE 0x8000 +/*---------------------------------------------------------------------------- + * Register 0x0010: XTEF Miscellaneous Control + * Bit 7 RF_VAL + * Bit 6 RF_OVERRIDE + * Bit 5 LF_VAL + * Bit 4 LF_OVERRIDE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RF_VAL 0x0080 +#define SUNI1x10GEXP_BITMSK_RF_OVERRIDE 0x0040 +#define SUNI1x10GEXP_BITMSK_LF_VAL 0x0020 +#define SUNI1x10GEXP_BITMSK_LF_OVERRIDE 0x0010 +#define SUNI1x10GEXP_BITMSK_LFRF_OVERRIDE_VAL 0x00F0 + +/*---------------------------------------------------------------------------- + * Register 0x0011: XRF Miscellaneous Control + * Bit 6-4 EN_IDLE_REP + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EN_IDLE_REP 0x0070 + +/*---------------------------------------------------------------------------- + * Register 0x0100: SERDES 3125 Configuration Register 1 + * Bit 10 RXEQB_3 + * Bit 8 RXEQB_2 + * Bit 6 RXEQB_1 + * Bit 4 RXEQB_0 + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXEQB 0x0FF0 +#define SUNI1x10GEXP_BITOFF_RXEQB_3 10 +#define SUNI1x10GEXP_BITOFF_RXEQB_2 8 +#define SUNI1x10GEXP_BITOFF_RXEQB_1 6 +#define SUNI1x10GEXP_BITOFF_RXEQB_0 4 + +/*---------------------------------------------------------------------------- + * Register 0x0101: SERDES 3125 Configuration Register 2 + * Bit 12 YSEL + * Bit 7 PRE_EMPH_3 + * Bit 6 PRE_EMPH_2 + * Bit 5 PRE_EMPH_1 + * Bit 4 PRE_EMPH_0 + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_YSEL 0x1000 +#define SUNI1x10GEXP_BITMSK_PRE_EMPH 0x00F0 +#define SUNI1x10GEXP_BITMSK_PRE_EMPH_3 0x0080 +#define SUNI1x10GEXP_BITMSK_PRE_EMPH_2 0x0040 +#define SUNI1x10GEXP_BITMSK_PRE_EMPH_1 0x0020 +#define SUNI1x10GEXP_BITMSK_PRE_EMPH_0 0x0010 + +/*---------------------------------------------------------------------------- + * Register 0x0102: SERDES 3125 Interrupt Enable Register + * Bit 3 LASIE + * Bit 2 SPLL_RAE + * Bit 1 MPLL_RAE + * Bit 0 PLL_LOCKE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LASIE 0x0008 +#define SUNI1x10GEXP_BITMSK_SPLL_RAE 0x0004 +#define SUNI1x10GEXP_BITMSK_MPLL_RAE 0x0002 +#define SUNI1x10GEXP_BITMSK_PLL_LOCKE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0103: SERDES 3125 Interrupt Visibility Register + * Bit 3 LASIV + * Bit 2 SPLL_RAV + * Bit 1 MPLL_RAV + * Bit 0 PLL_LOCKV + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LASIV 0x0008 +#define SUNI1x10GEXP_BITMSK_SPLL_RAV 0x0004 +#define SUNI1x10GEXP_BITMSK_MPLL_RAV 0x0002 +#define SUNI1x10GEXP_BITMSK_PLL_LOCKV 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0104: SERDES 3125 Interrupt Status Register + * Bit 3 LASII + * Bit 2 SPLL_RAI + * Bit 1 MPLL_RAI + * Bit 0 PLL_LOCKI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LASII 0x0008 +#define SUNI1x10GEXP_BITMSK_SPLL_RAI 0x0004 +#define SUNI1x10GEXP_BITMSK_MPLL_RAI 0x0002 +#define SUNI1x10GEXP_BITMSK_PLL_LOCKI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x0107: SERDES 3125 Test Configuration + * Bit 12 DUALTX + * Bit 10 HC_1 + * Bit 9 HC_0 + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_DUALTX 0x1000 +#define SUNI1x10GEXP_BITMSK_HC 0x0600 +#define SUNI1x10GEXP_BITOFF_HC_0 9 + /*---------------------------------------------------------------------------- * Register 0x2040: RXXG Configuration 1 * Bit 15 RXXG_RXEN @@ -168,10 +840,83 @@ * Bit 2-0 RXXG_MIFG *----------------------------------------------------------------------------*/ #define SUNI1x10GEXP_BITMSK_RXXG_RXEN 0x8000 +#define SUNI1x10GEXP_BITMSK_RXXG_ROCF 0x4000 +#define SUNI1x10GEXP_BITMSK_RXXG_PAD_STRIP 0x2000 #define SUNI1x10GEXP_BITMSK_RXXG_PUREP 0x0400 +#define SUNI1x10GEXP_BITMSK_RXXG_LONGP 0x0200 +#define SUNI1x10GEXP_BITMSK_RXXG_PARF 0x0100 #define SUNI1x10GEXP_BITMSK_RXXG_FLCHK 0x0080 +#define SUNI1x10GEXP_BITMSK_RXXG_PASS_CTRL 0x0020 #define SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP 0x0008 +/*---------------------------------------------------------------------------- + * Register 0x02041: RXXG Configuration 2 + * Bit 7-0 RXXG_HDRSIZE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_HDRSIZE 0x00FF + +/*---------------------------------------------------------------------------- + * Register 0x2042: RXXG Configuration 3 + * Bit 15 RXXG_MIN_LERRE + * Bit 14 RXXG_MAX_LERRE + * Bit 12 RXXG_LINE_ERRE + * Bit 10 RXXG_RX_OVRE + * Bit 9 RXXG_ADR_FILTERE + * Bit 8 RXXG_ERR_FILTERE + * Bit 5 RXXG_PRMB_ERRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRE 0x8000 +#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRE 0x4000 +#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRE 0x1000 +#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRE 0x0400 +#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERE 0x0200 +#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERRE 0x0100 +#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE 0x0020 + +/*---------------------------------------------------------------------------- + * Register 0x2043: RXXG Interrupt + * Bit 15 RXXG_MIN_LERRI + * Bit 14 RXXG_MAX_LERRI + * Bit 12 RXXG_LINE_ERRI + * Bit 10 RXXG_RX_OVRI + * Bit 9 RXXG_ADR_FILTERI + * Bit 8 RXXG_ERR_FILTERI + * Bit 5 RXXG_PRMB_ERRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_MIN_LERRI 0x8000 +#define SUNI1x10GEXP_BITMSK_RXXG_MAX_LERRI 0x4000 +#define SUNI1x10GEXP_BITMSK_RXXG_LINE_ERRI 0x1000 +#define SUNI1x10GEXP_BITMSK_RXXG_RX_OVRI 0x0400 +#define SUNI1x10GEXP_BITMSK_RXXG_ADR_FILTERI 0x0200 +#define SUNI1x10GEXP_BITMSK_RXXG_ERR_FILTERI 0x0100 +#define SUNI1x10GEXP_BITMSK_RXXG_PRMB_ERRE 0x0020 + +/*---------------------------------------------------------------------------- + * Register 0x2049: RXXG Receive FIFO Threshold + * Bit 2-0 RXXG_CUT_THRU + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_CUT_THRU 0x0007 +#define SUNI1x10GEXP_BITOFF_RXXG_CUT_THRU 0 + +/*---------------------------------------------------------------------------- + * Register 0x2062H - 0x2069: RXXG Exact Match VID + * Bit 11-0 RXXG_VID_MATCH + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_VID_MATCH 0x0FFF +#define SUNI1x10GEXP_BITOFF_RXXG_VID_MATCH 0 + +/*---------------------------------------------------------------------------- + * Register 0x206EH - 0x206F: RXXG Address Filter Control + * Bit 3 RXXG_FORWARD_ENABLE + * Bit 2 RXXG_VLAN_ENABLE + * Bit 1 RXXG_SRC_ADDR + * Bit 0 RXXG_MATCH_ENABLE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXXG_FORWARD_ENABLE 0x0008 +#define SUNI1x10GEXP_BITMSK_RXXG_VLAN_ENABLE 0x0004 +#define SUNI1x10GEXP_BITMSK_RXXG_SRC_ADDR 0x0002 +#define SUNI1x10GEXP_BITMSK_RXXG_MATCH_ENABLE 0x0001 + /*---------------------------------------------------------------------------- * Register 0x2070: RXXG Address Filter Control 2 * Bit 1 RXXG_PMODE @@ -180,15 +925,446 @@ #define SUNI1x10GEXP_BITMSK_RXXG_PMODE 0x0002 #define SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN 0x0001 +/*---------------------------------------------------------------------------- + * Register 0x2081: XRF Control Register 2 + * Bit 6 EN_PKT_GEN + * Bit 4-2 PATT + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EN_PKT_GEN 0x0040 +#define SUNI1x10GEXP_BITMSK_PATT 0x001C +#define SUNI1x10GEXP_BITOFF_PATT 2 + +/*---------------------------------------------------------------------------- + * Register 0x2088: XRF Interrupt Enable + * Bit 12-9 LANE_HICERE + * Bit 8-5 HS_SD_LANEE + * Bit 4 ALIGN_STATUS_ERRE + * Bit 3-0 LANE_SYNC_STAT_ERRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LANE_HICERE 0x1E00 +#define SUNI1x10GEXP_BITOFF_LANE_HICERE 9 +#define SUNI1x10GEXP_BITMSK_HS_SD_LANEE 0x01E0 +#define SUNI1x10GEXP_BITOFF_HS_SD_LANEE 5 +#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRE 0x0010 +#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRE 0x000F +#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRE 0 + +/*---------------------------------------------------------------------------- + * Register 0x2089: XRF Interrupt Status + * Bit 12-9 LANE_HICERI + * Bit 8-5 HS_SD_LANEI + * Bit 4 ALIGN_STATUS_ERRI + * Bit 3-0 LANE_SYNC_STAT_ERRI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LANE_HICERI 0x1E00 +#define SUNI1x10GEXP_BITOFF_LANE_HICERI 9 +#define SUNI1x10GEXP_BITMSK_HS_SD_LANEI 0x01E0 +#define SUNI1x10GEXP_BITOFF_HS_SD_LANEI 5 +#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERRI 0x0010 +#define SUNI1x10GEXP_BITMSK_LANE_SYNC_STAT_ERRI 0x000F +#define SUNI1x10GEXP_BITOFF_LANE_SYNC_STAT_ERRI 0 + +/*---------------------------------------------------------------------------- + * Register 0x208A: XRF Error Status + * Bit 8-5 HS_SD_LANE + * Bit 4 ALIGN_STATUS_ERR + * Bit 3-0 LANE_SYNC_STAT_ERR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_HS_SD_LANE3 0x0100 +#define SUNI1x10GEXP_BITMSK_HS_SD_LANE2 0x0080 +#define SUNI1x10GEXP_BITMSK_HS_SD_LANE1 0x0040 +#define SUNI1x10GEXP_BITMSK_HS_SD_LANE0 0x0020 +#define SUNI1x10GEXP_BITMSK_ALIGN_STATUS_ERR 0x0010 +#define SUNI1x10GEXP_BITMSK_LANE3_SYNC_STAT_ERR 0x0008 +#define SUNI1x10GEXP_BITMSK_LANE2_SYNC_STAT_ERR 0x0004 +#define SUNI1x10GEXP_BITMSK_LANE1_SYNC_STAT_ERR 0x0002 +#define SUNI1x10GEXP_BITMSK_LANE0_SYNC_STAT_ERR 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x208B: XRF Diagnostic Interrupt Enable + * Bit 7-4 LANE_OVERRUNE + * Bit 3-0 LANE_UNDERRUNE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNE 0x00F0 +#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNE 4 +#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNE 0x000F +#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNE 0 + +/*---------------------------------------------------------------------------- + * Register 0x208C: XRF Diagnostic Interrupt Status + * Bit 7-4 LANE_OVERRUNI + * Bit 3-0 LANE_UNDERRUNI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_LANE_OVERRUNI 0x00F0 +#define SUNI1x10GEXP_BITOFF_LANE_OVERRUNI 4 +#define SUNI1x10GEXP_BITMSK_LANE_UNDERRUNI 0x000F +#define SUNI1x10GEXP_BITOFF_LANE_UNDERRUNI 0 + +/*---------------------------------------------------------------------------- + * Register 0x20C0: RXOAM Configuration + * Bit 15 RXOAM_BUSY + * Bit 14-12 RXOAM_F2_SEL + * Bit 10-8 RXOAM_F1_SEL + * Bit 7-6 RXOAM_FILTER_CTRL + * Bit 5-0 RXOAM_PX_EN + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_BUSY 0x8000 +#define SUNI1x10GEXP_BITMSK_RXOAM_F2_SEL 0x7000 +#define SUNI1x10GEXP_BITOFF_RXOAM_F2_SEL 12 +#define SUNI1x10GEXP_BITMSK_RXOAM_F1_SEL 0x0700 +#define SUNI1x10GEXP_BITOFF_RXOAM_F1_SEL 8 +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_CTRL 0x00C0 +#define SUNI1x10GEXP_BITOFF_RXOAM_FILTER_CTRL 6 +#define SUNI1x10GEXP_BITMSK_RXOAM_PX_EN 0x003F +#define SUNI1x10GEXP_BITOFF_RXOAM_PX_EN 0 + +/*---------------------------------------------------------------------------- + * Register 0x20C1,0x20C2: RXOAM Filter Configuration + * Bit 15-8 RXOAM_FX_MASK + * Bit 7-0 RXOAM_FX_VAL + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_FX_MASK 0xFF00 +#define SUNI1x10GEXP_BITOFF_RXOAM_FX_MASK 8 +#define SUNI1x10GEXP_BITMSK_RXOAM_FX_VAL 0x00FF +#define SUNI1x10GEXP_BITOFF_RXOAM_FX_VAl 0 + +/*---------------------------------------------------------------------------- + * Register 0x20C3: RXOAM Configuration Register 2 + * Bit 13 RXOAM_REC_BYTE_VAL + * Bit 11-10 RXOAM_BYPASS_MODE + * Bit 5-0 RXOAM_PX_CLEAR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_REC_BYTE_VAL 0x2000 +#define SUNI1x10GEXP_BITMSK_RXOAM_BYPASS_MODE 0x0C00 +#define SUNI1x10GEXP_BITOFF_RXOAM_BYPASS_MODE 10 +#define SUNI1x10GEXP_BITMSK_RXOAM_PX_CLEAR 0x003F +#define SUNI1x10GEXP_BITOFF_RXOAM_PX_CLEAR 0 + +/*---------------------------------------------------------------------------- + * Register 0x20C4: RXOAM HEC Configuration + * Bit 15-8 RXOAM_COSET + * Bit 2 RXOAM_HEC_ERR_PKT + * Bit 0 RXOAM_HEC_EN + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_COSET 0xFF00 +#define SUNI1x10GEXP_BITOFF_RXOAM_COSET 8 +#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_ERR_PKT 0x0004 +#define SUNI1x10GEXP_BITMSK_RXOAM_HEC_EN 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x20C7: RXOAM Interrupt Enable + * Bit 10 RXOAM_FILTER_THRSHE + * Bit 9 RXOAM_OAM_ERRE + * Bit 8 RXOAM_HECE_THRSHE + * Bit 7 RXOAM_SOPE + * Bit 6 RXOAM_RFE + * Bit 5 RXOAM_LFE + * Bit 4 RXOAM_DV_ERRE + * Bit 3 RXOAM_DATA_INVALIDE + * Bit 2 RXOAM_FILTER_DROPE + * Bit 1 RXOAM_HECE + * Bit 0 RXOAM_OFLE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHE 0x0400 +#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRE 0x0200 +#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHE 0x0100 +#define SUNI1x10GEXP_BITMSK_RXOAM_SOPE 0x0080 +#define SUNI1x10GEXP_BITMSK_RXOAM_RFE 0x0040 +#define SUNI1x10GEXP_BITMSK_RXOAM_LFE 0x0020 +#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRE 0x0010 +#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDE 0x0008 +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPE 0x0004 +#define SUNI1x10GEXP_BITMSK_RXOAM_HECE 0x0002 +#define SUNI1x10GEXP_BITMSK_RXOAM_OFLE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x20C8: RXOAM Interrupt Status + * Bit 10 RXOAM_FILTER_THRSHI + * Bit 9 RXOAM_OAM_ERRI + * Bit 8 RXOAM_HECE_THRSHI + * Bit 7 RXOAM_SOPI + * Bit 6 RXOAM_RFI + * Bit 5 RXOAM_LFI + * Bit 4 RXOAM_DV_ERRI + * Bit 3 RXOAM_DATA_INVALIDI + * Bit 2 RXOAM_FILTER_DROPI + * Bit 1 RXOAM_HECI + * Bit 0 RXOAM_OFLI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHI 0x0400 +#define SUNI1x10GEXP_BITMSK_RXOAM_OAM_ERRI 0x0200 +#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHI 0x0100 +#define SUNI1x10GEXP_BITMSK_RXOAM_SOPI 0x0080 +#define SUNI1x10GEXP_BITMSK_RXOAM_RFI 0x0040 +#define SUNI1x10GEXP_BITMSK_RXOAM_LFI 0x0020 +#define SUNI1x10GEXP_BITMSK_RXOAM_DV_ERRI 0x0010 +#define SUNI1x10GEXP_BITMSK_RXOAM_DATA_INVALIDI 0x0008 +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_DROPI 0x0004 +#define SUNI1x10GEXP_BITMSK_RXOAM_HECI 0x0002 +#define SUNI1x10GEXP_BITMSK_RXOAM_OFLI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x20C9: RXOAM Status + * Bit 10 RXOAM_FILTER_THRSHV + * Bit 8 RXOAM_HECE_THRSHV + * Bit 6 RXOAM_RFV + * Bit 5 RXOAM_LFV + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_RXOAM_FILTER_THRSHV 0x0400 +#define SUNI1x10GEXP_BITMSK_RXOAM_HECE_THRSHV 0x0100 +#define SUNI1x10GEXP_BITMSK_RXOAM_RFV 0x0040 +#define SUNI1x10GEXP_BITMSK_RXOAM_LFV 0x0020 + /*---------------------------------------------------------------------------- * Register 0x2100: MSTAT Control * Bit 2 MSTAT_WRITE * Bit 1 MSTAT_CLEAR * Bit 0 MSTAT_SNAP *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE 0x0004 #define SUNI1x10GEXP_BITMSK_MSTAT_CLEAR 0x0002 #define SUNI1x10GEXP_BITMSK_MSTAT_SNAP 0x0001 +/*---------------------------------------------------------------------------- + * Register 0x2109: MSTAT Counter Write Address + * Bit 5-0 MSTAT_WRITE_ADDRESS + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_MSTAT_WRITE_ADDRESS 0x003F +#define SUNI1x10GEXP_BITOFF_MSTAT_WRITE_ADDRESS 0 + +/*---------------------------------------------------------------------------- + * Register 0x2200: IFLX Global Configuration Register + * Bit 15 IFLX_IRCU_ENABLE + * Bit 14 IFLX_IDSWT_ENABLE + * Bit 13-0 IFLX_IFD_CNT + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_IRCU_ENABLE 0x8000 +#define SUNI1x10GEXP_BITMSK_IFLX_IDSWT_ENABLE 0x4000 +#define SUNI1x10GEXP_BITMSK_IFLX_IFD_CNT 0x3FFF +#define SUNI1x10GEXP_BITOFF_IFLX_IFD_CNT 0 + +/*---------------------------------------------------------------------------- + * Register 0x2209: IFLX FIFO Overflow Enable + * Bit 0 IFLX_OVFE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_OVFE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x220A: IFLX FIFO Overflow Interrupt + * Bit 0 IFLX_OVFI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_OVFI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x220D: IFLX Indirect Channel Address + * Bit 15 IFLX_BUSY + * Bit 14 IFLX_RWB + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_BUSY 0x8000 +#define SUNI1x10GEXP_BITMSK_IFLX_RWB 0x4000 + +/*---------------------------------------------------------------------------- + * Register 0x220E: IFLX Indirect Logical FIFO Low Limit & Provision + * Bit 9-0 IFLX_LOLIM + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_LOLIM 0x03FF +#define SUNI1x10GEXP_BITOFF_IFLX_LOLIM 0 + +/*---------------------------------------------------------------------------- + * Register 0x220F: IFLX Indirect Logical FIFO High Limit + * Bit 9-0 IFLX_HILIM + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_HILIM 0x03FF +#define SUNI1x10GEXP_BITOFF_IFLX_HILIM 0 + +/*---------------------------------------------------------------------------- + * Register 0x2210: IFLX Indirect Full/Almost Full Status & Limit + * Bit 15 IFLX_FULL + * Bit 14 IFLX_AFULL + * Bit 13-0 IFLX_AFTH + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_FULL 0x8000 +#define SUNI1x10GEXP_BITMSK_IFLX_AFULL 0x4000 +#define SUNI1x10GEXP_BITMSK_IFLX_AFTH 0x3FFF +#define SUNI1x10GEXP_BITOFF_IFLX_AFTH 0 + +/*---------------------------------------------------------------------------- + * Register 0x2211: IFLX Indirect Empty/Almost Empty Status & Limit + * Bit 15 IFLX_EMPTY + * Bit 14 IFLX_AEMPTY + * Bit 13-0 IFLX_AETH + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_IFLX_EMPTY 0x8000 +#define SUNI1x10GEXP_BITMSK_IFLX_AEMPTY 0x4000 +#define SUNI1x10GEXP_BITMSK_IFLX_AETH 0x3FFF +#define SUNI1x10GEXP_BITOFF_IFLX_AETH 0 + +/*---------------------------------------------------------------------------- + * Register 0x2240: PL4MOS Configuration Register + * Bit 3 PL4MOS_RE_INIT + * Bit 2 PL4MOS_EN + * Bit 1 PL4MOS_NO_STATUS + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4MOS_RE_INIT 0x0008 +#define SUNI1x10GEXP_BITMSK_PL4MOS_EN 0x0004 +#define SUNI1x10GEXP_BITMSK_PL4MOS_NO_STATUS 0x0002 + +/*---------------------------------------------------------------------------- + * Register 0x2243: PL4MOS MaxBurst1 Register + * Bit 11-0 PL4MOS_MAX_BURST1 + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST1 0x0FFF +#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST1 0 + +/*---------------------------------------------------------------------------- + * Register 0x2244: PL4MOS MaxBurst2 Register + * Bit 11-0 PL4MOS_MAX_BURST2 + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_BURST2 0x0FFF +#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_BURST2 0 + +/*---------------------------------------------------------------------------- + * Register 0x2245: PL4MOS Transfer Size Register + * Bit 7-0 PL4MOS_MAX_TRANSFER + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4MOS_MAX_TRANSFER 0x00FF +#define SUNI1x10GEXP_BITOFF_PL4MOS_MAX_TRANSFER 0 + +/*---------------------------------------------------------------------------- + * Register 0x2280: PL4ODP Configuration + * Bit 15-12 PL4ODP_REPEAT_T + * Bit 8 PL4ODP_SOP_RULE + * Bit 1 PL4ODP_EN_PORTS + * Bit 0 PL4ODP_EN_DFWD + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4ODP_REPEAT_T 0xF000 +#define SUNI1x10GEXP_BITOFF_PL4ODP_REPEAT_T 12 +#define SUNI1x10GEXP_BITMSK_PL4ODP_SOP_RULE 0x0100 +#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_PORTS 0x0002 +#define SUNI1x10GEXP_BITMSK_PL4ODP_EN_DFWD 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x2282: PL4ODP Interrupt Mask + * Bit 0 PL4ODP_OUT_DISE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISE 0x0001 + + + +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBE 0x0080 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPE 0x0040 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPE 0x0008 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPE 0x0004 +#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRE 0x0002 + + +/*---------------------------------------------------------------------------- + * Register 0x2283: PL4ODP Interrupt + * Bit 0 PL4ODP_OUT_DISI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4ODP_OUT_DISI 0x0001 + + + +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_EOPEOBI 0x0080 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_ERREOPI 0x0040 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MEOPI 0x0008 +#define SUNI1x10GEXP_BITMSK_PL4ODP_PPE_MSOPI 0x0004 +#define SUNI1x10GEXP_BITMSK_PL4ODP_ES_OVRI 0x0002 + +/*---------------------------------------------------------------------------- + * Register 0x2300: PL4IO Lock Detect Status + * Bit 15 PL4IO_OUT_ROOLV + * Bit 12 PL4IO_IS_ROOLV + * Bit 11 PL4IO_DIP2_ERRV + * Bit 8 PL4IO_ID_ROOLV + * Bit 4 PL4IO_IS_DOOLV + * Bit 0 PL4IO_ID_DOOLV + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLV 0x8000 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLV 0x1000 +#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRV 0x0800 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLV 0x0100 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLV 0x0010 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLV 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x2301: PL4IO Lock Detect Change + * Bit 15 PL4IO_OUT_ROOLI + * Bit 12 PL4IO_IS_ROOLI + * Bit 11 PL4IO_DIP2_ERRI + * Bit 8 PL4IO_ID_ROOLI + * Bit 4 PL4IO_IS_DOOLI + * Bit 0 PL4IO_ID_DOOLI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLI 0x8000 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLI 0x1000 +#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRI 0x0800 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLI 0x0100 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLI 0x0010 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x2302: PL4IO Lock Detect Mask + * Bit 15 PL4IO_OUT_ROOLE + * Bit 12 PL4IO_IS_ROOLE + * Bit 11 PL4IO_DIP2_ERRE + * Bit 8 PL4IO_ID_ROOLE + * Bit 4 PL4IO_IS_DOOLE + * Bit 0 PL4IO_ID_DOOLE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_ROOLE 0x8000 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_ROOLE 0x1000 +#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERRE 0x0800 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_ROOLE 0x0100 +#define SUNI1x10GEXP_BITMSK_PL4IO_IS_DOOLE 0x0010 +#define SUNI1x10GEXP_BITMSK_PL4IO_ID_DOOLE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x2303: PL4IO Lock Detect Limits + * Bit 15-8 PL4IO_REF_LIMIT + * Bit 7-0 PL4IO_TRAN_LIMIT + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_REF_LIMIT 0xFF00 +#define SUNI1x10GEXP_BITOFF_PL4IO_REF_LIMIT 8 +#define SUNI1x10GEXP_BITMSK_PL4IO_TRAN_LIMIT 0x00FF +#define SUNI1x10GEXP_BITOFF_PL4IO_TRAN_LIMIT 0 + +/*---------------------------------------------------------------------------- + * Register 0x2304: PL4IO Calendar Repetitions + * Bit 15-8 PL4IO_IN_MUL + * Bit 7-0 PL4IO_OUT_MUL + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_IN_MUL 0xFF00 +#define SUNI1x10GEXP_BITOFF_PL4IO_IN_MUL 8 +#define SUNI1x10GEXP_BITMSK_PL4IO_OUT_MUL 0x00FF +#define SUNI1x10GEXP_BITOFF_PL4IO_OUT_MUL 0 + +/*---------------------------------------------------------------------------- + * Register 0x2305: PL4IO Configuration + * Bit 15 PL4IO_DIP2_ERR_CHK + * Bit 11 PL4IO_ODAT_DIS + * Bit 10 PL4IO_TRAIN_DIS + * Bit 9 PL4IO_OSTAT_DIS + * Bit 8 PL4IO_ISTAT_DIS + * Bit 7 PL4IO_NO_ISTAT + * Bit 6 PL4IO_STAT_OUTSEL + * Bit 5 PL4IO_INSEL + * Bit 4 PL4IO_DLSEL + * Bit 1-0 PL4IO_OUTSEL + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IO_DIP2_ERR_CHK 0x8000 +#define SUNI1x10GEXP_BITMSK_PL4IO_ODAT_DIS 0x0800 +#define SUNI1x10GEXP_BITMSK_PL4IO_TRAIN_DIS 0x0400 +#define SUNI1x10GEXP_BITMSK_PL4IO_OSTAT_DIS 0x0200 +#define SUNI1x10GEXP_BITMSK_PL4IO_ISTAT_DIS 0x0100 +#define SUNI1x10GEXP_BITMSK_PL4IO_NO_ISTAT 0x0080 +#define SUNI1x10GEXP_BITMSK_PL4IO_STAT_OUTSEL 0x0040 +#define SUNI1x10GEXP_BITMSK_PL4IO_INSEL 0x0020 +#define SUNI1x10GEXP_BITMSK_PL4IO_DLSEL 0x0010 +#define SUNI1x10GEXP_BITMSK_PL4IO_OUTSEL 0x0003 +#define SUNI1x10GEXP_BITOFF_PL4IO_OUTSEL 0 + /*---------------------------------------------------------------------------- * Register 0x3040: TXXG Configuration Register 1 * Bit 15 TXXG_TXEN0 @@ -202,12 +1378,266 @@ * Bit 0 TXXG_SPRE *----------------------------------------------------------------------------*/ #define SUNI1x10GEXP_BITMSK_TXXG_TXEN0 0x8000 +#define SUNI1x10GEXP_BITMSK_TXXG_HOSTPAUSE 0x2000 +#define SUNI1x10GEXP_BITMSK_TXXG_IPGT 0x1F80 #define SUNI1x10GEXP_BITOFF_TXXG_IPGT 7 #define SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN 0x0020 #define SUNI1x10GEXP_BITMSK_TXXG_CRCEN 0x0010 #define SUNI1x10GEXP_BITMSK_TXXG_FCTX 0x0008 #define SUNI1x10GEXP_BITMSK_TXXG_FCRX 0x0004 #define SUNI1x10GEXP_BITMSK_TXXG_PADEN 0x0002 +#define SUNI1x10GEXP_BITMSK_TXXG_SPRE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3041: TXXG Configuration Register 2 + * Bit 7-0 TXXG_HDRSIZE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_HDRSIZE 0x00FF + +/*---------------------------------------------------------------------------- + * Register 0x3042: TXXG Configuration Register 3 + * Bit 15 TXXG_FIFO_ERRE + * Bit 14 TXXG_FIFO_UDRE + * Bit 13 TXXG_MAX_LERRE + * Bit 12 TXXG_MIN_LERRE + * Bit 11 TXXG_XFERE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRE 0x8000 +#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRE 0x4000 +#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRE 0x2000 +#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRE 0x1000 +#define SUNI1x10GEXP_BITMSK_TXXG_XFERE 0x0800 + +/*---------------------------------------------------------------------------- + * Register 0x3043: TXXG Interrupt + * Bit 15 TXXG_FIFO_ERRI + * Bit 14 TXXG_FIFO_UDRI + * Bit 13 TXXG_MAX_LERRI + * Bit 12 TXXG_MIN_LERRI + * Bit 11 TXXG_XFERI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_ERRI 0x8000 +#define SUNI1x10GEXP_BITMSK_TXXG_FIFO_UDRI 0x4000 +#define SUNI1x10GEXP_BITMSK_TXXG_MAX_LERRI 0x2000 +#define SUNI1x10GEXP_BITMSK_TXXG_MIN_LERRI 0x1000 +#define SUNI1x10GEXP_BITMSK_TXXG_XFERI 0x0800 + +/*---------------------------------------------------------------------------- + * Register 0x3044: TXXG Status Register + * Bit 1 TXXG_TXACTIVE + * Bit 0 TXXG_PAUSED + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_TXACTIVE 0x0002 +#define SUNI1x10GEXP_BITMSK_TXXG_PAUSED 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3046: TXXG TX_MINFR - Transmit Min Frame Size Register + * Bit 7-0 TXXG_TX_MINFR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_TX_MINFR 0x00FF +#define SUNI1x10GEXP_BITOFF_TXXG_TX_MINFR 0 + +/*---------------------------------------------------------------------------- + * Register 0x3052: TXXG Pause Quantum Value Configuration Register + * Bit 7-0 TXXG_FC_PAUSE_QNTM + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXXG_FC_PAUSE_QNTM 0x00FF +#define SUNI1x10GEXP_BITOFF_TXXG_FC_PAUSE_QNTM 0 + +/*---------------------------------------------------------------------------- + * Register 0x3080: XTEF Control + * Bit 3-0 XTEF_FORCE_PARITY_ERR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_XTEF_FORCE_PARITY_ERR 0x000F +#define SUNI1x10GEXP_BITOFF_XTEF_FORCE_PARITY_ERR 0 + +/*---------------------------------------------------------------------------- + * Register 0x3084: XTEF Interrupt Event Register + * Bit 0 XTEF_LOST_SYNCI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3085: XTEF Interrupt Enable Register + * Bit 0 XTEF_LOST_SYNCE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3086: XTEF Visibility Register + * Bit 0 XTEF_LOST_SYNCV + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_XTEF_LOST_SYNCV 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x30C0: TXOAM OAM Configuration + * Bit 15 TXOAM_HEC_EN + * Bit 14 TXOAM_EMPTYCODE_EN + * Bit 13 TXOAM_FORCE_IDLE + * Bit 12 TXOAM_IGNORE_IDLE + * Bit 11-6 TXOAM_PX_OVERWRITE + * Bit 5-0 TXOAM_PX_SEL + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_HEC_EN 0x8000 +#define SUNI1x10GEXP_BITMSK_TXOAM_EMPTYCODE_EN 0x4000 +#define SUNI1x10GEXP_BITMSK_TXOAM_FORCE_IDLE 0x2000 +#define SUNI1x10GEXP_BITMSK_TXOAM_IGNORE_IDLE 0x1000 +#define SUNI1x10GEXP_BITMSK_TXOAM_PX_OVERWRITE 0x0FC0 +#define SUNI1x10GEXP_BITOFF_TXOAM_PX_OVERWRITE 6 +#define SUNI1x10GEXP_BITMSK_TXOAM_PX_SEL 0x003F +#define SUNI1x10GEXP_BITOFF_TXOAM_PX_SEL 0 + +/*---------------------------------------------------------------------------- + * Register 0x30C1: TXOAM Mini-Packet Rate Configuration + * Bit 15 TXOAM_MINIDIS + * Bit 14 TXOAM_BUSY + * Bit 13 TXOAM_TRANS_EN + * Bit 10-0 TXOAM_MINIRATE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_MINIDIS 0x8000 +#define SUNI1x10GEXP_BITMSK_TXOAM_BUSY 0x4000 +#define SUNI1x10GEXP_BITMSK_TXOAM_TRANS_EN 0x2000 +#define SUNI1x10GEXP_BITMSK_TXOAM_MINIRATE 0x07FF + +/*---------------------------------------------------------------------------- + * Register 0x30C2: TXOAM Mini-Packet Gap and FIFO Configuration + * Bit 13-10 TXOAM_FTHRESH + * Bit 9-6 TXOAM_MINIPOST + * Bit 5-0 TXOAM_MINIPRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_FTHRESH 0x3C00 +#define SUNI1x10GEXP_BITOFF_TXOAM_FTHRESH 10 +#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPOST 0x03C0 +#define SUNI1x10GEXP_BITOFF_TXOAM_MINIPOST 6 +#define SUNI1x10GEXP_BITMSK_TXOAM_MINIPRE 0x003F + +/*---------------------------------------------------------------------------- + * Register 0x30C6: TXOAM Interrupt Enable + * Bit 2 TXOAM_SOP_ERRE + * Bit 1 TXOAM_OFLE + * Bit 0 TXOAM_ERRE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRE 0x0004 +#define SUNI1x10GEXP_BITMSK_TXOAM_OFLE 0x0002 +#define SUNI1x10GEXP_BITMSK_TXOAM_ERRE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x30C7: TXOAM Interrupt Status + * Bit 2 TXOAM_SOP_ERRI + * Bit 1 TXOAM_OFLI + * Bit 0 TXOAM_ERRI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_SOP_ERRI 0x0004 +#define SUNI1x10GEXP_BITMSK_TXOAM_OFLI 0x0002 +#define SUNI1x10GEXP_BITMSK_TXOAM_ERRI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x30CF: TXOAM Coset + * Bit 7-0 TXOAM_COSET + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_TXOAM_COSET 0x00FF + +/*---------------------------------------------------------------------------- + * Register 0x3200: EFLX Global Configuration + * Bit 15 EFLX_ERCU_EN + * Bit 7 EFLX_EN_EDSWT + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_ERCU_EN 0x8000 +#define SUNI1x10GEXP_BITMSK_EFLX_EN_EDSWT 0x0080 + +/*---------------------------------------------------------------------------- + * Register 0x3201: EFLX ERCU Global Status + * Bit 13 EFLX_OVF_ERR + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_OVF_ERR 0x2000 + +/*---------------------------------------------------------------------------- + * Register 0x3202: EFLX Indirect Channel Address + * Bit 15 EFLX_BUSY + * Bit 14 EFLX_RDWRB + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_BUSY 0x8000 +#define SUNI1x10GEXP_BITMSK_EFLX_RDWRB 0x4000 + +/*---------------------------------------------------------------------------- + * Register 0x3203: EFLX Indirect Logical FIFO Low Limit + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_LOLIM 0x03FF +#define SUNI1x10GEXP_BITOFF_EFLX_LOLIM 0 + +/*---------------------------------------------------------------------------- + * Register 0x3204: EFLX Indirect Logical FIFO High Limit + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_HILIM 0x03FF +#define SUNI1x10GEXP_BITOFF_EFLX_HILIM 0 + +/*---------------------------------------------------------------------------- + * Register 0x3205: EFLX Indirect Full/Almost-Full Status and Limit + * Bit 15 EFLX_FULL + * Bit 14 EFLX_AFULL + * Bit 13-0 EFLX_AFTH + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_FULL 0x8000 +#define SUNI1x10GEXP_BITMSK_EFLX_AFULL 0x4000 +#define SUNI1x10GEXP_BITMSK_EFLX_AFTH 0x3FFF +#define SUNI1x10GEXP_BITOFF_EFLX_AFTH 0 + +/*---------------------------------------------------------------------------- + * Register 0x3206: EFLX Indirect Empty/Almost-Empty Status and Limit + * Bit 15 EFLX_EMPTY + * Bit 14 EFLX_AEMPTY + * Bit 13-0 EFLX_AETH + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_EMPTY 0x8000 +#define SUNI1x10GEXP_BITMSK_EFLX_AEMPTY 0x4000 +#define SUNI1x10GEXP_BITMSK_EFLX_AETH 0x3FFF +#define SUNI1x10GEXP_BITOFF_EFLX_AETH 0 + +/*---------------------------------------------------------------------------- + * Register 0x3207: EFLX Indirect FIFO Cut-Through Threshold + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_CUT_THRU 0x3FFF +#define SUNI1x10GEXP_BITOFF_EFLX_CUT_THRU 0 + +/*---------------------------------------------------------------------------- + * Register 0x320C: EFLX FIFO Overflow Error Enable + * Bit 0 EFLX_OVFE + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_OVFE 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x320D: EFLX FIFO Overflow Error Indication + * Bit 0 EFLX_OVFI + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_OVFI 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3210: EFLX Channel Provision + * Bit 0 EFLX_PROV + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_EFLX_PROV 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3280: PL4IDU Configuration + * Bit 2 PL4IDU_SYNCH_ON_TRAIN + * Bit 1 PL4IDU_EN_PORTS + * Bit 0 PL4IDU_EN_DFWD + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IDU_SYNCH_ON_TRAIN 0x0004 +#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_PORTS 0x0002 +#define SUNI1x10GEXP_BITMSK_PL4IDU_EN_DFWD 0x0001 + +/*---------------------------------------------------------------------------- + * Register 0x3282: PL4IDU Interrupt Mask + * Bit 1 PL4IDU_DIP4E + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4E 0x0002 + +/*---------------------------------------------------------------------------- + * Register 0x3283: PL4IDU Interrupt + * Bit 1 PL4IDU_DIP4I + *----------------------------------------------------------------------------*/ +#define SUNI1x10GEXP_BITMSK_PL4IDU_DIP4I 0x0002 #endif /* _CXGB_SUNI1x10GEXP_REGS_H_ */ diff --git a/drivers/net/chelsio/tp.c b/drivers/net/chelsio/tp.c new file mode 100644 index 000000000000..04a7073e9d15 --- /dev/null +++ b/drivers/net/chelsio/tp.c @@ -0,0 +1,145 @@ +/* $Date: 2006/02/07 04:21:54 $ $RCSfile: tp.c,v $ $Revision: 1.73 $ */ +#include "common.h" +#include "regs.h" +#include "tp.h" + +struct petp { + adapter_t *adapter; +}; + +/* Pause deadlock avoidance parameters */ +#define DROP_MSEC 16 +#define DROP_PKTS_CNT 1 + +static void tp_init(adapter_t * ap, const struct tp_params *p, + unsigned int tp_clk) +{ + if (t1_is_asic(ap)) { + u32 val; + + val = F_TP_IN_CSPI_CPL | F_TP_IN_CSPI_CHECK_IP_CSUM | + F_TP_IN_CSPI_CHECK_TCP_CSUM | F_TP_IN_ESPI_ETHERNET; + if (!p->pm_size) + val |= F_OFFLOAD_DISABLE; + else + val |= F_TP_IN_ESPI_CHECK_IP_CSUM | + F_TP_IN_ESPI_CHECK_TCP_CSUM; + writel(val, ap->regs + A_TP_IN_CONFIG); + writel(F_TP_OUT_CSPI_CPL | + F_TP_OUT_ESPI_ETHERNET | + F_TP_OUT_ESPI_GENERATE_IP_CSUM | + F_TP_OUT_ESPI_GENERATE_TCP_CSUM, + ap->regs + A_TP_OUT_CONFIG); + writel(V_IP_TTL(64) | + F_PATH_MTU /* IP DF bit */ | + V_5TUPLE_LOOKUP(p->use_5tuple_mode) | + V_SYN_COOKIE_PARAMETER(29), + ap->regs + A_TP_GLOBAL_CONFIG); + /* + * Enable pause frame deadlock prevention. + */ + if (is_T2(ap) && ap->params.nports > 1) { + u32 drop_ticks = DROP_MSEC * (tp_clk / 1000); + + writel(F_ENABLE_TX_DROP | F_ENABLE_TX_ERROR | + V_DROP_TICKS_CNT(drop_ticks) | + V_NUM_PKTS_DROPPED(DROP_PKTS_CNT), + ap->regs + A_TP_TX_DROP_CONFIG); + } + + } +} + +void t1_tp_destroy(struct petp *tp) +{ + kfree(tp); +} + +struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p) +{ + struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL); + if (!tp) + return NULL; + + tp->adapter = adapter; + + return tp; +} + +void t1_tp_intr_enable(struct petp *tp) +{ + u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); + + { + /* We don't use any TP interrupts */ + writel(0, tp->adapter->regs + A_TP_INT_ENABLE); + writel(tp_intr | F_PL_INTR_TP, + tp->adapter->regs + A_PL_ENABLE); + } +} + +void t1_tp_intr_disable(struct petp *tp) +{ + u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); + + { + writel(0, tp->adapter->regs + A_TP_INT_ENABLE); + writel(tp_intr & ~F_PL_INTR_TP, + tp->adapter->regs + A_PL_ENABLE); + } +} + +void t1_tp_intr_clear(struct petp *tp) +{ + writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE); + writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE); +} + +int t1_tp_intr_handler(struct petp *tp) +{ + u32 cause; + + + cause = readl(tp->adapter->regs + A_TP_INT_CAUSE); + writel(cause, tp->adapter->regs + A_TP_INT_CAUSE); + return 0; +} + +static void set_csum_offload(struct petp *tp, u32 csum_bit, int enable) +{ + u32 val = readl(tp->adapter->regs + A_TP_GLOBAL_CONFIG); + + if (enable) + val |= csum_bit; + else + val &= ~csum_bit; + writel(val, tp->adapter->regs + A_TP_GLOBAL_CONFIG); +} + +void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable) +{ + set_csum_offload(tp, F_IP_CSUM, enable); +} + +void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable) +{ + set_csum_offload(tp, F_UDP_CSUM, enable); +} + +void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable) +{ + set_csum_offload(tp, F_TCP_CSUM, enable); +} + +/* + * Initialize TP state. tp_params contains initial settings for some TP + * parameters, particularly the one-time PM and CM settings. + */ +int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk) +{ + adapter_t *adapter = tp->adapter; + + tp_init(adapter, p, tp_clk); + writel(F_TP_RESET, adapter->regs + A_TP_RESET); + return 0; +} diff --git a/drivers/net/chelsio/tp.h b/drivers/net/chelsio/tp.h new file mode 100644 index 000000000000..32fc71e58913 --- /dev/null +++ b/drivers/net/chelsio/tp.h @@ -0,0 +1,73 @@ +/* $Date: 2005/03/07 23:59:05 $ $RCSfile: tp.h,v $ $Revision: 1.20 $ */ +#ifndef CHELSIO_TP_H +#define CHELSIO_TP_H + +#include "common.h" + +#define TP_MAX_RX_COALESCING_SIZE 16224U + +struct tp_mib_statistics { + + /* IP */ + u32 ipInReceive_hi; + u32 ipInReceive_lo; + u32 ipInHdrErrors_hi; + u32 ipInHdrErrors_lo; + u32 ipInAddrErrors_hi; + u32 ipInAddrErrors_lo; + u32 ipInUnknownProtos_hi; + u32 ipInUnknownProtos_lo; + u32 ipInDiscards_hi; + u32 ipInDiscards_lo; + u32 ipInDelivers_hi; + u32 ipInDelivers_lo; + u32 ipOutRequests_hi; + u32 ipOutRequests_lo; + u32 ipOutDiscards_hi; + u32 ipOutDiscards_lo; + u32 ipOutNoRoutes_hi; + u32 ipOutNoRoutes_lo; + u32 ipReasmTimeout; + u32 ipReasmReqds; + u32 ipReasmOKs; + u32 ipReasmFails; + + u32 reserved[8]; + + /* TCP */ + u32 tcpActiveOpens; + u32 tcpPassiveOpens; + u32 tcpAttemptFails; + u32 tcpEstabResets; + u32 tcpOutRsts; + u32 tcpCurrEstab; + u32 tcpInSegs_hi; + u32 tcpInSegs_lo; + u32 tcpOutSegs_hi; + u32 tcpOutSegs_lo; + u32 tcpRetransSeg_hi; + u32 tcpRetransSeg_lo; + u32 tcpInErrs_hi; + u32 tcpInErrs_lo; + u32 tcpRtoMin; + u32 tcpRtoMax; +}; + +struct petp; +struct tp_params; + +struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p); +void t1_tp_destroy(struct petp *tp); + +void t1_tp_intr_disable(struct petp *tp); +void t1_tp_intr_enable(struct petp *tp); +void t1_tp_intr_clear(struct petp *tp); +int t1_tp_intr_handler(struct petp *tp); + +void t1_tp_get_mib_statistics(adapter_t *adap, struct tp_mib_statistics *tps); +void t1_tp_set_udp_checksum_offload(struct petp *tp, int enable); +void t1_tp_set_tcp_checksum_offload(struct petp *tp, int enable); +void t1_tp_set_ip_checksum_offload(struct petp *tp, int enable); +int t1_tp_set_coalescing_size(struct petp *tp, unsigned int size); +int t1_tp_reset(struct petp *tp, struct tp_params *p, unsigned int tp_clk); +#endif diff --git a/drivers/net/chelsio/vsc7326_reg.h b/drivers/net/chelsio/vsc7326_reg.h new file mode 100644 index 000000000000..491bcf75c4fb --- /dev/null +++ b/drivers/net/chelsio/vsc7326_reg.h @@ -0,0 +1,286 @@ +/* $Date: 2006/04/28 19:20:17 $ $RCSfile: vsc7326_reg.h,v $ $Revision: 1.5 $ */ +#ifndef _VSC7321_REG_H_ +#define _VSC7321_REG_H_ + +/* Register definitions for Vitesse VSC7321 (Meigs II) MAC + * + * Straight off the data sheet, VMDS-10038 Rev 2.0 and + * PD0011-01-14-Meigs-II 2002-12-12 + */ + +/* Just 'cause it's in here doesn't mean it's used. */ + +#define CRA(blk,sub,adr) ((((blk) & 0x7) << 13) | (((sub) & 0xf) << 9) | (((adr) & 0xff) << 1)) + +/* System and CPU comm's registers */ +#define REG_CHIP_ID CRA(0x7,0xf,0x00) /* Chip ID */ +#define REG_BLADE_ID CRA(0x7,0xf,0x01) /* Blade ID */ +#define REG_SW_RESET CRA(0x7,0xf,0x02) /* Global Soft Reset */ +#define REG_MEM_BIST CRA(0x7,0xf,0x04) /* mem */ +#define REG_IFACE_MODE CRA(0x7,0xf,0x07) /* Interface mode */ +#define REG_MSCH CRA(0x7,0x2,0x06) /* CRC error count */ +#define REG_CRC_CNT CRA(0x7,0x2,0x0a) /* CRC error count */ +#define REG_CRC_CFG CRA(0x7,0x2,0x0b) /* CRC config */ +#define REG_SI_TRANSFER_SEL CRA(0x7,0xf,0x18) /* SI Transfer Select */ +#define REG_PLL_CLK_SPEED CRA(0x7,0xf,0x19) /* Clock Speed Selection */ +#define REG_SYS_CLK_SELECT CRA(0x7,0xf,0x1c) /* System Clock Select */ +#define REG_GPIO_CTRL CRA(0x7,0xf,0x1d) /* GPIO Control */ +#define REG_GPIO_OUT CRA(0x7,0xf,0x1e) /* GPIO Out */ +#define REG_GPIO_IN CRA(0x7,0xf,0x1f) /* GPIO In */ +#define REG_CPU_TRANSFER_SEL CRA(0x7,0xf,0x20) /* CPU Transfer Select */ +#define REG_LOCAL_DATA CRA(0x7,0xf,0xfe) /* Local CPU Data Register */ +#define REG_LOCAL_STATUS CRA(0x7,0xf,0xff) /* Local CPU Status Register */ + +/* Aggregator registers */ +#define REG_AGGR_SETUP CRA(0x7,0x1,0x00) /* Aggregator Setup */ +#define REG_PMAP_TABLE CRA(0x7,0x1,0x01) /* Port map table */ +#define REG_MPLS_BIT0 CRA(0x7,0x1,0x08) /* MPLS bit0 position */ +#define REG_MPLS_BIT1 CRA(0x7,0x1,0x09) /* MPLS bit1 position */ +#define REG_MPLS_BIT2 CRA(0x7,0x1,0x0a) /* MPLS bit2 position */ +#define REG_MPLS_BIT3 CRA(0x7,0x1,0x0b) /* MPLS bit3 position */ +#define REG_MPLS_BITMASK CRA(0x7,0x1,0x0c) /* MPLS bit mask */ +#define REG_PRE_BIT0POS CRA(0x7,0x1,0x10) /* Preamble bit0 position */ +#define REG_PRE_BIT1POS CRA(0x7,0x1,0x11) /* Preamble bit1 position */ +#define REG_PRE_BIT2POS CRA(0x7,0x1,0x12) /* Preamble bit2 position */ +#define REG_PRE_BIT3POS CRA(0x7,0x1,0x13) /* Preamble bit3 position */ +#define REG_PRE_ERR_CNT CRA(0x7,0x1,0x14) /* Preamble parity error count */ + +/* BIST registers */ +/*#define REG_RAM_BIST_CMD CRA(0x7,0x2,0x00)*/ /* RAM BIST Command Register */ +/*#define REG_RAM_BIST_RESULT CRA(0x7,0x2,0x01)*/ /* RAM BIST Read Status/Result */ +#define REG_RAM_BIST_CMD CRA(0x7,0x1,0x00) /* RAM BIST Command Register */ +#define REG_RAM_BIST_RESULT CRA(0x7,0x1,0x01) /* RAM BIST Read Status/Result */ +#define BIST_PORT_SELECT 0x00 /* BIST port select */ +#define BIST_COMMAND 0x01 /* BIST enable/disable */ +#define BIST_STATUS 0x02 /* BIST operation status */ +#define BIST_ERR_CNT_LSB 0x03 /* BIST error count lo 8b */ +#define BIST_ERR_CNT_MSB 0x04 /* BIST error count hi 8b */ +#define BIST_ERR_SEL_LSB 0x05 /* BIST error select lo 8b */ +#define BIST_ERR_SEL_MSB 0x06 /* BIST error select hi 8b */ +#define BIST_ERROR_STATE 0x07 /* BIST engine internal state */ +#define BIST_ERR_ADR0 0x08 /* BIST error address lo 8b */ +#define BIST_ERR_ADR1 0x09 /* BIST error address lomid 8b */ +#define BIST_ERR_ADR2 0x0a /* BIST error address himid 8b */ +#define BIST_ERR_ADR3 0x0b /* BIST error address hi 8b */ + +/* FIFO registers + * ie = 0 for ingress, 1 for egress + * fn = FIFO number, 0-9 + */ +#define REG_TEST(ie,fn) CRA(0x2,ie&1,0x00+fn) /* Mode & Test Register */ +#define REG_TOP_BOTTOM(ie,fn) CRA(0x2,ie&1,0x10+fn) /* FIFO Buffer Top & Bottom */ +#define REG_TAIL(ie,fn) CRA(0x2,ie&1,0x20+fn) /* FIFO Write Pointer */ +#define REG_HEAD(ie,fn) CRA(0x2,ie&1,0x30+fn) /* FIFO Read Pointer */ +#define REG_HIGH_LOW_WM(ie,fn) CRA(0x2,ie&1,0x40+fn) /* Flow Control Water Marks */ +#define REG_CT_THRHLD(ie,fn) CRA(0x2,ie&1,0x50+fn) /* Cut Through Threshold */ +#define REG_FIFO_DROP_CNT(ie,fn) CRA(0x2,ie&1,0x60+fn) /* Drop & CRC Error Counter */ +#define REG_DEBUG_BUF_CNT(ie,fn) CRA(0x2,ie&1,0x70+fn) /* Input Side Debug Counter */ +#define REG_BUCKI(fn) CRA(0x2,2,0x20+fn) /* Input Side Debug Counter */ +#define REG_BUCKE(fn) CRA(0x2,3,0x20+fn) /* Input Side Debug Counter */ + +/* Traffic shaper buckets + * ie = 0 for ingress, 1 for egress + * bn = bucket number 0-10 (yes, 11 buckets) + */ +/* OK, this one's kinda ugly. Some hardware designers are perverse. */ +#define REG_TRAFFIC_SHAPER_BUCKET(ie,bn) CRA(0x2,ie&1,0x0a + (bn>7) | ((bn&7)<<4)) +#define REG_TRAFFIC_SHAPER_CONTROL(ie) CRA(0x2,ie&1,0x3b) + +#define REG_SRAM_ADR(ie) CRA(0x2,ie&1,0x0e) /* FIFO SRAM address */ +#define REG_SRAM_WR_STRB(ie) CRA(0x2,ie&1,0x1e) /* FIFO SRAM write strobe */ +#define REG_SRAM_RD_STRB(ie) CRA(0x2,ie&1,0x2e) /* FIFO SRAM read strobe */ +#define REG_SRAM_DATA_0(ie) CRA(0x2,ie&1,0x3e) /* FIFO SRAM data lo 8b */ +#define REG_SRAM_DATA_1(ie) CRA(0x2,ie&1,0x4e) /* FIFO SRAM data lomid 8b */ +#define REG_SRAM_DATA_2(ie) CRA(0x2,ie&1,0x5e) /* FIFO SRAM data himid 8b */ +#define REG_SRAM_DATA_3(ie) CRA(0x2,ie&1,0x6e) /* FIFO SRAM data hi 8b */ +#define REG_SRAM_DATA_BLK_TYPE(ie) CRA(0x2,ie&1,0x7e) /* FIFO SRAM tag */ +/* REG_ING_CONTROL equals REG_CONTROL with ie = 0, likewise REG_EGR_CONTROL is ie = 1 */ +#define REG_CONTROL(ie) CRA(0x2,ie&1,0x0f) /* FIFO control */ +#define REG_ING_CONTROL CRA(0x2,0x0,0x0f) /* Ingress control (alias) */ +#define REG_EGR_CONTROL CRA(0x2,0x1,0x0f) /* Egress control (alias) */ +#define REG_AGE_TIMER(ie) CRA(0x2,ie&1,0x1f) /* Aging timer */ +#define REG_AGE_INC(ie) CRA(0x2,ie&1,0x2f) /* Aging increment */ +#define DEBUG_OUT(ie) CRA(0x2,ie&1,0x3f) /* Output debug counter control */ +#define DEBUG_CNT(ie) CRA(0x2,ie&1,0x4f) /* Output debug counter */ + +/* SPI4 interface */ +#define REG_SPI4_MISC CRA(0x5,0x0,0x00) /* Misc Register */ +#define REG_SPI4_STATUS CRA(0x5,0x0,0x01) /* CML Status */ +#define REG_SPI4_ING_SETUP0 CRA(0x5,0x0,0x02) /* Ingress Status Channel Setup */ +#define REG_SPI4_ING_SETUP1 CRA(0x5,0x0,0x03) /* Ingress Data Training Setup */ +#define REG_SPI4_ING_SETUP2 CRA(0x5,0x0,0x04) /* Ingress Data Burst Size Setup */ +#define REG_SPI4_EGR_SETUP0 CRA(0x5,0x0,0x05) /* Egress Status Channel Setup */ +#define REG_SPI4_DBG_CNT(n) CRA(0x5,0x0,0x10+n) /* Debug counters 0-9 */ +#define REG_SPI4_DBG_SETUP CRA(0x5,0x0,0x1A) /* Debug counters setup */ +#define REG_SPI4_TEST CRA(0x5,0x0,0x20) /* Test Setup Register */ +#define REG_TPGEN_UP0 CRA(0x5,0x0,0x21) /* Test Pattern generator user pattern 0 */ +#define REG_TPGEN_UP1 CRA(0x5,0x0,0x22) /* Test Pattern generator user pattern 1 */ +#define REG_TPCHK_UP0 CRA(0x5,0x0,0x23) /* Test Pattern checker user pattern 0 */ +#define REG_TPCHK_UP1 CRA(0x5,0x0,0x24) /* Test Pattern checker user pattern 1 */ +#define REG_TPSAM_P0 CRA(0x5,0x0,0x25) /* Sampled pattern 0 */ +#define REG_TPSAM_P1 CRA(0x5,0x0,0x26) /* Sampled pattern 1 */ +#define REG_TPERR_CNT CRA(0x5,0x0,0x27) /* Pattern checker error counter */ +#define REG_SPI4_STICKY CRA(0x5,0x0,0x30) /* Sticky bits register */ +#define REG_SPI4_DBG_INH CRA(0x5,0x0,0x31) /* Core egress & ingress inhibit */ +#define REG_SPI4_DBG_STATUS CRA(0x5,0x0,0x32) /* Sampled ingress status */ +#define REG_SPI4_DBG_GRANT CRA(0x5,0x0,0x33) /* Ingress cranted credit value */ + +#define REG_SPI4_DESKEW CRA(0x5,0x0,0x43) /* Ingress cranted credit value */ + +/* 10GbE MAC Block Registers */ +/* Note that those registers that are exactly the same for 10GbE as for + * tri-speed are only defined with the version that needs a port number. + * Pass 0xa in those cases. + * + * Also note that despite the presence of a MAC address register, this part + * does no ingress MAC address filtering. That register is used only for + * pause frame detection and generation. + */ +/* 10GbE specific, and different from tri-speed */ +#define REG_MISC_10G CRA(0x1,0xa,0x00) /* Misc 10GbE setup */ +#define REG_PAUSE_10G CRA(0x1,0xa,0x01) /* Pause register */ +#define REG_NORMALIZER_10G CRA(0x1,0xa,0x05) /* 10G normalizer */ +#define REG_STICKY_RX CRA(0x1,0xa,0x06) /* RX debug register */ +#define REG_DENORM_10G CRA(0x1,0xa,0x07) /* Denormalizer */ +#define REG_STICKY_TX CRA(0x1,0xa,0x08) /* TX sticky bits */ +#define REG_MAX_RXHIGH CRA(0x1,0xa,0x0a) /* XGMII lane 0-3 debug */ +#define REG_MAX_RXLOW CRA(0x1,0xa,0x0b) /* XGMII lane 4-7 debug */ +#define REG_MAC_TX_STICKY CRA(0x1,0xa,0x0c) /* MAC Tx state sticky debug */ +#define REG_MAC_TX_RUNNING CRA(0x1,0xa,0x0d) /* MAC Tx state running debug */ +#define REG_TX_ABORT_AGE CRA(0x1,0xa,0x14) /* Aged Tx frames discarded */ +#define REG_TX_ABORT_SHORT CRA(0x1,0xa,0x15) /* Short Tx frames discarded */ +#define REG_TX_ABORT_TAXI CRA(0x1,0xa,0x16) /* Taxi error frames discarded */ +#define REG_TX_ABORT_UNDERRUN CRA(0x1,0xa,0x17) /* Tx Underrun abort counter */ +#define REG_TX_DENORM_DISCARD CRA(0x1,0xa,0x18) /* Tx denormalizer discards */ +#define REG_XAUI_STAT_A CRA(0x1,0xa,0x20) /* XAUI status A */ +#define REG_XAUI_STAT_B CRA(0x1,0xa,0x21) /* XAUI status B */ +#define REG_XAUI_STAT_C CRA(0x1,0xa,0x22) /* XAUI status C */ +#define REG_XAUI_CONF_A CRA(0x1,0xa,0x23) /* XAUI configuration A */ +#define REG_XAUI_CONF_B CRA(0x1,0xa,0x24) /* XAUI configuration B */ +#define REG_XAUI_CODE_GRP_CNT CRA(0x1,0xa,0x25) /* XAUI code group error count */ +#define REG_XAUI_CONF_TEST_A CRA(0x1,0xa,0x26) /* XAUI test register A */ +#define REG_PDERRCNT CRA(0x1,0xa,0x27) /* XAUI test register B */ + +/* pn = port number 0-9 for tri-speed, 10 for 10GbE */ +/* Both tri-speed and 10GbE */ +#define REG_MAX_LEN(pn) CRA(0x1,pn,0x02) /* Max length */ +#define REG_MAC_HIGH_ADDR(pn) CRA(0x1,pn,0x03) /* Upper 24 bits of MAC addr */ +#define REG_MAC_LOW_ADDR(pn) CRA(0x1,pn,0x04) /* Lower 24 bits of MAC addr */ + +/* tri-speed only + * pn = port number, 0-9 + */ +#define REG_MODE_CFG(pn) CRA(0x1,pn,0x00) /* Mode configuration */ +#define REG_PAUSE_CFG(pn) CRA(0x1,pn,0x01) /* Pause configuration */ +#define REG_NORMALIZER(pn) CRA(0x1,pn,0x05) /* Normalizer */ +#define REG_TBI_STATUS(pn) CRA(0x1,pn,0x06) /* TBI status */ +#define REG_PCS_STATUS_DBG(pn) CRA(0x1,pn,0x07) /* PCS status debug */ +#define REG_PCS_CTRL(pn) CRA(0x1,pn,0x08) /* PCS control */ +#define REG_TBI_CONFIG(pn) CRA(0x1,pn,0x09) /* TBI configuration */ +#define REG_STICK_BIT(pn) CRA(0x1,pn,0x0a) /* Sticky bits */ +#define REG_DEV_SETUP(pn) CRA(0x1,pn,0x0b) /* MAC clock/reset setup */ +#define REG_DROP_CNT(pn) CRA(0x1,pn,0x0c) /* Drop counter */ +#define REG_PORT_POS(pn) CRA(0x1,pn,0x0d) /* Preamble port position */ +#define REG_PORT_FAIL(pn) CRA(0x1,pn,0x0e) /* Preamble port position */ +#define REG_SERDES_CONF(pn) CRA(0x1,pn,0x0f) /* SerDes configuration */ +#define REG_SERDES_TEST(pn) CRA(0x1,pn,0x10) /* SerDes test */ +#define REG_SERDES_STAT(pn) CRA(0x1,pn,0x11) /* SerDes status */ +#define REG_SERDES_COM_CNT(pn) CRA(0x1,pn,0x12) /* SerDes comma counter */ +#define REG_DENORM(pn) CRA(0x1,pn,0x15) /* Frame denormalization */ +#define REG_DBG(pn) CRA(0x1,pn,0x16) /* Device 1G debug */ +#define REG_TX_IFG(pn) CRA(0x1,pn,0x18) /* Tx IFG config */ +#define REG_HDX(pn) CRA(0x1,pn,0x19) /* Half-duplex config */ + +/* Statistics */ +/* pn = port number, 0-a, a = 10GbE */ +#define REG_RX_IN_BYTES(pn) CRA(0x4,pn,0x00) /* # Rx in octets */ +#define REG_RX_SYMBOL_CARRIER(pn) CRA(0x4,pn,0x01) /* Frames w/ symbol errors */ +#define REG_RX_PAUSE(pn) CRA(0x4,pn,0x02) /* # pause frames received */ +#define REG_RX_UNSUP_OPCODE(pn) CRA(0x4,pn,0x03) /* # control frames with unsupported opcode */ +#define REG_RX_OK_BYTES(pn) CRA(0x4,pn,0x04) /* # octets in good frames */ +#define REG_RX_BAD_BYTES(pn) CRA(0x4,pn,0x05) /* # octets in bad frames */ +#define REG_RX_UNICAST(pn) CRA(0x4,pn,0x06) /* # good unicast frames */ +#define REG_RX_MULTICAST(pn) CRA(0x4,pn,0x07) /* # good multicast frames */ +#define REG_RX_BROADCAST(pn) CRA(0x4,pn,0x08) /* # good broadcast frames */ +#define REG_CRC(pn) CRA(0x4,pn,0x09) /* # frames w/ bad CRC only */ +#define REG_RX_ALIGNMENT(pn) CRA(0x4,pn,0x0a) /* # frames w/ alignment err */ +#define REG_RX_UNDERSIZE(pn) CRA(0x4,pn,0x0b) /* # frames undersize */ +#define REG_RX_FRAGMENTS(pn) CRA(0x4,pn,0x0c) /* # frames undersize w/ crc err */ +#define REG_RX_IN_RANGE_LENGTH_ERROR(pn) CRA(0x4,pn,0x0d) /* # frames with length error */ +#define REG_RX_OUT_OF_RANGE_ERROR(pn) CRA(0x4,pn,0x0e) /* # frames with illegal length field */ +#define REG_RX_OVERSIZE(pn) CRA(0x4,pn,0x0f) /* # frames oversize */ +#define REG_RX_JABBERS(pn) CRA(0x4,pn,0x10) /* # frames oversize w/ crc err */ +#define REG_RX_SIZE_64(pn) CRA(0x4,pn,0x11) /* # frames 64 octets long */ +#define REG_RX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x12) /* # frames 65-127 octets */ +#define REG_RX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x13) /* # frames 128-255 */ +#define REG_RX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x14) /* # frames 256-511 */ +#define REG_RX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x15) /* # frames 512-1023 */ +#define REG_RX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x16) /* # frames 1024-1518 */ +#define REG_RX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x17) /* # frames 1519-max */ + +#define REG_TX_OUT_BYTES(pn) CRA(0x4,pn,0x18) /* # octets tx */ +#define REG_TX_PAUSE(pn) CRA(0x4,pn,0x19) /* # pause frames sent */ +#define REG_TX_OK_BYTES(pn) CRA(0x4,pn,0x1a) /* # octets tx OK */ +#define REG_TX_UNICAST(pn) CRA(0x4,pn,0x1b) /* # frames unicast */ +#define REG_TX_MULTICAST(pn) CRA(0x4,pn,0x1c) /* # frames multicast */ +#define REG_TX_BROADCAST(pn) CRA(0x4,pn,0x1d) /* # frames broadcast */ +#define REG_TX_MULTIPLE_COLL(pn) CRA(0x4,pn,0x1e) /* # frames tx after multiple collisions */ +#define REG_TX_LATE_COLL(pn) CRA(0x4,pn,0x1f) /* # late collisions detected */ +#define REG_TX_XCOLL(pn) CRA(0x4,pn,0x20) /* # frames lost, excessive collisions */ +#define REG_TX_DEFER(pn) CRA(0x4,pn,0x21) /* # frames deferred on first tx attempt */ +#define REG_TX_XDEFER(pn) CRA(0x4,pn,0x22) /* # frames excessively deferred */ +#define REG_TX_CSENSE(pn) CRA(0x4,pn,0x23) /* carrier sense errors at frame end */ +#define REG_TX_SIZE_64(pn) CRA(0x4,pn,0x24) /* # frames 64 octets long */ +#define REG_TX_SIZE_65_TO_127(pn) CRA(0x4,pn,0x25) /* # frames 65-127 octets */ +#define REG_TX_SIZE_128_TO_255(pn) CRA(0x4,pn,0x26) /* # frames 128-255 */ +#define REG_TX_SIZE_256_TO_511(pn) CRA(0x4,pn,0x27) /* # frames 256-511 */ +#define REG_TX_SIZE_512_TO_1023(pn) CRA(0x4,pn,0x28) /* # frames 512-1023 */ +#define REG_TX_SIZE_1024_TO_1518(pn) CRA(0x4,pn,0x29) /* # frames 1024-1518 */ +#define REG_TX_SIZE_1519_TO_MAX(pn) CRA(0x4,pn,0x2a) /* # frames 1519-max */ +#define REG_TX_SINGLE_COLL(pn) CRA(0x4,pn,0x2b) /* # frames tx after single collision */ +#define REG_TX_BACKOFF2(pn) CRA(0x4,pn,0x2c) /* # frames tx ok after 2 backoffs/collisions */ +#define REG_TX_BACKOFF3(pn) CRA(0x4,pn,0x2d) /* after 3 backoffs/collisions */ +#define REG_TX_BACKOFF4(pn) CRA(0x4,pn,0x2e) /* after 4 */ +#define REG_TX_BACKOFF5(pn) CRA(0x4,pn,0x2f) /* after 5 */ +#define REG_TX_BACKOFF6(pn) CRA(0x4,pn,0x30) /* after 6 */ +#define REG_TX_BACKOFF7(pn) CRA(0x4,pn,0x31) /* after 7 */ +#define REG_TX_BACKOFF8(pn) CRA(0x4,pn,0x32) /* after 8 */ +#define REG_TX_BACKOFF9(pn) CRA(0x4,pn,0x33) /* after 9 */ +#define REG_TX_BACKOFF10(pn) CRA(0x4,pn,0x34) /* after 10 */ +#define REG_TX_BACKOFF11(pn) CRA(0x4,pn,0x35) /* after 11 */ +#define REG_TX_BACKOFF12(pn) CRA(0x4,pn,0x36) /* after 12 */ +#define REG_TX_BACKOFF13(pn) CRA(0x4,pn,0x37) /* after 13 */ +#define REG_TX_BACKOFF14(pn) CRA(0x4,pn,0x38) /* after 14 */ +#define REG_TX_BACKOFF15(pn) CRA(0x4,pn,0x39) /* after 15 */ +#define REG_TX_UNDERRUN(pn) CRA(0x4,pn,0x3a) /* # frames dropped from underrun */ +#define REG_RX_XGMII_PROT_ERR CRA(0x4,0xa,0x3b) /* # protocol errors detected on XGMII interface */ +#define REG_RX_IPG_SHRINK(pn) CRA(0x4,pn,0x3c) /* # of IPG shrinks detected */ + +#define REG_STAT_STICKY1G(pn) CRA(0x4,pn,0x3e) /* tri-speed sticky bits */ +#define REG_STAT_STICKY10G CRA(0x4,0xa,0x3e) /* 10GbE sticky bits */ +#define REG_STAT_INIT(pn) CRA(0x4,pn,0x3f) /* Clear all statistics */ + +/* MII-Management Block registers */ +/* These are for MII-M interface 0, which is the bidirectional LVTTL one. If + * we hooked up to the one with separate directions, the middle 0x0 needs to + * change to 0x1. And the current errata states that MII-M 1 doesn't work. + */ + +#define REG_MIIM_STATUS CRA(0x3,0x0,0x00) /* MII-M Status */ +#define REG_MIIM_CMD CRA(0x3,0x0,0x01) /* MII-M Command */ +#define REG_MIIM_DATA CRA(0x3,0x0,0x02) /* MII-M Data */ +#define REG_MIIM_PRESCALE CRA(0x3,0x0,0x03) /* MII-M MDC Prescale */ + +#define REG_ING_FFILT_UM_EN CRA(0x2, 0, 0xd) +#define REG_ING_FFILT_BE_EN CRA(0x2, 0, 0x1d) +#define REG_ING_FFILT_VAL0 CRA(0x2, 0, 0x2d) +#define REG_ING_FFILT_VAL1 CRA(0x2, 0, 0x3d) +#define REG_ING_FFILT_MASK0 CRA(0x2, 0, 0x4d) +#define REG_ING_FFILT_MASK1 CRA(0x2, 0, 0x5d) +#define REG_ING_FFILT_MASK2 CRA(0x2, 0, 0x6d) +#define REG_ING_FFILT_ETYPE CRA(0x2, 0, 0x7d) + + +/* Whew. */ + +#endif -- cgit v1.2.3 From 352c417ddb593de757f0ee1fa490cb5444778c41 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:17 -0800 Subject: [PATCH] chelsio: add 1G swcixw aupport Add support for 1G versions of Chelsio devices. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 7 + drivers/net/chelsio/Makefile | 1 + drivers/net/chelsio/common.h | 2 + drivers/net/chelsio/cxgb2.c | 1 + drivers/net/chelsio/ixf1010.c | 485 +++++++++++++++++++++++++ drivers/net/chelsio/mac.c | 368 +++++++++++++++++++ drivers/net/chelsio/mv88e1xxx.c | 397 +++++++++++++++++++++ drivers/net/chelsio/subr.c | 221 ++++++++++++ drivers/net/chelsio/tp.c | 33 ++ drivers/net/chelsio/vsc7326.c | 725 ++++++++++++++++++++++++++++++++++++++ drivers/net/chelsio/vsc8244.c | 368 +++++++++++++++++++ drivers/net/chelsio/vsc8244_reg.h | 172 +++++++++ 12 files changed, 2780 insertions(+) create mode 100644 drivers/net/chelsio/ixf1010.c create mode 100644 drivers/net/chelsio/mac.c create mode 100644 drivers/net/chelsio/mv88e1xxx.c create mode 100644 drivers/net/chelsio/vsc7326.c create mode 100644 drivers/net/chelsio/vsc8244.c create mode 100644 drivers/net/chelsio/vsc8244_reg.h (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 2f10dd554e33..ee391f29dae7 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2376,6 +2376,13 @@ config CHELSIO_T1 To compile this driver as a module, choose M here: the module will be called cxgb. +config CHELSIO_T1_1G + bool "Chelsio gigabit Ethernet support" + depends on CHELSIO_T1 + help + Enables support for Chelsio's gigabit Ethernet PCI cards. If you + are using only 10G cards say 'N' here. + config EHEA tristate "eHEA Ethernet support" depends on IBMEBUS diff --git a/drivers/net/chelsio/Makefile b/drivers/net/chelsio/Makefile index 6d87316e58cb..382d23f810ab 100644 --- a/drivers/net/chelsio/Makefile +++ b/drivers/net/chelsio/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_CHELSIO_T1) += cxgb.o +cxgb-$(CONFIG_CHELSIO_T1_1G) += ixf1010.o mac.o mv88e1xxx.o vsc7326.o vsc8244.o cxgb-objs := cxgb2.o espi.o tp.o pm3393.o sge.o subr.o \ mv88x201x.o my3126.o $(cxgb-y) diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index e4e59d2d410e..55f1eaad115c 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -283,6 +283,8 @@ struct adapter { spinlock_t tpi_lock; spinlock_t work_lock; + spinlock_t mac_lock; + /* guards async operations */ spinlock_t async_lock ____cacheline_aligned; u32 slow_intr_mask; diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index a8c873b0af54..571aa06ddfd4 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -1094,6 +1094,7 @@ static int __devinit init_one(struct pci_dev *pdev, spin_lock_init(&adapter->tpi_lock); spin_lock_init(&adapter->work_lock); spin_lock_init(&adapter->async_lock); + spin_lock_init(&adapter->mac_lock); INIT_WORK(&adapter->ext_intr_handler_task, ext_intr_task, adapter); diff --git a/drivers/net/chelsio/ixf1010.c b/drivers/net/chelsio/ixf1010.c new file mode 100644 index 000000000000..5b8f144e83d4 --- /dev/null +++ b/drivers/net/chelsio/ixf1010.c @@ -0,0 +1,485 @@ +/* $Date: 2005/11/12 02:13:49 $ $RCSfile: ixf1010.c,v $ $Revision: 1.36 $ */ +#include "gmac.h" +#include "elmer0.h" + +/* Update fast changing statistics every 15 seconds */ +#define STATS_TICK_SECS 15 +/* 30 minutes for full statistics update */ +#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS) + +/* + * The IXF1010 can handle frames up to 16383 bytes but it's optimized for + * frames up to 9831 (0x2667) bytes, so we limit jumbo frame size to this. + * This length includes ethernet header and FCS. + */ +#define MAX_FRAME_SIZE 0x2667 + +/* MAC registers */ +enum { + /* Per-port registers */ + REG_MACADDR_LOW = 0, + REG_MACADDR_HIGH = 0x4, + REG_FDFC_TYPE = 0xC, + REG_FC_TX_TIMER_VALUE = 0x1c, + REG_IPG_RX_TIME1 = 0x28, + REG_IPG_RX_TIME2 = 0x2c, + REG_IPG_TX_TIME = 0x30, + REG_PAUSE_THRES = 0x38, + REG_MAX_FRAME_SIZE = 0x3c, + REG_RGMII_SPEED = 0x40, + REG_FC_ENABLE = 0x48, + REG_DISCARD_CTRL_FRAMES = 0x54, + REG_DIVERSE_CONFIG = 0x60, + REG_RX_FILTER = 0x64, + REG_MC_ADDR_LOW = 0x68, + REG_MC_ADDR_HIGH = 0x6c, + + REG_RX_OCTETS_OK = 0x80, + REG_RX_OCTETS_BAD = 0x84, + REG_RX_UC_PKTS = 0x88, + REG_RX_MC_PKTS = 0x8c, + REG_RX_BC_PKTS = 0x90, + REG_RX_FCS_ERR = 0xb0, + REG_RX_TAGGED = 0xb4, + REG_RX_DATA_ERR = 0xb8, + REG_RX_ALIGN_ERR = 0xbc, + REG_RX_LONG_ERR = 0xc0, + REG_RX_JABBER_ERR = 0xc4, + REG_RX_PAUSE_FRAMES = 0xc8, + REG_RX_UNKNOWN_CTRL_FRAMES = 0xcc, + REG_RX_VERY_LONG_ERR = 0xd0, + REG_RX_RUNT_ERR = 0xd4, + REG_RX_SHORT_ERR = 0xd8, + REG_RX_SYMBOL_ERR = 0xe4, + + REG_TX_OCTETS_OK = 0x100, + REG_TX_OCTETS_BAD = 0x104, + REG_TX_UC_PKTS = 0x108, + REG_TX_MC_PKTS = 0x10c, + REG_TX_BC_PKTS = 0x110, + REG_TX_EXCESSIVE_LEN_DROP = 0x14c, + REG_TX_UNDERRUN = 0x150, + REG_TX_TAGGED = 0x154, + REG_TX_PAUSE_FRAMES = 0x15C, + + /* Global registers */ + REG_PORT_ENABLE = 0x1400, + + REG_JTAG_ID = 0x1430, + + RX_FIFO_HIGH_WATERMARK_BASE = 0x1600, + RX_FIFO_LOW_WATERMARK_BASE = 0x1628, + RX_FIFO_FRAMES_REMOVED_BASE = 0x1650, + + REG_RX_ERR_DROP = 0x167c, + REG_RX_FIFO_OVERFLOW_EVENT = 0x1680, + + TX_FIFO_HIGH_WATERMARK_BASE = 0x1800, + TX_FIFO_LOW_WATERMARK_BASE = 0x1828, + TX_FIFO_XFER_THRES_BASE = 0x1850, + + REG_TX_FIFO_OVERFLOW_EVENT = 0x1878, + REG_TX_FIFO_OOS_EVENT = 0x1884, + + TX_FIFO_FRAMES_REMOVED_BASE = 0x1888, + + REG_SPI_RX_BURST = 0x1c00, + REG_SPI_RX_TRAINING = 0x1c04, + REG_SPI_RX_CALENDAR = 0x1c08, + REG_SPI_TX_SYNC = 0x1c0c +}; + +enum { /* RMON registers */ + REG_RxOctetsTotalOK = 0x80, + REG_RxOctetsBad = 0x84, + REG_RxUCPkts = 0x88, + REG_RxMCPkts = 0x8c, + REG_RxBCPkts = 0x90, + REG_RxJumboPkts = 0xac, + REG_RxFCSErrors = 0xb0, + REG_RxDataErrors = 0xb8, + REG_RxAlignErrors = 0xbc, + REG_RxLongErrors = 0xc0, + REG_RxJabberErrors = 0xc4, + REG_RxPauseMacControlCounter = 0xc8, + REG_RxVeryLongErrors = 0xd0, + REG_RxRuntErrors = 0xd4, + REG_RxShortErrors = 0xd8, + REG_RxSequenceErrors = 0xe0, + REG_RxSymbolErrors = 0xe4, + + REG_TxOctetsTotalOK = 0x100, + REG_TxOctetsBad = 0x104, + REG_TxUCPkts = 0x108, + REG_TxMCPkts = 0x10c, + REG_TxBCPkts = 0x110, + REG_TxJumboPkts = 0x12C, + REG_TxTotalCollisions = 0x134, + REG_TxExcessiveLengthDrop = 0x14c, + REG_TxUnderrun = 0x150, + REG_TxCRCErrors = 0x158, + REG_TxPauseFrames = 0x15c +}; + +enum { + DIVERSE_CONFIG_PAD_ENABLE = 0x80, + DIVERSE_CONFIG_CRC_ADD = 0x40 +}; + +#define MACREG_BASE 0 +#define MACREG(mac, mac_reg) ((mac)->instance->mac_base + (mac_reg)) + +struct _cmac_instance { + u32 mac_base; + u32 index; + u32 version; + u32 ticks; +}; + +static void disable_port(struct cmac *mac) +{ + u32 val; + + t1_tpi_read(mac->adapter, REG_PORT_ENABLE, &val); + val &= ~(1 << mac->instance->index); + t1_tpi_write(mac->adapter, REG_PORT_ENABLE, val); +} + +#define RMON_UPDATE(mac, name, stat_name) \ + t1_tpi_read((mac)->adapter, MACREG(mac, REG_##name), &val); \ + (mac)->stats.stat_name += val; + +/* + * Read the current values of the RMON counters and add them to the cumulative + * port statistics. The HW RMON counters are cleared by this operation. + */ +static void port_stats_update(struct cmac *mac) +{ + u32 val; + + /* Rx stats */ + RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK); + RMON_UPDATE(mac, RxOctetsBad, RxOctetsBad); + RMON_UPDATE(mac, RxUCPkts, RxUnicastFramesOK); + RMON_UPDATE(mac, RxMCPkts, RxMulticastFramesOK); + RMON_UPDATE(mac, RxBCPkts, RxBroadcastFramesOK); + RMON_UPDATE(mac, RxJumboPkts, RxJumboFramesOK); + RMON_UPDATE(mac, RxFCSErrors, RxFCSErrors); + RMON_UPDATE(mac, RxAlignErrors, RxAlignErrors); + RMON_UPDATE(mac, RxLongErrors, RxFrameTooLongErrors); + RMON_UPDATE(mac, RxVeryLongErrors, RxFrameTooLongErrors); + RMON_UPDATE(mac, RxPauseMacControlCounter, RxPauseFrames); + RMON_UPDATE(mac, RxDataErrors, RxDataErrors); + RMON_UPDATE(mac, RxJabberErrors, RxJabberErrors); + RMON_UPDATE(mac, RxRuntErrors, RxRuntErrors); + RMON_UPDATE(mac, RxShortErrors, RxRuntErrors); + RMON_UPDATE(mac, RxSequenceErrors, RxSequenceErrors); + RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors); + + /* Tx stats (skip collision stats as we are full-duplex only) */ + RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK); + RMON_UPDATE(mac, TxOctetsBad, TxOctetsBad); + RMON_UPDATE(mac, TxUCPkts, TxUnicastFramesOK); + RMON_UPDATE(mac, TxMCPkts, TxMulticastFramesOK); + RMON_UPDATE(mac, TxBCPkts, TxBroadcastFramesOK); + RMON_UPDATE(mac, TxJumboPkts, TxJumboFramesOK); + RMON_UPDATE(mac, TxPauseFrames, TxPauseFrames); + RMON_UPDATE(mac, TxExcessiveLengthDrop, TxLengthErrors); + RMON_UPDATE(mac, TxUnderrun, TxUnderrun); + RMON_UPDATE(mac, TxCRCErrors, TxFCSErrors); +} + +/* No-op interrupt operation as this MAC does not support interrupts */ +static int mac_intr_op(struct cmac *mac) +{ + return 0; +} + +/* Expect MAC address to be in network byte order. */ +static int mac_set_address(struct cmac *mac, u8 addr[6]) +{ + u32 addr_lo, addr_hi; + + addr_lo = addr[2]; + addr_lo = (addr_lo << 8) | addr[3]; + addr_lo = (addr_lo << 8) | addr[4]; + addr_lo = (addr_lo << 8) | addr[5]; + + addr_hi = addr[0]; + addr_hi = (addr_hi << 8) | addr[1]; + + t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_LOW), addr_lo); + t1_tpi_write(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), addr_hi); + return 0; +} + +static int mac_get_address(struct cmac *mac, u8 addr[6]) +{ + u32 addr_lo, addr_hi; + + t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_LOW), &addr_lo); + t1_tpi_read(mac->adapter, MACREG(mac, REG_MACADDR_HIGH), &addr_hi); + + addr[0] = (u8) (addr_hi >> 8); + addr[1] = (u8) addr_hi; + addr[2] = (u8) (addr_lo >> 24); + addr[3] = (u8) (addr_lo >> 16); + addr[4] = (u8) (addr_lo >> 8); + addr[5] = (u8) addr_lo; + return 0; +} + +/* This is intended to reset a port, not the whole MAC */ +static int mac_reset(struct cmac *mac) +{ + return 0; +} + +static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm) +{ + u32 val, new_mode; + adapter_t *adapter = mac->adapter; + u32 addr_lo, addr_hi; + u8 *addr; + + t1_tpi_read(adapter, MACREG(mac, REG_RX_FILTER), &val); + new_mode = val & ~7; + if (!t1_rx_mode_promisc(rm) && mac->instance->version > 0) + new_mode |= 1; /* only set if version > 0 due to erratum */ + if (!t1_rx_mode_promisc(rm) && !t1_rx_mode_allmulti(rm) + && t1_rx_mode_mc_cnt(rm) <= 1) + new_mode |= 2; + if (new_mode != val) + t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), new_mode); + switch (t1_rx_mode_mc_cnt(rm)) { + case 0: + t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), 0); + t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), 0); + break; + case 1: + addr = t1_get_next_mcaddr(rm); + addr_lo = (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | + addr[5]; + addr_hi = (addr[0] << 8) | addr[1]; + t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_LOW), addr_lo); + t1_tpi_write(adapter, MACREG(mac, REG_MC_ADDR_HIGH), addr_hi); + break; + default: + break; + } + return 0; +} + +static int mac_set_mtu(struct cmac *mac, int mtu) +{ + /* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't */ + if (mtu > (MAX_FRAME_SIZE - 14 - 4)) return -EINVAL; + t1_tpi_write(mac->adapter, MACREG(mac, REG_MAX_FRAME_SIZE), + mtu + 14 + 4); + return 0; +} + +static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, + int fc) +{ + u32 val; + + if (speed >= 0 && speed != SPEED_100 && speed != SPEED_1000) + return -1; + if (duplex >= 0 && duplex != DUPLEX_FULL) + return -1; + + if (speed >= 0) { + val = speed == SPEED_100 ? 1 : 2; + t1_tpi_write(mac->adapter, MACREG(mac, REG_RGMII_SPEED), val); + } + + t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val); + val &= ~3; + if (fc & PAUSE_RX) + val |= 1; + if (fc & PAUSE_TX) + val |= 2; + t1_tpi_write(mac->adapter, MACREG(mac, REG_FC_ENABLE), val); + return 0; +} + +static int mac_get_speed_duplex_fc(struct cmac *mac, int *speed, int *duplex, + int *fc) +{ + u32 val; + + if (duplex) + *duplex = DUPLEX_FULL; + if (speed) { + t1_tpi_read(mac->adapter, MACREG(mac, REG_RGMII_SPEED), + &val); + *speed = (val & 2) ? SPEED_1000 : SPEED_100; + } + if (fc) { + t1_tpi_read(mac->adapter, MACREG(mac, REG_FC_ENABLE), &val); + *fc = 0; + if (val & 1) + *fc |= PAUSE_RX; + if (val & 2) + *fc |= PAUSE_TX; + } + return 0; +} + +static void enable_port(struct cmac *mac) +{ + u32 val; + u32 index = mac->instance->index; + adapter_t *adapter = mac->adapter; + + t1_tpi_read(adapter, MACREG(mac, REG_DIVERSE_CONFIG), &val); + val |= DIVERSE_CONFIG_CRC_ADD | DIVERSE_CONFIG_PAD_ENABLE; + t1_tpi_write(adapter, MACREG(mac, REG_DIVERSE_CONFIG), val); + if (mac->instance->version > 0) + t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 3); + else /* Don't enable unicast address filtering due to IXF1010 bug */ + t1_tpi_write(adapter, MACREG(mac, REG_RX_FILTER), 2); + + t1_tpi_read(adapter, REG_RX_ERR_DROP, &val); + val |= (1 << index); + t1_tpi_write(adapter, REG_RX_ERR_DROP, val); + + /* + * Clear the port RMON registers by adding their current values to the + * cumulatice port stats and then clearing the stats. Really. + */ + port_stats_update(mac); + memset(&mac->stats, 0, sizeof(struct cmac_statistics)); + mac->instance->ticks = 0; + + t1_tpi_read(adapter, REG_PORT_ENABLE, &val); + val |= (1 << index); + t1_tpi_write(adapter, REG_PORT_ENABLE, val); + + index <<= 2; + if (is_T2(adapter)) { + /* T204: set the Fifo water level & threshold */ + t1_tpi_write(adapter, RX_FIFO_HIGH_WATERMARK_BASE + index, 0x740); + t1_tpi_write(adapter, RX_FIFO_LOW_WATERMARK_BASE + index, 0x730); + t1_tpi_write(adapter, TX_FIFO_HIGH_WATERMARK_BASE + index, 0x600); + t1_tpi_write(adapter, TX_FIFO_LOW_WATERMARK_BASE + index, 0x1d0); + t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x1100); + } else { + /* + * Set the TX Fifo Threshold to 0x400 instead of 0x100 to work around + * Underrun problem. Intel has blessed this solution. + */ + t1_tpi_write(adapter, TX_FIFO_XFER_THRES_BASE + index, 0x400); + } +} + +/* IXF1010 ports do not have separate enables for TX and RX */ +static int mac_enable(struct cmac *mac, int which) +{ + if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX)) + enable_port(mac); + return 0; +} + +static int mac_disable(struct cmac *mac, int which) +{ + if (which & (MAC_DIRECTION_RX | MAC_DIRECTION_TX)) + disable_port(mac); + return 0; +} + +/* + * This function is called periodically to accumulate the current values of the + * RMON counters into the port statistics. Since the counters are only 32 bits + * some of them can overflow in less than a minute at GigE speeds, so this + * function should be called every 30 seconds or so. + * + * To cut down on reading costs we update only the octet counters at each tick + * and do a full update at major ticks, which can be every 30 minutes or more. + */ +static const struct cmac_statistics *mac_update_statistics(struct cmac *mac, + int flag) +{ + if (flag == MAC_STATS_UPDATE_FULL || + MAJOR_UPDATE_TICKS <= mac->instance->ticks) { + port_stats_update(mac); + mac->instance->ticks = 0; + } else { + u32 val; + + RMON_UPDATE(mac, RxOctetsTotalOK, RxOctetsOK); + RMON_UPDATE(mac, TxOctetsTotalOK, TxOctetsOK); + mac->instance->ticks++; + } + return &mac->stats; +} + +static void mac_destroy(struct cmac *mac) +{ + kfree(mac); +} + +static struct cmac_ops ixf1010_ops = { + .destroy = mac_destroy, + .reset = mac_reset, + .interrupt_enable = mac_intr_op, + .interrupt_disable = mac_intr_op, + .interrupt_clear = mac_intr_op, + .enable = mac_enable, + .disable = mac_disable, + .set_mtu = mac_set_mtu, + .set_rx_mode = mac_set_rx_mode, + .set_speed_duplex_fc = mac_set_speed_duplex_fc, + .get_speed_duplex_fc = mac_get_speed_duplex_fc, + .statistics_update = mac_update_statistics, + .macaddress_get = mac_get_address, + .macaddress_set = mac_set_address, +}; + +static int ixf1010_mac_reset(adapter_t *adapter) +{ + u32 val; + + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + if ((val & 1) != 0) { + val &= ~1; + t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(2); + } + val |= 1; + t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(2); + + t1_tpi_write(adapter, REG_PORT_ENABLE, 0); + return 0; +} + +static struct cmac *ixf1010_mac_create(adapter_t *adapter, int index) +{ + struct cmac *mac; + u32 val; + + if (index > 9) return NULL; + + mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL); + if (!mac) return NULL; + + mac->ops = &ixf1010_ops; + mac->instance = (cmac_instance *)(mac + 1); + + mac->instance->mac_base = MACREG_BASE + (index * 0x200); + mac->instance->index = index; + mac->adapter = adapter; + mac->instance->ticks = 0; + + t1_tpi_read(adapter, REG_JTAG_ID, &val); + mac->instance->version = val >> 28; + return mac; +} + +struct gmac t1_ixf1010_ops = { + STATS_TICK_SECS, + ixf1010_mac_create, + ixf1010_mac_reset +}; diff --git a/drivers/net/chelsio/mac.c b/drivers/net/chelsio/mac.c new file mode 100644 index 000000000000..6af39dc70459 --- /dev/null +++ b/drivers/net/chelsio/mac.c @@ -0,0 +1,368 @@ +/* $Date: 2005/10/22 00:42:59 $ $RCSfile: mac.c,v $ $Revision: 1.32 $ */ +#include "gmac.h" +#include "regs.h" +#include "fpga_defs.h" + +#define MAC_CSR_INTERFACE_GMII 0x0 +#define MAC_CSR_INTERFACE_TBI 0x1 +#define MAC_CSR_INTERFACE_MII 0x2 +#define MAC_CSR_INTERFACE_RMII 0x3 + +/* Chelsio's MAC statistics. */ +struct mac_statistics { + + /* Transmit */ + u32 TxFramesTransmittedOK; + u32 TxReserved1; + u32 TxReserved2; + u32 TxOctetsTransmittedOK; + u32 TxFramesWithDeferredXmissions; + u32 TxLateCollisions; + u32 TxFramesAbortedDueToXSCollisions; + u32 TxFramesLostDueToIntMACXmitError; + u32 TxReserved3; + u32 TxMulticastFrameXmittedOK; + u32 TxBroadcastFramesXmittedOK; + u32 TxFramesWithExcessiveDeferral; + u32 TxPAUSEMACCtrlFramesTransmitted; + + /* Receive */ + u32 RxFramesReceivedOK; + u32 RxFrameCheckSequenceErrors; + u32 RxAlignmentErrors; + u32 RxOctetsReceivedOK; + u32 RxFramesLostDueToIntMACRcvError; + u32 RxMulticastFramesReceivedOK; + u32 RxBroadcastFramesReceivedOK; + u32 RxInRangeLengthErrors; + u32 RxTxOutOfRangeLengthField; + u32 RxFrameTooLongErrors; + u32 RxPAUSEMACCtrlFramesReceived; +}; + +static int static_aPorts[] = { + FPGA_GMAC_INTERRUPT_PORT0, + FPGA_GMAC_INTERRUPT_PORT1, + FPGA_GMAC_INTERRUPT_PORT2, + FPGA_GMAC_INTERRUPT_PORT3 +}; + +struct _cmac_instance { + u32 index; +}; + +static int mac_intr_enable(struct cmac *mac) +{ + u32 mac_intr; + + if (t1_is_asic(mac->adapter)) { + /* ASIC */ + + /* We don't use the on chip MAC for ASIC products. */ + } else { + /* FPGA */ + + /* Set parent gmac interrupt. */ + mac_intr = readl(mac->adapter->regs + A_PL_ENABLE); + mac_intr |= FPGA_PCIX_INTERRUPT_GMAC; + writel(mac_intr, mac->adapter->regs + A_PL_ENABLE); + + mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE); + mac_intr |= static_aPorts[mac->instance->index]; + writel(mac_intr, + mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE); + } + + return 0; +} + +static int mac_intr_disable(struct cmac *mac) +{ + u32 mac_intr; + + if (t1_is_asic(mac->adapter)) { + /* ASIC */ + + /* We don't use the on chip MAC for ASIC products. */ + } else { + /* FPGA */ + + /* Set parent gmac interrupt. */ + mac_intr = readl(mac->adapter->regs + A_PL_ENABLE); + mac_intr &= ~FPGA_PCIX_INTERRUPT_GMAC; + writel(mac_intr, mac->adapter->regs + A_PL_ENABLE); + + mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE); + mac_intr &= ~(static_aPorts[mac->instance->index]); + writel(mac_intr, + mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_ENABLE); + } + + return 0; +} + +static int mac_intr_clear(struct cmac *mac) +{ + u32 mac_intr; + + if (t1_is_asic(mac->adapter)) { + /* ASIC */ + + /* We don't use the on chip MAC for ASIC products. */ + } else { + /* FPGA */ + + /* Set parent gmac interrupt. */ + writel(FPGA_PCIX_INTERRUPT_GMAC, + mac->adapter->regs + A_PL_CAUSE); + mac_intr = readl(mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); + mac_intr |= (static_aPorts[mac->instance->index]); + writel(mac_intr, + mac->adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); + } + + return 0; +} + +static int mac_get_address(struct cmac *mac, u8 addr[6]) +{ + u32 data32_lo, data32_hi; + + data32_lo = readl(mac->adapter->regs + + MAC_REG_IDLO(mac->instance->index)); + data32_hi = readl(mac->adapter->regs + + MAC_REG_IDHI(mac->instance->index)); + + addr[0] = (u8) ((data32_hi >> 8) & 0xFF); + addr[1] = (u8) ((data32_hi) & 0xFF); + addr[2] = (u8) ((data32_lo >> 24) & 0xFF); + addr[3] = (u8) ((data32_lo >> 16) & 0xFF); + addr[4] = (u8) ((data32_lo >> 8) & 0xFF); + addr[5] = (u8) ((data32_lo) & 0xFF); + return 0; +} + +static int mac_reset(struct cmac *mac) +{ + u32 data32; + int mac_in_reset, time_out = 100; + int idx = mac->instance->index; + + data32 = readl(mac->adapter->regs + MAC_REG_CSR(idx)); + writel(data32 | F_MAC_RESET, + mac->adapter->regs + MAC_REG_CSR(idx)); + + do { + data32 = readl(mac->adapter->regs + MAC_REG_CSR(idx)); + + mac_in_reset = data32 & F_MAC_RESET; + if (mac_in_reset) + udelay(1); + } while (mac_in_reset && --time_out); + + if (mac_in_reset) { + CH_ERR("%s: MAC %d reset timed out\n", + mac->adapter->name, idx); + return 2; + } + + return 0; +} + +static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm) +{ + u32 val; + + val = readl(mac->adapter->regs + + MAC_REG_CSR(mac->instance->index)); + val &= ~(F_MAC_PROMISC | F_MAC_MC_ENABLE); + val |= V_MAC_PROMISC(t1_rx_mode_promisc(rm) != 0); + val |= V_MAC_MC_ENABLE(t1_rx_mode_allmulti(rm) != 0); + writel(val, + mac->adapter->regs + MAC_REG_CSR(mac->instance->index)); + + return 0; +} + +static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, + int fc) +{ + u32 data32; + + data32 = readl(mac->adapter->regs + + MAC_REG_CSR(mac->instance->index)); + data32 &= ~(F_MAC_HALF_DUPLEX | V_MAC_SPEED(M_MAC_SPEED) | + V_INTERFACE(M_INTERFACE) | F_MAC_TX_PAUSE_ENABLE | + F_MAC_RX_PAUSE_ENABLE); + + switch (speed) { + case SPEED_10: + case SPEED_100: + data32 |= V_INTERFACE(MAC_CSR_INTERFACE_MII); + data32 |= V_MAC_SPEED(speed == SPEED_10 ? 0 : 1); + break; + case SPEED_1000: + data32 |= V_INTERFACE(MAC_CSR_INTERFACE_GMII); + data32 |= V_MAC_SPEED(2); + break; + } + + if (duplex >= 0) + data32 |= V_MAC_HALF_DUPLEX(duplex == DUPLEX_HALF); + + if (fc >= 0) { + data32 |= V_MAC_RX_PAUSE_ENABLE((fc & PAUSE_RX) != 0); + data32 |= V_MAC_TX_PAUSE_ENABLE((fc & PAUSE_TX) != 0); + } + + writel(data32, + mac->adapter->regs + MAC_REG_CSR(mac->instance->index)); + return 0; +} + +static int mac_enable(struct cmac *mac, int which) +{ + u32 val; + + val = readl(mac->adapter->regs + + MAC_REG_CSR(mac->instance->index)); + if (which & MAC_DIRECTION_RX) + val |= F_MAC_RX_ENABLE; + if (which & MAC_DIRECTION_TX) + val |= F_MAC_TX_ENABLE; + writel(val, + mac->adapter->regs + MAC_REG_CSR(mac->instance->index)); + return 0; +} + +static int mac_disable(struct cmac *mac, int which) +{ + u32 val; + + val = readl(mac->adapter->regs + + MAC_REG_CSR(mac->instance->index)); + if (which & MAC_DIRECTION_RX) + val &= ~F_MAC_RX_ENABLE; + if (which & MAC_DIRECTION_TX) + val &= ~F_MAC_TX_ENABLE; + writel(val, + mac->adapter->regs + MAC_REG_CSR(mac->instance->index)); + return 0; +} + +#if 0 +static int mac_set_ifs(struct cmac *mac, u32 mode) +{ + t1_write_reg_4(mac->adapter, + MAC_REG_IFS(mac->instance->index), + mode); + return 0; +} + +static int mac_enable_isl(struct cmac *mac) +{ + u32 data32 = readl(mac->adapter->regs + + MAC_REG_CSR(mac->instance->index)); + data32 |= F_MAC_RX_ENABLE | F_MAC_TX_ENABLE; + t1_write_reg_4(mac->adapter, + MAC_REG_CSR(mac->instance->index), + data32); + return 0; +} +#endif + +static int mac_set_mtu(struct cmac *mac, int mtu) +{ + if (mtu > 9600) + return -EINVAL; + writel(mtu + ETH_HLEN + VLAN_HLEN, + mac->adapter->regs + MAC_REG_LARGEFRAMELENGTH(mac->instance->index)); + + return 0; +} + +static const struct cmac_statistics *mac_update_statistics(struct cmac *mac, + int flag) +{ + struct mac_statistics st; + u32 *p = (u32 *) & st, i; + + writel(0, + mac->adapter->regs + MAC_REG_RMCNT(mac->instance->index)); + + for (i = 0; i < sizeof(st) / sizeof(u32); i++) + *p++ = readl(mac->adapter->regs + + MAC_REG_RMDATA(mac->instance->index)); + + /* XXX convert stats */ + return &mac->stats; +} + +static void mac_destroy(struct cmac *mac) +{ + kfree(mac); +} + +static struct cmac_ops chelsio_mac_ops = { + .destroy = mac_destroy, + .reset = mac_reset, + .interrupt_enable = mac_intr_enable, + .interrupt_disable = mac_intr_disable, + .interrupt_clear = mac_intr_clear, + .enable = mac_enable, + .disable = mac_disable, + .set_mtu = mac_set_mtu, + .set_rx_mode = mac_set_rx_mode, + .set_speed_duplex_fc = mac_set_speed_duplex_fc, + .macaddress_get = mac_get_address, + .statistics_update = mac_update_statistics, +}; + +static struct cmac *mac_create(adapter_t *adapter, int index) +{ + struct cmac *mac; + u32 data32; + + if (index >= 4) + return NULL; + + mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL); + if (!mac) + return NULL; + + mac->ops = &chelsio_mac_ops; + mac->instance = (cmac_instance *) (mac + 1); + + mac->instance->index = index; + mac->adapter = adapter; + + data32 = readl(adapter->regs + MAC_REG_CSR(mac->instance->index)); + data32 &= ~(F_MAC_RESET | F_MAC_PROMISC | F_MAC_PROMISC | + F_MAC_LB_ENABLE | F_MAC_RX_ENABLE | F_MAC_TX_ENABLE); + data32 |= F_MAC_JUMBO_ENABLE; + writel(data32, adapter->regs + MAC_REG_CSR(mac->instance->index)); + + /* Initialize the random backoff seed. */ + data32 = 0x55aa + (3 * index); + writel(data32, + adapter->regs + MAC_REG_GMRANDBACKOFFSEED(mac->instance->index)); + + /* Check to see if the mac address needs to be set manually. */ + data32 = readl(adapter->regs + MAC_REG_IDLO(mac->instance->index)); + if (data32 == 0 || data32 == 0xffffffff) { + /* + * Add a default MAC address if we can't read one. + */ + writel(0x43FFFFFF - index, + adapter->regs + MAC_REG_IDLO(mac->instance->index)); + writel(0x0007, + adapter->regs + MAC_REG_IDHI(mac->instance->index)); + } + + (void) mac_set_mtu(mac, 1500); + return mac; +} + +struct gmac t1_chelsio_mac_ops = { + .create = mac_create +}; diff --git a/drivers/net/chelsio/mv88e1xxx.c b/drivers/net/chelsio/mv88e1xxx.c new file mode 100644 index 000000000000..28ac93ff7c4f --- /dev/null +++ b/drivers/net/chelsio/mv88e1xxx.c @@ -0,0 +1,397 @@ +/* $Date: 2005/10/24 23:18:13 $ $RCSfile: mv88e1xxx.c,v $ $Revision: 1.49 $ */ +#include "common.h" +#include "mv88e1xxx.h" +#include "cphy.h" +#include "elmer0.h" + +/* MV88E1XXX MDI crossover register values */ +#define CROSSOVER_MDI 0 +#define CROSSOVER_MDIX 1 +#define CROSSOVER_AUTO 3 + +#define INTR_ENABLE_MASK 0x6CA0 + +/* + * Set the bits given by 'bitval' in PHY register 'reg'. + */ +static void mdio_set_bit(struct cphy *cphy, int reg, u32 bitval) +{ + u32 val; + + (void) simple_mdio_read(cphy, reg, &val); + (void) simple_mdio_write(cphy, reg, val | bitval); +} + +/* + * Clear the bits given by 'bitval' in PHY register 'reg'. + */ +static void mdio_clear_bit(struct cphy *cphy, int reg, u32 bitval) +{ + u32 val; + + (void) simple_mdio_read(cphy, reg, &val); + (void) simple_mdio_write(cphy, reg, val & ~bitval); +} + +/* + * NAME: phy_reset + * + * DESC: Reset the given PHY's port. NOTE: This is not a global + * chip reset. + * + * PARAMS: cphy - Pointer to PHY instance data. + * + * RETURN: 0 - Successfull reset. + * -1 - Timeout. + */ +static int mv88e1xxx_reset(struct cphy *cphy, int wait) +{ + u32 ctl; + int time_out = 1000; + + mdio_set_bit(cphy, MII_BMCR, BMCR_RESET); + + do { + (void) simple_mdio_read(cphy, MII_BMCR, &ctl); + ctl &= BMCR_RESET; + if (ctl) + udelay(1); + } while (ctl && --time_out); + + return ctl ? -1 : 0; +} + +static int mv88e1xxx_interrupt_enable(struct cphy *cphy) +{ + /* Enable PHY interrupts. */ + (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, + INTR_ENABLE_MASK); + + /* Enable Marvell interrupts through Elmer0. */ + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer |= ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } + return 0; +} + +static int mv88e1xxx_interrupt_disable(struct cphy *cphy) +{ + /* Disable all phy interrupts. */ + (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, 0); + + /* Disable Marvell interrupts through Elmer0. */ + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer &= ~ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4); + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } + return 0; +} + +static int mv88e1xxx_interrupt_clear(struct cphy *cphy) +{ + u32 elmer; + + /* Clear PHY interrupts by reading the register. */ + (void) simple_mdio_read(cphy, + MV88E1XXX_INTERRUPT_STATUS_REGISTER, &elmer); + + /* Clear Marvell interrupts through Elmer0. */ + if (t1_is_asic(cphy->adapter)) { + t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); + elmer |= ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); + } + return 0; +} + +/* + * Set the PHY speed and duplex. This also disables auto-negotiation, except + * for 1Gb/s, where auto-negotiation is mandatory. + */ +static int mv88e1xxx_set_speed_duplex(struct cphy *phy, int speed, int duplex) +{ + u32 ctl; + + (void) simple_mdio_read(phy, MII_BMCR, &ctl); + if (speed >= 0) { + ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); + if (speed == SPEED_100) + ctl |= BMCR_SPEED100; + else if (speed == SPEED_1000) + ctl |= BMCR_SPEED1000; + } + if (duplex >= 0) { + ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE); + if (duplex == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + } + if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */ + ctl |= BMCR_ANENABLE; + (void) simple_mdio_write(phy, MII_BMCR, ctl); + return 0; +} + +static int mv88e1xxx_crossover_set(struct cphy *cphy, int crossover) +{ + u32 data32; + + (void) simple_mdio_read(cphy, + MV88E1XXX_SPECIFIC_CNTRL_REGISTER, &data32); + data32 &= ~V_PSCR_MDI_XOVER_MODE(M_PSCR_MDI_XOVER_MODE); + data32 |= V_PSCR_MDI_XOVER_MODE(crossover); + (void) simple_mdio_write(cphy, + MV88E1XXX_SPECIFIC_CNTRL_REGISTER, data32); + return 0; +} + +static int mv88e1xxx_autoneg_enable(struct cphy *cphy) +{ + u32 ctl; + + (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_AUTO); + + (void) simple_mdio_read(cphy, MII_BMCR, &ctl); + /* restart autoneg for change to take effect */ + ctl |= BMCR_ANENABLE | BMCR_ANRESTART; + (void) simple_mdio_write(cphy, MII_BMCR, ctl); + return 0; +} + +static int mv88e1xxx_autoneg_disable(struct cphy *cphy) +{ + u32 ctl; + + /* + * Crossover *must* be set to manual in order to disable auto-neg. + * The Alaska FAQs document highlights this point. + */ + (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_MDI); + + /* + * Must include autoneg reset when disabling auto-neg. This + * is described in the Alaska FAQ document. + */ + (void) simple_mdio_read(cphy, MII_BMCR, &ctl); + ctl &= ~BMCR_ANENABLE; + (void) simple_mdio_write(cphy, MII_BMCR, ctl | BMCR_ANRESTART); + return 0; +} + +static int mv88e1xxx_autoneg_restart(struct cphy *cphy) +{ + mdio_set_bit(cphy, MII_BMCR, BMCR_ANRESTART); + return 0; +} + +static int mv88e1xxx_advertise(struct cphy *phy, unsigned int advertise_map) +{ + u32 val = 0; + + if (advertise_map & + (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { + (void) simple_mdio_read(phy, MII_GBCR, &val); + val &= ~(GBCR_ADV_1000HALF | GBCR_ADV_1000FULL); + if (advertise_map & ADVERTISED_1000baseT_Half) + val |= GBCR_ADV_1000HALF; + if (advertise_map & ADVERTISED_1000baseT_Full) + val |= GBCR_ADV_1000FULL; + } + (void) simple_mdio_write(phy, MII_GBCR, val); + + val = 1; + if (advertise_map & ADVERTISED_10baseT_Half) + val |= ADVERTISE_10HALF; + if (advertise_map & ADVERTISED_10baseT_Full) + val |= ADVERTISE_10FULL; + if (advertise_map & ADVERTISED_100baseT_Half) + val |= ADVERTISE_100HALF; + if (advertise_map & ADVERTISED_100baseT_Full) + val |= ADVERTISE_100FULL; + if (advertise_map & ADVERTISED_PAUSE) + val |= ADVERTISE_PAUSE; + if (advertise_map & ADVERTISED_ASYM_PAUSE) + val |= ADVERTISE_PAUSE_ASYM; + (void) simple_mdio_write(phy, MII_ADVERTISE, val); + return 0; +} + +static int mv88e1xxx_set_loopback(struct cphy *cphy, int on) +{ + if (on) + mdio_set_bit(cphy, MII_BMCR, BMCR_LOOPBACK); + else + mdio_clear_bit(cphy, MII_BMCR, BMCR_LOOPBACK); + return 0; +} + +static int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok, + int *speed, int *duplex, int *fc) +{ + u32 status; + int sp = -1, dplx = -1, pause = 0; + + (void) simple_mdio_read(cphy, + MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status); + if ((status & V_PSSR_STATUS_RESOLVED) != 0) { + if (status & V_PSSR_RX_PAUSE) + pause |= PAUSE_RX; + if (status & V_PSSR_TX_PAUSE) + pause |= PAUSE_TX; + dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; + sp = G_PSSR_SPEED(status); + if (sp == 0) + sp = SPEED_10; + else if (sp == 1) + sp = SPEED_100; + else + sp = SPEED_1000; + } + if (link_ok) + *link_ok = (status & V_PSSR_LINK) != 0; + if (speed) + *speed = sp; + if (duplex) + *duplex = dplx; + if (fc) + *fc = pause; + return 0; +} + +static int mv88e1xxx_downshift_set(struct cphy *cphy, int downshift_enable) +{ + u32 val; + + (void) simple_mdio_read(cphy, + MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, &val); + + /* + * Set the downshift counter to 2 so we try to establish Gb link + * twice before downshifting. + */ + val &= ~(V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(M_DOWNSHIFT_CNT)); + + if (downshift_enable) + val |= V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(2); + (void) simple_mdio_write(cphy, + MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, val); + return 0; +} + +static int mv88e1xxx_interrupt_handler(struct cphy *cphy) +{ + int cphy_cause = 0; + u32 status; + + /* + * Loop until cause reads zero. Need to handle bouncing interrupts. + */ + while (1) { + u32 cause; + + (void) simple_mdio_read(cphy, + MV88E1XXX_INTERRUPT_STATUS_REGISTER, + &cause); + cause &= INTR_ENABLE_MASK; + if (!cause) break; + + if (cause & MV88E1XXX_INTR_LINK_CHNG) { + (void) simple_mdio_read(cphy, + MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status); + + if (status & MV88E1XXX_INTR_LINK_CHNG) { + cphy->state |= PHY_LINK_UP; + } else { + cphy->state &= ~PHY_LINK_UP; + if (cphy->state & PHY_AUTONEG_EN) + cphy->state &= ~PHY_AUTONEG_RDY; + cphy_cause |= cphy_cause_link_change; + } + } + + if (cause & MV88E1XXX_INTR_AUTONEG_DONE) + cphy->state |= PHY_AUTONEG_RDY; + + if ((cphy->state & (PHY_LINK_UP | PHY_AUTONEG_RDY)) == + (PHY_LINK_UP | PHY_AUTONEG_RDY)) + cphy_cause |= cphy_cause_link_change; + } + return cphy_cause; +} + +static void mv88e1xxx_destroy(struct cphy *cphy) +{ + kfree(cphy); +} + +static struct cphy_ops mv88e1xxx_ops = { + .destroy = mv88e1xxx_destroy, + .reset = mv88e1xxx_reset, + .interrupt_enable = mv88e1xxx_interrupt_enable, + .interrupt_disable = mv88e1xxx_interrupt_disable, + .interrupt_clear = mv88e1xxx_interrupt_clear, + .interrupt_handler = mv88e1xxx_interrupt_handler, + .autoneg_enable = mv88e1xxx_autoneg_enable, + .autoneg_disable = mv88e1xxx_autoneg_disable, + .autoneg_restart = mv88e1xxx_autoneg_restart, + .advertise = mv88e1xxx_advertise, + .set_loopback = mv88e1xxx_set_loopback, + .set_speed_duplex = mv88e1xxx_set_speed_duplex, + .get_link_status = mv88e1xxx_get_link_status, +}; + +static struct cphy *mv88e1xxx_phy_create(adapter_t *adapter, int phy_addr, + struct mdio_ops *mdio_ops) +{ + struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); + + if (!cphy) return NULL; + + cphy_init(cphy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops); + + /* Configure particular PHY's to run in a different mode. */ + if ((board_info(adapter)->caps & SUPPORTED_TP) && + board_info(adapter)->chip_phy == CHBT_PHY_88E1111) { + /* + * Configure the PHY transmitter as class A to reduce EMI. + */ + (void) simple_mdio_write(cphy, + MV88E1XXX_EXTENDED_ADDR_REGISTER, 0xB); + (void) simple_mdio_write(cphy, + MV88E1XXX_EXTENDED_REGISTER, 0x8004); + } + (void) mv88e1xxx_downshift_set(cphy, 1); /* Enable downshift */ + + /* LED */ + if (is_T2(adapter)) { + (void) simple_mdio_write(cphy, + MV88E1XXX_LED_CONTROL_REGISTER, 0x1); + } + + return cphy; +} + +static int mv88e1xxx_phy_reset(adapter_t* adapter) +{ + return 0; +} + +struct gphy t1_mv88e1xxx_ops = { + mv88e1xxx_phy_create, + mv88e1xxx_phy_reset +}; diff --git a/drivers/net/chelsio/subr.c b/drivers/net/chelsio/subr.c index d41d15a71e4d..22ed9a383c08 100644 --- a/drivers/net/chelsio/subr.c +++ b/drivers/net/chelsio/subr.c @@ -185,6 +185,66 @@ static int t1_pci_intr_handler(adapter_t *adapter) return 0; } +#ifdef CONFIG_CHELSIO_T1_COUGAR +#include "cspi.h" +#endif +#ifdef CONFIG_CHELSIO_T1_1G +#include "fpga_defs.h" + +/* + * PHY interrupt handler for FPGA boards. + */ +static int fpga_phy_intr_handler(adapter_t *adapter) +{ + int p; + u32 cause = readl(adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); + + for_each_port(adapter, p) + if (cause & (1 << p)) { + struct cphy *phy = adapter->port[p].phy; + int phy_cause = phy->ops->interrupt_handler(phy); + + if (phy_cause & cphy_cause_link_change) + t1_link_changed(adapter, p); + } + writel(cause, adapter->regs + FPGA_GMAC_ADDR_INTERRUPT_CAUSE); + return 0; +} + +/* + * Slow path interrupt handler for FPGAs. + */ +static int fpga_slow_intr(adapter_t *adapter) +{ + u32 cause = readl(adapter->regs + A_PL_CAUSE); + + cause &= ~F_PL_INTR_SGE_DATA; + if (cause & F_PL_INTR_SGE_ERR) + t1_sge_intr_error_handler(adapter->sge); + + if (cause & FPGA_PCIX_INTERRUPT_GMAC) + fpga_phy_intr_handler(adapter); + + if (cause & FPGA_PCIX_INTERRUPT_TP) { + /* + * FPGA doesn't support MC4 interrupts and it requires + * this odd layer of indirection for MC5. + */ + u32 tp_cause = readl(adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); + + /* Clear TP interrupt */ + writel(tp_cause, adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); + } + if (cause & FPGA_PCIX_INTERRUPT_PCIX) + t1_pci_intr_handler(adapter); + + /* Clear the interrupts just processed. */ + if (cause) + writel(cause, adapter->regs + A_PL_CAUSE); + + return cause != 0; +} +#endif /* * Wait until Elmer's MI1 interface is ready for new operations. @@ -221,6 +281,56 @@ static void mi1_mdio_init(adapter_t *adapter, const struct board_info *bi) t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_CFG, val); } +#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) +/* + * Elmer MI1 MDIO read/write operations. + */ +static int mi1_mdio_read(adapter_t *adapter, int phy_addr, int mmd_addr, + int reg_addr, unsigned int *valp) +{ + u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); + + if (mmd_addr) + return -EINVAL; + + spin_lock(&adapter->tpi_lock); + __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); + __t1_tpi_write(adapter, + A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_READ); + mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); + __t1_tpi_read(adapter, A_ELMER0_PORT0_MI1_DATA, valp); + spin_unlock(&adapter->tpi_lock); + return 0; +} + +static int mi1_mdio_write(adapter_t *adapter, int phy_addr, int mmd_addr, + int reg_addr, unsigned int val) +{ + u32 addr = V_MI1_REG_ADDR(reg_addr) | V_MI1_PHY_ADDR(phy_addr); + + if (mmd_addr) + return -EINVAL; + + spin_lock(&adapter->tpi_lock); + __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_ADDR, addr); + __t1_tpi_write(adapter, A_ELMER0_PORT0_MI1_DATA, val); + __t1_tpi_write(adapter, + A_ELMER0_PORT0_MI1_OP, MI1_OP_DIRECT_WRITE); + mi1_wait_until_ready(adapter, A_ELMER0_PORT0_MI1_OP); + spin_unlock(&adapter->tpi_lock); + return 0; +} + +#if defined(CONFIG_CHELSIO_T1_1G) || defined(CONFIG_CHELSIO_T1_COUGAR) +static struct mdio_ops mi1_mdio_ops = { + mi1_mdio_init, + mi1_mdio_read, + mi1_mdio_write +}; +#endif + +#endif + static int mi1_mdio_ext_read(adapter_t *adapter, int phy_addr, int mmd_addr, int reg_addr, unsigned int *valp) { @@ -330,6 +440,17 @@ static struct board_info t1_board[] = { &t1_my3126_ops, &mi1_mdio_ext_ops, "Chelsio T210 1x10GBase-CX4 TOE" }, +#ifdef CONFIG_CHELSIO_T1_1G +{ CHBT_BOARD_CHN204, 4/*ports#*/, + SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | + SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | + SUPPORTED_PAUSE | SUPPORTED_TP /*caps*/, CHBT_TERM_T2, CHBT_MAC_VSC7321, CHBT_PHY_88E1111, + 100000000/*clk-core*/, 0/*clk-mc3*/, 0/*clk-mc4*/, + 4/*espi-ports*/, 0/*clk-cspi*/, 44/*clk-elmer0*/, 0/*mdien*/, + 0/*mdiinv*/, 1/*mdc*/, 4/*phybaseaddr*/, &t1_vsc7326_ops, + &t1_mv88e1xxx_ops, &mi1_mdio_ops, + "Chelsio N204 4x100/1000BaseT NIC" }, +#endif }; @@ -483,6 +604,48 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) t1_tpi_read(adapter, A_ELMER0_INT_CAUSE, &cause); switch (board_info(adapter)->board) { +#ifdef CONFIG_CHELSIO_T1_1G + case CHBT_BOARD_CHT204: + case CHBT_BOARD_CHT204E: + case CHBT_BOARD_CHN204: + case CHBT_BOARD_CHT204V: { + int i, port_bit; + for_each_port(adapter, i) { + port_bit = i + 1; + if (!(cause & (1 << port_bit))) continue; + + phy = adapter->port[i].phy; + phy_cause = phy->ops->interrupt_handler(phy); + if (phy_cause & cphy_cause_link_change) + t1_link_changed(adapter, i); + } + break; + } + case CHBT_BOARD_CHT101: + if (cause & ELMER0_GP_BIT1) { /* Marvell 88E1111 interrupt */ + phy = adapter->port[0].phy; + phy_cause = phy->ops->interrupt_handler(phy); + if (phy_cause & cphy_cause_link_change) + t1_link_changed(adapter, 0); + } + break; + case CHBT_BOARD_7500: { + int p; + /* + * Elmer0's interrupt cause isn't useful here because there is + * only one bit that can be set for all 4 ports. This means + * we are forced to check every PHY's interrupt status + * register to see who initiated the interrupt. + */ + for_each_port(adapter, p) { + phy = adapter->port[p].phy; + phy_cause = phy->ops->interrupt_handler(phy); + if (phy_cause & cphy_cause_link_change) + t1_link_changed(adapter, p); + } + break; + } +#endif case CHBT_BOARD_CHT210: case CHBT_BOARD_N210: case CHBT_BOARD_N110: @@ -511,6 +674,30 @@ int t1_elmer0_ext_intr_handler(adapter_t *adapter) mod_detect ? "removed" : "inserted"); } break; +#ifdef CONFIG_CHELSIO_T1_COUGAR + case CHBT_BOARD_COUGAR: + if (adapter->params.nports == 1) { + if (cause & ELMER0_GP_BIT1) { /* Vitesse MAC */ + struct cmac *mac = adapter->port[0].mac; + mac->ops->interrupt_handler(mac); + } + if (cause & ELMER0_GP_BIT5) { /* XPAK MOD_DETECT */ + } + } else { + int i, port_bit; + + for_each_port(adapter, i) { + port_bit = i ? i + 1 : 0; + if (!(cause & (1 << port_bit))) continue; + + phy = adapter->port[i].phy; + phy_cause = phy->ops->interrupt_handler(phy); + if (phy_cause & cphy_cause_link_change) + t1_link_changed(adapter, i); + } + } + break; +#endif } t1_tpi_write(adapter, A_ELMER0_INT_CAUSE, cause); return 0; @@ -633,6 +820,10 @@ static int asic_slow_intr(adapter_t *adapter) int t1_slow_intr_handler(adapter_t *adapter) { +#ifdef CONFIG_CHELSIO_T1_1G + if (!t1_is_asic(adapter)) + return fpga_slow_intr(adapter); +#endif return asic_slow_intr(adapter); } @@ -698,6 +889,21 @@ static int board_init(adapter_t *adapter, const struct board_info *bi) */ power_sequence_xpak(adapter); break; +#ifdef CONFIG_CHELSIO_T1_1G + case CHBT_BOARD_CHT204E: + /* add config space write here */ + case CHBT_BOARD_CHT204: + case CHBT_BOARD_CHT204V: + case CHBT_BOARD_CHN204: + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x804); + break; + case CHBT_BOARD_CHT101: + case CHBT_BOARD_7500: + t1_tpi_par(adapter, 0xf); + t1_tpi_write(adapter, A_ELMER0_GPO, 0x1804); + break; +#endif } return 0; } @@ -719,6 +925,10 @@ int t1_init_hw_modules(adapter_t *adapter) adapter->regs + A_MC5_CONFIG); } +#ifdef CONFIG_CHELSIO_T1_COUGAR + if (adapter->cspi && t1_cspi_init(adapter->cspi)) + goto out_err; +#endif if (adapter->espi && t1_espi_init(adapter->espi, bi->chip_mac, bi->espi_nports)) goto out_err; @@ -772,6 +982,10 @@ void t1_free_sw_modules(adapter_t *adapter) t1_tp_destroy(adapter->tp); if (adapter->espi) t1_espi_destroy(adapter->espi); +#ifdef CONFIG_CHELSIO_T1_COUGAR + if (adapter->cspi) + t1_cspi_destroy(adapter->cspi); +#endif } static void __devinit init_link_config(struct link_config *lc, @@ -791,6 +1005,13 @@ static void __devinit init_link_config(struct link_config *lc, } } +#ifdef CONFIG_CHELSIO_T1_COUGAR + if (bi->clock_cspi && !(adapter->cspi = t1_cspi_create(adapter))) { + CH_ERR("%s: CSPI initialization failed\n", + adapter->name); + goto error; + } +#endif /* * Allocate and initialize the data structures that hold the SW state of diff --git a/drivers/net/chelsio/tp.c b/drivers/net/chelsio/tp.c index 04a7073e9d15..0ca0b6e19e43 100644 --- a/drivers/net/chelsio/tp.c +++ b/drivers/net/chelsio/tp.c @@ -2,6 +2,9 @@ #include "common.h" #include "regs.h" #include "tp.h" +#ifdef CONFIG_CHELSIO_T1_1G +#include "fpga_defs.h" +#endif struct petp { adapter_t *adapter; @@ -70,6 +73,15 @@ void t1_tp_intr_enable(struct petp *tp) { u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); +#ifdef CONFIG_CHELSIO_T1_1G + if (!t1_is_asic(tp->adapter)) { + /* FPGA */ + writel(0xffffffff, + tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); + writel(tp_intr | FPGA_PCIX_INTERRUPT_TP, + tp->adapter->regs + A_PL_ENABLE); + } else +#endif { /* We don't use any TP interrupts */ writel(0, tp->adapter->regs + A_TP_INT_ENABLE); @@ -82,6 +94,14 @@ void t1_tp_intr_disable(struct petp *tp) { u32 tp_intr = readl(tp->adapter->regs + A_PL_ENABLE); +#ifdef CONFIG_CHELSIO_T1_1G + if (!t1_is_asic(tp->adapter)) { + /* FPGA */ + writel(0, tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_ENABLE); + writel(tp_intr & ~FPGA_PCIX_INTERRUPT_TP, + tp->adapter->regs + A_PL_ENABLE); + } else +#endif { writel(0, tp->adapter->regs + A_TP_INT_ENABLE); writel(tp_intr & ~F_PL_INTR_TP, @@ -91,6 +111,14 @@ void t1_tp_intr_disable(struct petp *tp) void t1_tp_intr_clear(struct petp *tp) { +#ifdef CONFIG_CHELSIO_T1_1G + if (!t1_is_asic(tp->adapter)) { + writel(0xffffffff, + tp->adapter->regs + FPGA_TP_ADDR_INTERRUPT_CAUSE); + writel(FPGA_PCIX_INTERRUPT_TP, tp->adapter->regs + A_PL_CAUSE); + return; + } +#endif writel(0xffffffff, tp->adapter->regs + A_TP_INT_CAUSE); writel(F_PL_INTR_TP, tp->adapter->regs + A_PL_CAUSE); } @@ -99,6 +127,11 @@ int t1_tp_intr_handler(struct petp *tp) { u32 cause; +#ifdef CONFIG_CHELSIO_T1_1G + /* FPGA doesn't support TP interrupts. */ + if (!t1_is_asic(tp->adapter)) + return 1; +#endif cause = readl(tp->adapter->regs + A_TP_INT_CAUSE); writel(cause, tp->adapter->regs + A_TP_INT_CAUSE); diff --git a/drivers/net/chelsio/vsc7326.c b/drivers/net/chelsio/vsc7326.c new file mode 100644 index 000000000000..85dc3b1dc309 --- /dev/null +++ b/drivers/net/chelsio/vsc7326.c @@ -0,0 +1,725 @@ +/* $Date: 2006/04/28 19:20:06 $ $RCSfile: vsc7326.c,v $ $Revision: 1.19 $ */ + +/* Driver for Vitesse VSC7326 (Schaumburg) MAC */ + +#include "gmac.h" +#include "elmer0.h" +#include "vsc7326_reg.h" + +/* Update fast changing statistics every 15 seconds */ +#define STATS_TICK_SECS 15 +/* 30 minutes for full statistics update */ +#define MAJOR_UPDATE_TICKS (1800 / STATS_TICK_SECS) + +#define MAX_MTU 9600 + +/* The egress WM value 0x01a01fff should be used only when the + * interface is down (MAC port disabled). This is a workaround + * for disabling the T2/MAC flow-control. When the interface is + * enabled, the WM value should be set to 0x014a03F0. + */ +#define WM_DISABLE 0x01a01fff +#define WM_ENABLE 0x014a03F0 + +struct init_table { + u32 addr; + u32 data; +}; + +struct _cmac_instance { + u32 index; + u32 ticks; +}; + +#define INITBLOCK_SLEEP 0xffffffff + +static void vsc_read(adapter_t *adapter, u32 addr, u32 *val) +{ + u32 status, vlo, vhi; + int i; + + spin_lock_bh(&adapter->mac_lock); + t1_tpi_read(adapter, (addr << 2) + 4, &vlo); + i = 0; + do { + t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo); + t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi); + status = (vhi << 16) | vlo; + i++; + } while (((status & 1) == 0) && (i < 50)); + if (i == 50) + CH_ERR("Invalid tpi read from MAC, breaking loop.\n"); + + t1_tpi_read(adapter, (REG_LOCAL_DATA << 2) + 4, &vlo); + t1_tpi_read(adapter, REG_LOCAL_DATA << 2, &vhi); + + *val = (vhi << 16) | vlo; + + /* CH_ERR("rd: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", + ((addr&0xe000)>>13), ((addr&0x1e00)>>9), + ((addr&0x01fe)>>1), *val); */ + spin_unlock_bh(&adapter->mac_lock); +} + +static void vsc_write(adapter_t *adapter, u32 addr, u32 data) +{ + spin_lock_bh(&adapter->mac_lock); + t1_tpi_write(adapter, (addr << 2) + 4, data & 0xFFFF); + t1_tpi_write(adapter, addr << 2, (data >> 16) & 0xFFFF); + /* CH_ERR("wr: block: 0x%x sublock: 0x%x reg: 0x%x data: 0x%x\n", + ((addr&0xe000)>>13), ((addr&0x1e00)>>9), + ((addr&0x01fe)>>1), data); */ + spin_unlock_bh(&adapter->mac_lock); +} + +/* Hard reset the MAC. This wipes out *all* configuration. */ +static void vsc7326_full_reset(adapter_t* adapter) +{ + u32 val; + u32 result = 0xffff; + + t1_tpi_read(adapter, A_ELMER0_GPO, &val); + val &= ~1; + t1_tpi_write(adapter, A_ELMER0_GPO, val); + udelay(2); + val |= 0x1; /* Enable mac MAC itself */ + val |= 0x800; /* Turn off the red LED */ + t1_tpi_write(adapter, A_ELMER0_GPO, val); + mdelay(1); + vsc_write(adapter, REG_SW_RESET, 0x80000001); + do { + mdelay(1); + vsc_read(adapter, REG_SW_RESET, &result); + } while (result != 0x0); +} + +static struct init_table vsc7326_reset[] = { + { REG_IFACE_MODE, 0x00000000 }, + { REG_CRC_CFG, 0x00000020 }, + { REG_PLL_CLK_SPEED, 0x00050c00 }, + { REG_PLL_CLK_SPEED, 0x00050c00 }, + { REG_MSCH, 0x00002f14 }, + { REG_SPI4_MISC, 0x00040409 }, + { REG_SPI4_DESKEW, 0x00080000 }, + { REG_SPI4_ING_SETUP2, 0x08080004 }, + { REG_SPI4_ING_SETUP0, 0x04111004 }, + { REG_SPI4_EGR_SETUP0, 0x80001a04 }, + { REG_SPI4_ING_SETUP1, 0x02010000 }, + { REG_AGE_INC(0), 0x00000000 }, + { REG_AGE_INC(1), 0x00000000 }, + { REG_ING_CONTROL, 0x0a200011 }, + { REG_EGR_CONTROL, 0xa0010091 }, +}; + +static struct init_table vsc7326_portinit[4][22] = { + { /* Port 0 */ + /* FIFO setup */ + { REG_DBG(0), 0x000004f0 }, + { REG_HDX(0), 0x00073101 }, + { REG_TEST(0,0), 0x00000022 }, + { REG_TEST(1,0), 0x00000022 }, + { REG_TOP_BOTTOM(0,0), 0x003f0000 }, + { REG_TOP_BOTTOM(1,0), 0x00120000 }, + { REG_HIGH_LOW_WM(0,0), 0x07460757 }, + { REG_HIGH_LOW_WM(1,0), WM_DISABLE }, + { REG_CT_THRHLD(0,0), 0x00000000 }, + { REG_CT_THRHLD(1,0), 0x00000000 }, + { REG_BUCKE(0), 0x0002ffff }, + { REG_BUCKI(0), 0x0002ffff }, + { REG_TEST(0,0), 0x00000020 }, + { REG_TEST(1,0), 0x00000020 }, + /* Port config */ + { REG_MAX_LEN(0), 0x00002710 }, + { REG_PORT_FAIL(0), 0x00000002 }, + { REG_NORMALIZER(0), 0x00000a64 }, + { REG_DENORM(0), 0x00000010 }, + { REG_STICK_BIT(0), 0x03baa370 }, + { REG_DEV_SETUP(0), 0x00000083 }, + { REG_DEV_SETUP(0), 0x00000082 }, + { REG_MODE_CFG(0), 0x0200259f }, + }, + { /* Port 1 */ + /* FIFO setup */ + { REG_DBG(1), 0x000004f0 }, + { REG_HDX(1), 0x00073101 }, + { REG_TEST(0,1), 0x00000022 }, + { REG_TEST(1,1), 0x00000022 }, + { REG_TOP_BOTTOM(0,1), 0x007e003f }, + { REG_TOP_BOTTOM(1,1), 0x00240012 }, + { REG_HIGH_LOW_WM(0,1), 0x07460757 }, + { REG_HIGH_LOW_WM(1,1), WM_DISABLE }, + { REG_CT_THRHLD(0,1), 0x00000000 }, + { REG_CT_THRHLD(1,1), 0x00000000 }, + { REG_BUCKE(1), 0x0002ffff }, + { REG_BUCKI(1), 0x0002ffff }, + { REG_TEST(0,1), 0x00000020 }, + { REG_TEST(1,1), 0x00000020 }, + /* Port config */ + { REG_MAX_LEN(1), 0x00002710 }, + { REG_PORT_FAIL(1), 0x00000002 }, + { REG_NORMALIZER(1), 0x00000a64 }, + { REG_DENORM(1), 0x00000010 }, + { REG_STICK_BIT(1), 0x03baa370 }, + { REG_DEV_SETUP(1), 0x00000083 }, + { REG_DEV_SETUP(1), 0x00000082 }, + { REG_MODE_CFG(1), 0x0200259f }, + }, + { /* Port 2 */ + /* FIFO setup */ + { REG_DBG(2), 0x000004f0 }, + { REG_HDX(2), 0x00073101 }, + { REG_TEST(0,2), 0x00000022 }, + { REG_TEST(1,2), 0x00000022 }, + { REG_TOP_BOTTOM(0,2), 0x00bd007e }, + { REG_TOP_BOTTOM(1,2), 0x00360024 }, + { REG_HIGH_LOW_WM(0,2), 0x07460757 }, + { REG_HIGH_LOW_WM(1,2), WM_DISABLE }, + { REG_CT_THRHLD(0,2), 0x00000000 }, + { REG_CT_THRHLD(1,2), 0x00000000 }, + { REG_BUCKE(2), 0x0002ffff }, + { REG_BUCKI(2), 0x0002ffff }, + { REG_TEST(0,2), 0x00000020 }, + { REG_TEST(1,2), 0x00000020 }, + /* Port config */ + { REG_MAX_LEN(2), 0x00002710 }, + { REG_PORT_FAIL(2), 0x00000002 }, + { REG_NORMALIZER(2), 0x00000a64 }, + { REG_DENORM(2), 0x00000010 }, + { REG_STICK_BIT(2), 0x03baa370 }, + { REG_DEV_SETUP(2), 0x00000083 }, + { REG_DEV_SETUP(2), 0x00000082 }, + { REG_MODE_CFG(2), 0x0200259f }, + }, + { /* Port 3 */ + /* FIFO setup */ + { REG_DBG(3), 0x000004f0 }, + { REG_HDX(3), 0x00073101 }, + { REG_TEST(0,3), 0x00000022 }, + { REG_TEST(1,3), 0x00000022 }, + { REG_TOP_BOTTOM(0,3), 0x00fc00bd }, + { REG_TOP_BOTTOM(1,3), 0x00480036 }, + { REG_HIGH_LOW_WM(0,3), 0x07460757 }, + { REG_HIGH_LOW_WM(1,3), WM_DISABLE }, + { REG_CT_THRHLD(0,3), 0x00000000 }, + { REG_CT_THRHLD(1,3), 0x00000000 }, + { REG_BUCKE(3), 0x0002ffff }, + { REG_BUCKI(3), 0x0002ffff }, + { REG_TEST(0,3), 0x00000020 }, + { REG_TEST(1,3), 0x00000020 }, + /* Port config */ + { REG_MAX_LEN(3), 0x00002710 }, + { REG_PORT_FAIL(3), 0x00000002 }, + { REG_NORMALIZER(3), 0x00000a64 }, + { REG_DENORM(3), 0x00000010 }, + { REG_STICK_BIT(3), 0x03baa370 }, + { REG_DEV_SETUP(3), 0x00000083 }, + { REG_DEV_SETUP(3), 0x00000082 }, + { REG_MODE_CFG(3), 0x0200259f }, + }, +}; + +static void run_table(adapter_t *adapter, struct init_table *ib, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (ib[i].addr == INITBLOCK_SLEEP) { + udelay( ib[i].data ); + CH_ERR("sleep %d us\n",ib[i].data); + } else { + vsc_write( adapter, ib[i].addr, ib[i].data ); + } + } +} + +static int bist_rd(adapter_t *adapter, int moduleid, int address) +{ + int data=0; + u32 result=0; + + if( (address != 0x0) && + (address != 0x1) && + (address != 0x2) && + (address != 0xd) && + (address != 0xe)) + CH_ERR("No bist address: 0x%x\n", address); + + data = ((0x00 << 24) | ((address & 0xff) << 16) | (0x00 << 8) | + ((moduleid & 0xff) << 0)); + vsc_write(adapter, REG_RAM_BIST_CMD, data); + + udelay(10); + + vsc_read(adapter, REG_RAM_BIST_RESULT, &result); + if((result & (1<<9)) != 0x0) + CH_ERR("Still in bist read: 0x%x\n", result); + else if((result & (1<<8)) != 0x0) + CH_ERR("bist read error: 0x%x\n", result); + + return(result & 0xff); +} + +static int bist_wr(adapter_t *adapter, int moduleid, int address, int value) +{ + int data=0; + u32 result=0; + + if( (address != 0x0) && + (address != 0x1) && + (address != 0x2) && + (address != 0xd) && + (address != 0xe)) + CH_ERR("No bist address: 0x%x\n", address); + + if( value>255 ) + CH_ERR("Suspicious write out of range value: 0x%x\n", value); + + data = ((0x01 << 24) | ((address & 0xff) << 16) | (value << 8) | + ((moduleid & 0xff) << 0)); + vsc_write(adapter, REG_RAM_BIST_CMD, data); + + udelay(5); + + vsc_read(adapter, REG_RAM_BIST_CMD, &result); + if((result & (1<<27)) != 0x0) + CH_ERR("Still in bist write: 0x%x\n", result); + else if((result & (1<<26)) != 0x0) + CH_ERR("bist write error: 0x%x\n", result); + + return(0); +} + +static int run_bist(adapter_t *adapter, int moduleid) +{ + /*run bist*/ + (void) bist_wr(adapter,moduleid, 0x00, 0x02); + (void) bist_wr(adapter,moduleid, 0x01, 0x01); + + return(0); +} + +static int check_bist(adapter_t *adapter, int moduleid) +{ + int result=0; + int column=0; + /*check bist*/ + result = bist_rd(adapter,moduleid, 0x02); + column = ((bist_rd(adapter,moduleid, 0x0e)<<8) + + (bist_rd(adapter,moduleid, 0x0d))); + if ((result & 3) != 0x3) + CH_ERR("Result: 0x%x BIST error in ram %d, column: 0x%04x\n", + result, moduleid, column); + return(0); +} + +static int enable_mem(adapter_t *adapter, int moduleid) +{ + /*enable mem*/ + (void) bist_wr(adapter,moduleid, 0x00, 0x00); + return(0); +} + +static int run_bist_all(adapter_t *adapter) +{ + int port=0; + u32 val=0; + + vsc_write(adapter, REG_MEM_BIST, 0x5); + vsc_read(adapter, REG_MEM_BIST, &val); + + for(port=0; port<12; port++){ + vsc_write(adapter, REG_DEV_SETUP(port), 0x0); + } + + udelay(300); + vsc_write(adapter, REG_SPI4_MISC, 0x00040409); + udelay(300); + + (void) run_bist(adapter,13); + (void) run_bist(adapter,14); + (void) run_bist(adapter,20); + (void) run_bist(adapter,21); + mdelay(200); + (void) check_bist(adapter,13); + (void) check_bist(adapter,14); + (void) check_bist(adapter,20); + (void) check_bist(adapter,21); + udelay(100); + (void) enable_mem(adapter,13); + (void) enable_mem(adapter,14); + (void) enable_mem(adapter,20); + (void) enable_mem(adapter,21); + udelay(300); + vsc_write(adapter, REG_SPI4_MISC, 0x60040400); + udelay(300); + for(port=0; port<12; port++){ + vsc_write(adapter, REG_DEV_SETUP(port), 0x1); + } + udelay(300); + vsc_write(adapter, REG_MEM_BIST, 0x0); + mdelay(10); + return(0); +} + +static int mac_intr_handler(struct cmac *mac) +{ + return 0; +} + +static int mac_intr_enable(struct cmac *mac) +{ + return 0; +} + +static int mac_intr_disable(struct cmac *mac) +{ + return 0; +} + +static int mac_intr_clear(struct cmac *mac) +{ + return 0; +} + +/* Expect MAC address to be in network byte order. */ +static int mac_set_address(struct cmac* mac, u8 addr[6]) +{ + u32 val; + int port = mac->instance->index; + + vsc_write(mac->adapter, REG_MAC_LOW_ADDR(port), + (addr[3] << 16) | (addr[4] << 8) | addr[5]); + vsc_write(mac->adapter, REG_MAC_HIGH_ADDR(port), + (addr[0] << 16) | (addr[1] << 8) | addr[2]); + + vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &val); + val &= ~0xf0000000; + vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, val | (port << 28)); + + vsc_write(mac->adapter, REG_ING_FFILT_MASK0, + 0xffff0000 | (addr[4] << 8) | addr[5]); + vsc_write(mac->adapter, REG_ING_FFILT_MASK1, + 0xffff0000 | (addr[2] << 8) | addr[3]); + vsc_write(mac->adapter, REG_ING_FFILT_MASK2, + 0xffff0000 | (addr[0] << 8) | addr[1]); + return 0; +} + +static int mac_get_address(struct cmac *mac, u8 addr[6]) +{ + u32 addr_lo, addr_hi; + int port = mac->instance->index; + + vsc_read(mac->adapter, REG_MAC_LOW_ADDR(port), &addr_lo); + vsc_read(mac->adapter, REG_MAC_HIGH_ADDR(port), &addr_hi); + + addr[0] = (u8) (addr_hi >> 16); + addr[1] = (u8) (addr_hi >> 8); + addr[2] = (u8) addr_hi; + addr[3] = (u8) (addr_lo >> 16); + addr[4] = (u8) (addr_lo >> 8); + addr[5] = (u8) addr_lo; + return 0; +} + +/* This is intended to reset a port, not the whole MAC */ +static int mac_reset(struct cmac *mac) +{ + int index = mac->instance->index; + + run_table(mac->adapter, vsc7326_portinit[index], + ARRAY_SIZE(vsc7326_portinit[index])); + + return 0; +} + +static int mac_set_rx_mode(struct cmac *mac, struct t1_rx_mode *rm) +{ + u32 v; + int port = mac->instance->index; + + vsc_read(mac->adapter, REG_ING_FFILT_UM_EN, &v); + v |= 1 << 12; + + if (t1_rx_mode_promisc(rm)) + v &= ~(1 << (port + 16)); + else + v |= 1 << (port + 16); + + vsc_write(mac->adapter, REG_ING_FFILT_UM_EN, v); + return 0; +} + +static int mac_set_mtu(struct cmac *mac, int mtu) +{ + int port = mac->instance->index; + + if (mtu > MAX_MTU) + return -EINVAL; + + /* max_len includes header and FCS */ + vsc_write(mac->adapter, REG_MAX_LEN(port), mtu + 14 + 4); + return 0; +} + +static int mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, + int fc) +{ + u32 v; + int enable, port = mac->instance->index; + + if (speed >= 0 && speed != SPEED_10 && speed != SPEED_100 && + speed != SPEED_1000) + return -1; + if (duplex > 0 && duplex != DUPLEX_FULL) + return -1; + + if (speed >= 0) { + vsc_read(mac->adapter, REG_MODE_CFG(port), &v); + enable = v & 3; /* save tx/rx enables */ + v &= ~0xf; + v |= 4; /* full duplex */ + if (speed == SPEED_1000) + v |= 8; /* GigE */ + enable |= v; + vsc_write(mac->adapter, REG_MODE_CFG(port), v); + + if (speed == SPEED_1000) + v = 0x82; + else if (speed == SPEED_100) + v = 0x84; + else /* SPEED_10 */ + v = 0x86; + vsc_write(mac->adapter, REG_DEV_SETUP(port), v | 1); /* reset */ + vsc_write(mac->adapter, REG_DEV_SETUP(port), v); + vsc_read(mac->adapter, REG_DBG(port), &v); + v &= ~0xff00; + if (speed == SPEED_1000) + v |= 0x400; + else if (speed == SPEED_100) + v |= 0x2000; + else /* SPEED_10 */ + v |= 0xff00; + vsc_write(mac->adapter, REG_DBG(port), v); + + vsc_write(mac->adapter, REG_TX_IFG(port), + speed == SPEED_1000 ? 5 : 0x11); + if (duplex == DUPLEX_HALF) + enable = 0x0; /* 100 or 10 */ + else if (speed == SPEED_1000) + enable = 0xc; + else /* SPEED_100 or 10 */ + enable = 0x4; + enable |= 0x9 << 10; /* IFG1 */ + enable |= 0x6 << 6; /* IFG2 */ + enable |= 0x1 << 4; /* VLAN */ + enable |= 0x3; /* RX/TX EN */ + vsc_write(mac->adapter, REG_MODE_CFG(port), enable); + + } + + vsc_read(mac->adapter, REG_PAUSE_CFG(port), &v); + v &= 0xfff0ffff; + v |= 0x20000; /* xon/xoff */ + if (fc & PAUSE_RX) + v |= 0x40000; + if (fc & PAUSE_TX) + v |= 0x80000; + if (fc == (PAUSE_RX | PAUSE_TX)) + v |= 0x10000; + vsc_write(mac->adapter, REG_PAUSE_CFG(port), v); + return 0; +} + +static int mac_enable(struct cmac *mac, int which) +{ + u32 val; + int port = mac->instance->index; + + /* Write the correct WM value when the port is enabled. */ + vsc_write(mac->adapter, REG_HIGH_LOW_WM(1,port), WM_ENABLE); + + vsc_read(mac->adapter, REG_MODE_CFG(port), &val); + if (which & MAC_DIRECTION_RX) + val |= 0x2; + if (which & MAC_DIRECTION_TX) + val |= 1; + vsc_write(mac->adapter, REG_MODE_CFG(port), val); + return 0; +} + +static int mac_disable(struct cmac *mac, int which) +{ + u32 val; + int i, port = mac->instance->index; + + /* Reset the port, this also writes the correct WM value */ + mac_reset(mac); + + vsc_read(mac->adapter, REG_MODE_CFG(port), &val); + if (which & MAC_DIRECTION_RX) + val &= ~0x2; + if (which & MAC_DIRECTION_TX) + val &= ~0x1; + vsc_write(mac->adapter, REG_MODE_CFG(port), val); + vsc_read(mac->adapter, REG_MODE_CFG(port), &val); + + /* Clear stats */ + for (i = 0; i <= 0x3a; ++i) + vsc_write(mac->adapter, CRA(4, port, i), 0); + + /* Clear sofware counters */ + memset(&mac->stats, 0, sizeof(struct cmac_statistics)); + + return 0; +} + +static void rmon_update(struct cmac *mac, unsigned int addr, u64 *stat) +{ + u32 v, lo; + + vsc_read(mac->adapter, addr, &v); + lo = *stat; + *stat = *stat - lo + v; + + if (v == 0) + return; + + if (v < lo) + *stat += (1ULL << 32); +} + +static void port_stats_update(struct cmac *mac) +{ + int port = mac->instance->index; + + /* Rx stats */ + rmon_update(mac, REG_RX_OK_BYTES(port), &mac->stats.RxOctetsOK); + rmon_update(mac, REG_RX_BAD_BYTES(port), &mac->stats.RxOctetsBad); + rmon_update(mac, REG_RX_UNICAST(port), &mac->stats.RxUnicastFramesOK); + rmon_update(mac, REG_RX_MULTICAST(port), + &mac->stats.RxMulticastFramesOK); + rmon_update(mac, REG_RX_BROADCAST(port), + &mac->stats.RxBroadcastFramesOK); + rmon_update(mac, REG_CRC(port), &mac->stats.RxFCSErrors); + rmon_update(mac, REG_RX_ALIGNMENT(port), &mac->stats.RxAlignErrors); + rmon_update(mac, REG_RX_OVERSIZE(port), + &mac->stats.RxFrameTooLongErrors); + rmon_update(mac, REG_RX_PAUSE(port), &mac->stats.RxPauseFrames); + rmon_update(mac, REG_RX_JABBERS(port), &mac->stats.RxJabberErrors); + rmon_update(mac, REG_RX_FRAGMENTS(port), &mac->stats.RxRuntErrors); + rmon_update(mac, REG_RX_UNDERSIZE(port), &mac->stats.RxRuntErrors); + rmon_update(mac, REG_RX_SYMBOL_CARRIER(port), + &mac->stats.RxSymbolErrors); + rmon_update(mac, REG_RX_SIZE_1519_TO_MAX(port), + &mac->stats.RxJumboFramesOK); + + /* Tx stats (skip collision stats as we are full-duplex only) */ + rmon_update(mac, REG_TX_OK_BYTES(port), &mac->stats.TxOctetsOK); + rmon_update(mac, REG_TX_UNICAST(port), &mac->stats.TxUnicastFramesOK); + rmon_update(mac, REG_TX_MULTICAST(port), + &mac->stats.TxMulticastFramesOK); + rmon_update(mac, REG_TX_BROADCAST(port), + &mac->stats.TxBroadcastFramesOK); + rmon_update(mac, REG_TX_PAUSE(port), &mac->stats.TxPauseFrames); + rmon_update(mac, REG_TX_UNDERRUN(port), &mac->stats.TxUnderrun); + rmon_update(mac, REG_TX_SIZE_1519_TO_MAX(port), + &mac->stats.TxJumboFramesOK); +} + +/* + * This function is called periodically to accumulate the current values of the + * RMON counters into the port statistics. Since the counters are only 32 bits + * some of them can overflow in less than a minute at GigE speeds, so this + * function should be called every 30 seconds or so. + * + * To cut down on reading costs we update only the octet counters at each tick + * and do a full update at major ticks, which can be every 30 minutes or more. + */ +static const struct cmac_statistics *mac_update_statistics(struct cmac *mac, + int flag) +{ + if (flag == MAC_STATS_UPDATE_FULL || + mac->instance->ticks >= MAJOR_UPDATE_TICKS) { + port_stats_update(mac); + mac->instance->ticks = 0; + } else { + int port = mac->instance->index; + + rmon_update(mac, REG_RX_OK_BYTES(port), + &mac->stats.RxOctetsOK); + rmon_update(mac, REG_RX_BAD_BYTES(port), + &mac->stats.RxOctetsBad); + rmon_update(mac, REG_TX_OK_BYTES(port), + &mac->stats.TxOctetsOK); + mac->instance->ticks++; + } + return &mac->stats; +} + +static void mac_destroy(struct cmac *mac) +{ + kfree(mac); +} + +static struct cmac_ops vsc7326_ops = { + .destroy = mac_destroy, + .reset = mac_reset, + .interrupt_handler = mac_intr_handler, + .interrupt_enable = mac_intr_enable, + .interrupt_disable = mac_intr_disable, + .interrupt_clear = mac_intr_clear, + .enable = mac_enable, + .disable = mac_disable, + .set_mtu = mac_set_mtu, + .set_rx_mode = mac_set_rx_mode, + .set_speed_duplex_fc = mac_set_speed_duplex_fc, + .statistics_update = mac_update_statistics, + .macaddress_get = mac_get_address, + .macaddress_set = mac_set_address, +}; + +static struct cmac *vsc7326_mac_create(adapter_t *adapter, int index) +{ + struct cmac *mac; + u32 val; + int i; + + mac = kzalloc(sizeof(*mac) + sizeof(cmac_instance), GFP_KERNEL); + if (!mac) return NULL; + + mac->ops = &vsc7326_ops; + mac->instance = (cmac_instance *)(mac + 1); + mac->adapter = adapter; + + mac->instance->index = index; + mac->instance->ticks = 0; + + i = 0; + do { + u32 vhi, vlo; + + vhi = vlo = 0; + t1_tpi_read(adapter, (REG_LOCAL_STATUS << 2) + 4, &vlo); + udelay(1); + t1_tpi_read(adapter, REG_LOCAL_STATUS << 2, &vhi); + udelay(5); + val = (vhi << 16) | vlo; + } while ((++i < 10000) && (val == 0xffffffff)); + + return mac; +} + +static int vsc7326_mac_reset(adapter_t *adapter) +{ + vsc7326_full_reset(adapter); + (void) run_bist_all(adapter); + run_table(adapter, vsc7326_reset, ARRAY_SIZE(vsc7326_reset)); + return 0; +} + +struct gmac t1_vsc7326_ops = { + .stats_update_period = STATS_TICK_SECS, + .create = vsc7326_mac_create, + .reset = vsc7326_mac_reset, +}; diff --git a/drivers/net/chelsio/vsc8244.c b/drivers/net/chelsio/vsc8244.c new file mode 100644 index 000000000000..c493e783d459 --- /dev/null +++ b/drivers/net/chelsio/vsc8244.c @@ -0,0 +1,368 @@ +/* + * This file is part of the Chelsio T2 Ethernet driver. + * + * Copyright (C) 2005 Chelsio Communications. All rights reserved. + * + * 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 LICENSE file included in this + * release for licensing terms and conditions. + */ + +#include "common.h" +#include "cphy.h" +#include "elmer0.h" + +#ifndef ADVERTISE_PAUSE_CAP +# define ADVERTISE_PAUSE_CAP 0x400 +#endif +#ifndef ADVERTISE_PAUSE_ASYM +# define ADVERTISE_PAUSE_ASYM 0x800 +#endif + +/* Gigabit MII registers */ +#ifndef MII_CTRL1000 +# define MII_CTRL1000 9 +#endif + +#ifndef ADVERTISE_1000FULL +# define ADVERTISE_1000FULL 0x200 +# define ADVERTISE_1000HALF 0x100 +#endif + +/* VSC8244 PHY specific registers. */ +enum { + VSC8244_INTR_ENABLE = 25, + VSC8244_INTR_STATUS = 26, + VSC8244_AUX_CTRL_STAT = 28, +}; + +enum { + VSC_INTR_RX_ERR = 1 << 0, + VSC_INTR_MS_ERR = 1 << 1, /* master/slave resolution error */ + VSC_INTR_CABLE = 1 << 2, /* cable impairment */ + VSC_INTR_FALSE_CARR = 1 << 3, /* false carrier */ + VSC_INTR_MEDIA_CHG = 1 << 4, /* AMS media change */ + VSC_INTR_RX_FIFO = 1 << 5, /* Rx FIFO over/underflow */ + VSC_INTR_TX_FIFO = 1 << 6, /* Tx FIFO over/underflow */ + VSC_INTR_DESCRAMBL = 1 << 7, /* descrambler lock-lost */ + VSC_INTR_SYMBOL_ERR = 1 << 8, /* symbol error */ + VSC_INTR_NEG_DONE = 1 << 10, /* autoneg done */ + VSC_INTR_NEG_ERR = 1 << 11, /* autoneg error */ + VSC_INTR_LINK_CHG = 1 << 13, /* link change */ + VSC_INTR_ENABLE = 1 << 15, /* interrupt enable */ +}; + +#define CFG_CHG_INTR_MASK (VSC_INTR_LINK_CHG | VSC_INTR_NEG_ERR | \ + VSC_INTR_NEG_DONE) +#define INTR_MASK (CFG_CHG_INTR_MASK | VSC_INTR_TX_FIFO | VSC_INTR_RX_FIFO | \ + VSC_INTR_ENABLE) + +/* PHY specific auxiliary control & status register fields */ +#define S_ACSR_ACTIPHY_TMR 0 +#define M_ACSR_ACTIPHY_TMR 0x3 +#define V_ACSR_ACTIPHY_TMR(x) ((x) << S_ACSR_ACTIPHY_TMR) + +#define S_ACSR_SPEED 3 +#define M_ACSR_SPEED 0x3 +#define G_ACSR_SPEED(x) (((x) >> S_ACSR_SPEED) & M_ACSR_SPEED) + +#define S_ACSR_DUPLEX 5 +#define F_ACSR_DUPLEX (1 << S_ACSR_DUPLEX) + +#define S_ACSR_ACTIPHY 6 +#define F_ACSR_ACTIPHY (1 << S_ACSR_ACTIPHY) + +/* + * Reset the PHY. This PHY completes reset immediately so we never wait. + */ +static int vsc8244_reset(struct cphy *cphy, int wait) +{ + int err; + unsigned int ctl; + + err = simple_mdio_read(cphy, MII_BMCR, &ctl); + if (err) + return err; + + ctl &= ~BMCR_PDOWN; + ctl |= BMCR_RESET; + return simple_mdio_write(cphy, MII_BMCR, ctl); +} + +static int vsc8244_intr_enable(struct cphy *cphy) +{ + simple_mdio_write(cphy, VSC8244_INTR_ENABLE, INTR_MASK); + + /* Enable interrupts through Elmer */ + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer |= ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } + + return 0; +} + +static int vsc8244_intr_disable(struct cphy *cphy) +{ + simple_mdio_write(cphy, VSC8244_INTR_ENABLE, 0); + + if (t1_is_asic(cphy->adapter)) { + u32 elmer; + + t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); + elmer &= ~ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4); + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); + } + + return 0; +} + +static int vsc8244_intr_clear(struct cphy *cphy) +{ + u32 val; + u32 elmer; + + /* Clear PHY interrupts by reading the register. */ + simple_mdio_read(cphy, VSC8244_INTR_ENABLE, &val); + + if (t1_is_asic(cphy->adapter)) { + t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); + elmer |= ELMER0_GP_BIT1; + if (is_T2(cphy->adapter)) { + elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; + } + t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); + } + + return 0; +} + +/* + * Force the PHY speed and duplex. This also disables auto-negotiation, except + * for 1Gb/s, where auto-negotiation is mandatory. + */ +static int vsc8244_set_speed_duplex(struct cphy *phy, int speed, int duplex) +{ + int err; + unsigned int ctl; + + err = simple_mdio_read(phy, MII_BMCR, &ctl); + if (err) + return err; + + if (speed >= 0) { + ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); + if (speed == SPEED_100) + ctl |= BMCR_SPEED100; + else if (speed == SPEED_1000) + ctl |= BMCR_SPEED1000; + } + if (duplex >= 0) { + ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE); + if (duplex == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + } + if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */ + ctl |= BMCR_ANENABLE; + return simple_mdio_write(phy, MII_BMCR, ctl); +} + +int t1_mdio_set_bits(struct cphy *phy, int mmd, int reg, unsigned int bits) +{ + int ret; + unsigned int val; + + ret = mdio_read(phy, mmd, reg, &val); + if (!ret) + ret = mdio_write(phy, mmd, reg, val | bits); + return ret; +} + +static int vsc8244_autoneg_enable(struct cphy *cphy) +{ + return t1_mdio_set_bits(cphy, 0, MII_BMCR, + BMCR_ANENABLE | BMCR_ANRESTART); +} + +static int vsc8244_autoneg_restart(struct cphy *cphy) +{ + return t1_mdio_set_bits(cphy, 0, MII_BMCR, BMCR_ANRESTART); +} + +static int vsc8244_advertise(struct cphy *phy, unsigned int advertise_map) +{ + int err; + unsigned int val = 0; + + err = simple_mdio_read(phy, MII_CTRL1000, &val); + if (err) + return err; + + val &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); + if (advertise_map & ADVERTISED_1000baseT_Half) + val |= ADVERTISE_1000HALF; + if (advertise_map & ADVERTISED_1000baseT_Full) + val |= ADVERTISE_1000FULL; + + err = simple_mdio_write(phy, MII_CTRL1000, val); + if (err) + return err; + + val = 1; + if (advertise_map & ADVERTISED_10baseT_Half) + val |= ADVERTISE_10HALF; + if (advertise_map & ADVERTISED_10baseT_Full) + val |= ADVERTISE_10FULL; + if (advertise_map & ADVERTISED_100baseT_Half) + val |= ADVERTISE_100HALF; + if (advertise_map & ADVERTISED_100baseT_Full) + val |= ADVERTISE_100FULL; + if (advertise_map & ADVERTISED_PAUSE) + val |= ADVERTISE_PAUSE_CAP; + if (advertise_map & ADVERTISED_ASYM_PAUSE) + val |= ADVERTISE_PAUSE_ASYM; + return simple_mdio_write(phy, MII_ADVERTISE, val); +} + +static int vsc8244_get_link_status(struct cphy *cphy, int *link_ok, + int *speed, int *duplex, int *fc) +{ + unsigned int bmcr, status, lpa, adv; + int err, sp = -1, dplx = -1, pause = 0; + + err = simple_mdio_read(cphy, MII_BMCR, &bmcr); + if (!err) + err = simple_mdio_read(cphy, MII_BMSR, &status); + if (err) + return err; + + if (link_ok) { + /* + * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it + * once more to get the current link state. + */ + if (!(status & BMSR_LSTATUS)) + err = simple_mdio_read(cphy, MII_BMSR, &status); + if (err) + return err; + *link_ok = (status & BMSR_LSTATUS) != 0; + } + if (!(bmcr & BMCR_ANENABLE)) { + dplx = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; + if (bmcr & BMCR_SPEED1000) + sp = SPEED_1000; + else if (bmcr & BMCR_SPEED100) + sp = SPEED_100; + else + sp = SPEED_10; + } else if (status & BMSR_ANEGCOMPLETE) { + err = simple_mdio_read(cphy, VSC8244_AUX_CTRL_STAT, &status); + if (err) + return err; + + dplx = (status & F_ACSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; + sp = G_ACSR_SPEED(status); + if (sp == 0) + sp = SPEED_10; + else if (sp == 1) + sp = SPEED_100; + else + sp = SPEED_1000; + + if (fc && dplx == DUPLEX_FULL) { + err = simple_mdio_read(cphy, MII_LPA, &lpa); + if (!err) + err = simple_mdio_read(cphy, MII_ADVERTISE, + &adv); + if (err) + return err; + + if (lpa & adv & ADVERTISE_PAUSE_CAP) + pause = PAUSE_RX | PAUSE_TX; + else if ((lpa & ADVERTISE_PAUSE_CAP) && + (lpa & ADVERTISE_PAUSE_ASYM) && + (adv & ADVERTISE_PAUSE_ASYM)) + pause = PAUSE_TX; + else if ((lpa & ADVERTISE_PAUSE_ASYM) && + (adv & ADVERTISE_PAUSE_CAP)) + pause = PAUSE_RX; + } + } + if (speed) + *speed = sp; + if (duplex) + *duplex = dplx; + if (fc) + *fc = pause; + return 0; +} + +static int vsc8244_intr_handler(struct cphy *cphy) +{ + unsigned int cause; + int err, cphy_cause = 0; + + err = simple_mdio_read(cphy, VSC8244_INTR_STATUS, &cause); + if (err) + return err; + + cause &= INTR_MASK; + if (cause & CFG_CHG_INTR_MASK) + cphy_cause |= cphy_cause_link_change; + if (cause & (VSC_INTR_RX_FIFO | VSC_INTR_TX_FIFO)) + cphy_cause |= cphy_cause_fifo_error; + return cphy_cause; +} + +static void vsc8244_destroy(struct cphy *cphy) +{ + kfree(cphy); +} + +static struct cphy_ops vsc8244_ops = { + .destroy = vsc8244_destroy, + .reset = vsc8244_reset, + .interrupt_enable = vsc8244_intr_enable, + .interrupt_disable = vsc8244_intr_disable, + .interrupt_clear = vsc8244_intr_clear, + .interrupt_handler = vsc8244_intr_handler, + .autoneg_enable = vsc8244_autoneg_enable, + .autoneg_restart = vsc8244_autoneg_restart, + .advertise = vsc8244_advertise, + .set_speed_duplex = vsc8244_set_speed_duplex, + .get_link_status = vsc8244_get_link_status +}; + +static struct cphy* vsc8244_phy_create(adapter_t *adapter, int phy_addr, struct mdio_ops *mdio_ops) +{ + struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); + + if (!cphy) return NULL; + + cphy_init(cphy, adapter, phy_addr, &vsc8244_ops, mdio_ops); + + return cphy; +} + + +static int vsc8244_phy_reset(adapter_t* adapter) +{ + return 0; +} + +struct gphy t1_vsc8244_ops = { + vsc8244_phy_create, + vsc8244_phy_reset +}; + + diff --git a/drivers/net/chelsio/vsc8244_reg.h b/drivers/net/chelsio/vsc8244_reg.h new file mode 100644 index 000000000000..d3c1829055cb --- /dev/null +++ b/drivers/net/chelsio/vsc8244_reg.h @@ -0,0 +1,172 @@ +/* $Date: 2005/11/23 16:28:53 $ $RCSfile: vsc8244_reg.h,v $ $Revision: 1.1 $ */ +#ifndef CHELSIO_MV8E1XXX_H +#define CHELSIO_MV8E1XXX_H + +#ifndef BMCR_SPEED1000 +# define BMCR_SPEED1000 0x40 +#endif + +#ifndef ADVERTISE_PAUSE +# define ADVERTISE_PAUSE 0x400 +#endif +#ifndef ADVERTISE_PAUSE_ASYM +# define ADVERTISE_PAUSE_ASYM 0x800 +#endif + +/* Gigabit MII registers */ +#define MII_GBMR 1 /* 1000Base-T mode register */ +#define MII_GBCR 9 /* 1000Base-T control register */ +#define MII_GBSR 10 /* 1000Base-T status register */ + +/* 1000Base-T control register fields */ +#define GBCR_ADV_1000HALF 0x100 +#define GBCR_ADV_1000FULL 0x200 +#define GBCR_PREFER_MASTER 0x400 +#define GBCR_MANUAL_AS_MASTER 0x800 +#define GBCR_MANUAL_CONFIG_ENABLE 0x1000 + +/* 1000Base-T status register fields */ +#define GBSR_LP_1000HALF 0x400 +#define GBSR_LP_1000FULL 0x800 +#define GBSR_REMOTE_OK 0x1000 +#define GBSR_LOCAL_OK 0x2000 +#define GBSR_LOCAL_MASTER 0x4000 +#define GBSR_MASTER_FAULT 0x8000 + +/* Vitesse PHY interrupt status bits. */ +#if 0 +#define VSC8244_INTR_JABBER 0x0001 +#define VSC8244_INTR_POLARITY_CHNG 0x0002 +#define VSC8244_INTR_ENG_DETECT_CHNG 0x0010 +#define VSC8244_INTR_DOWNSHIFT 0x0020 +#define VSC8244_INTR_MDI_XOVER_CHNG 0x0040 +#define VSC8244_INTR_FIFO_OVER_UNDER 0x0080 +#define VSC8244_INTR_FALSE_CARRIER 0x0100 +#define VSC8244_INTR_SYMBOL_ERROR 0x0200 +#define VSC8244_INTR_LINK_CHNG 0x0400 +#define VSC8244_INTR_AUTONEG_DONE 0x0800 +#define VSC8244_INTR_PAGE_RECV 0x1000 +#define VSC8244_INTR_DUPLEX_CHNG 0x2000 +#define VSC8244_INTR_SPEED_CHNG 0x4000 +#define VSC8244_INTR_AUTONEG_ERR 0x8000 +#else +//#define VSC8244_INTR_JABBER 0x0001 +//#define VSC8244_INTR_POLARITY_CHNG 0x0002 +//#define VSC8244_INTR_BIT2 0x0004 +//#define VSC8244_INTR_BIT3 0x0008 +#define VSC8244_INTR_RX_ERR 0x0001 +#define VSC8244_INTR_MASTER_SLAVE 0x0002 +#define VSC8244_INTR_CABLE_IMPAIRED 0x0004 +#define VSC8244_INTR_FALSE_CARRIER 0x0008 +//#define VSC8244_INTR_ENG_DETECT_CHNG 0x0010 +//#define VSC8244_INTR_DOWNSHIFT 0x0020 +//#define VSC8244_INTR_MDI_XOVER_CHNG 0x0040 +//#define VSC8244_INTR_FIFO_OVER_UNDER 0x0080 +#define VSC8244_INTR_BIT4 0x0010 +#define VSC8244_INTR_FIFO_RX 0x0020 +#define VSC8244_INTR_FIFO_OVER_UNDER 0x0040 +#define VSC8244_INTR_LOCK_LOST 0x0080 +//#define VSC8244_INTR_FALSE_CARRIER 0x0100 +//#define VSC8244_INTR_SYMBOL_ERROR 0x0200 +//#define VSC8244_INTR_LINK_CHNG 0x0400 +//#define VSC8244_INTR_AUTONEG_DONE 0x0800 +#define VSC8244_INTR_SYMBOL_ERROR 0x0100 +#define VSC8244_INTR_ENG_DETECT_CHNG 0x0200 +#define VSC8244_INTR_AUTONEG_DONE 0x0400 +#define VSC8244_INTR_AUTONEG_ERR 0x0800 +//#define VSC8244_INTR_PAGE_RECV 0x1000 +//#define VSC8244_INTR_DUPLEX_CHNG 0x2000 +//#define VSC8244_INTR_SPEED_CHNG 0x4000 +//#define VSC8244_INTR_AUTONEG_ERR 0x8000 +#define VSC8244_INTR_DUPLEX_CHNG 0x1000 +#define VSC8244_INTR_LINK_CHNG 0x2000 +#define VSC8244_INTR_SPEED_CHNG 0x4000 +#define VSC8244_INTR_STATUS 0x8000 +#endif + + +/* Vitesse PHY specific registers. */ +#define VSC8244_SPECIFIC_CNTRL_REGISTER 16 +#define VSC8244_SPECIFIC_STATUS_REGISTER 0x1c +#define VSC8244_INTERRUPT_ENABLE_REGISTER 0x19 +#define VSC8244_INTERRUPT_STATUS_REGISTER 0x1a +#define VSC8244_EXT_PHY_SPECIFIC_CNTRL_REGISTER 20 +#define VSC8244_RECV_ERR_CNTR_REGISTER 21 +#define VSC8244_RES_REGISTER 22 +#define VSC8244_GLOBAL_STATUS_REGISTER 23 +#define VSC8244_LED_CONTROL_REGISTER 24 +#define VSC8244_MANUAL_LED_OVERRIDE_REGISTER 25 +#define VSC8244_EXT_PHY_SPECIFIC_CNTRL_2_REGISTER 26 +#define VSC8244_EXT_PHY_SPECIFIC_STATUS_REGISTER 27 +#define VSC8244_VIRTUAL_CABLE_TESTER_REGISTER 28 +#define VSC8244_EXTENDED_ADDR_REGISTER 29 +#define VSC8244_EXTENDED_REGISTER 30 + +/* PHY specific control register fields */ +#define S_PSCR_MDI_XOVER_MODE 5 +#define M_PSCR_MDI_XOVER_MODE 0x3 +#define V_PSCR_MDI_XOVER_MODE(x) ((x) << S_PSCR_MDI_XOVER_MODE) +#define G_PSCR_MDI_XOVER_MODE(x) (((x) >> S_PSCR_MDI_XOVER_MODE) & M_PSCR_MDI_XOVER_MODE) + +/* Extended PHY specific control register fields */ +#define S_DOWNSHIFT_ENABLE 8 +#define V_DOWNSHIFT_ENABLE (1 << S_DOWNSHIFT_ENABLE) + +#define S_DOWNSHIFT_CNT 9 +#define M_DOWNSHIFT_CNT 0x7 +#define V_DOWNSHIFT_CNT(x) ((x) << S_DOWNSHIFT_CNT) +#define G_DOWNSHIFT_CNT(x) (((x) >> S_DOWNSHIFT_CNT) & M_DOWNSHIFT_CNT) + +/* PHY specific status register fields */ +#define S_PSSR_JABBER 0 +#define V_PSSR_JABBER (1 << S_PSSR_JABBER) + +#define S_PSSR_POLARITY 1 +#define V_PSSR_POLARITY (1 << S_PSSR_POLARITY) + +#define S_PSSR_RX_PAUSE 2 +#define V_PSSR_RX_PAUSE (1 << S_PSSR_RX_PAUSE) + +#define S_PSSR_TX_PAUSE 3 +#define V_PSSR_TX_PAUSE (1 << S_PSSR_TX_PAUSE) + +#define S_PSSR_ENERGY_DETECT 4 +#define V_PSSR_ENERGY_DETECT (1 << S_PSSR_ENERGY_DETECT) + +#define S_PSSR_DOWNSHIFT_STATUS 5 +#define V_PSSR_DOWNSHIFT_STATUS (1 << S_PSSR_DOWNSHIFT_STATUS) + +#define S_PSSR_MDI 6 +#define V_PSSR_MDI (1 << S_PSSR_MDI) + +#define S_PSSR_CABLE_LEN 7 +#define M_PSSR_CABLE_LEN 0x7 +#define V_PSSR_CABLE_LEN(x) ((x) << S_PSSR_CABLE_LEN) +#define G_PSSR_CABLE_LEN(x) (((x) >> S_PSSR_CABLE_LEN) & M_PSSR_CABLE_LEN) + +//#define S_PSSR_LINK 10 +//#define S_PSSR_LINK 13 +#define S_PSSR_LINK 2 +#define V_PSSR_LINK (1 << S_PSSR_LINK) + +//#define S_PSSR_STATUS_RESOLVED 11 +//#define S_PSSR_STATUS_RESOLVED 10 +#define S_PSSR_STATUS_RESOLVED 15 +#define V_PSSR_STATUS_RESOLVED (1 << S_PSSR_STATUS_RESOLVED) + +#define S_PSSR_PAGE_RECEIVED 12 +#define V_PSSR_PAGE_RECEIVED (1 << S_PSSR_PAGE_RECEIVED) + +//#define S_PSSR_DUPLEX 13 +//#define S_PSSR_DUPLEX 12 +#define S_PSSR_DUPLEX 5 +#define V_PSSR_DUPLEX (1 << S_PSSR_DUPLEX) + +//#define S_PSSR_SPEED 14 +//#define S_PSSR_SPEED 14 +#define S_PSSR_SPEED 3 +#define M_PSSR_SPEED 0x3 +#define V_PSSR_SPEED(x) ((x) << S_PSSR_SPEED) +#define G_PSSR_SPEED(x) (((x) >> S_PSSR_SPEED) & M_PSSR_SPEED) + +#endif -- cgit v1.2.3 From a7377a50b88fce135249cfa68dfe02fac4f5fd61 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:18 -0800 Subject: [PATCH] chelsio: cleanup pm3393 code Replace macro with function for updating RMON values Cleanups: * remove unused enum's * Fix comment format Signed-off-by: Stephen HEmminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/pm3393.c | 69 +++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index b943f5ddd8fd..a1d15eebe12c 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -43,22 +43,6 @@ #include "elmer0.h" #include "suni1x10gexp_regs.h" -/* 802.3ae 10Gb/s MDIO Manageable Device(MMD) - */ -enum { - MMD_RESERVED, - MMD_PMAPMD, - MMD_WIS, - MMD_PCS, - MMD_PHY_XGXS, /* XGMII Extender Sublayer */ - MMD_DTE_XGXS, -}; - -enum { - PHY_XGXS_CTRL_1, - PHY_XGXS_STATUS_1 -}; - #define OFFSET(REG_ADDR) (REG_ADDR << 2) /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ @@ -128,12 +112,12 @@ static int pm3393_reset(struct cmac *cmac) /* * Enable interrupts for the PM3393 - - 1. Enable PM3393 BLOCK interrupts. - 2. Enable PM3393 Master Interrupt bit(INTE) - 3. Enable ELMER's PM3393 bit. - 4. Enable Terminator external interrupt. -*/ + * + * 1. Enable PM3393 BLOCK interrupts. + * 2. Enable PM3393 Master Interrupt bit(INTE) + * 3. Enable ELMER's PM3393 bit. + * 4. Enable Terminator external interrupt. + */ static int pm3393_interrupt_enable(struct cmac *cmac) { u32 pl_intr; @@ -261,11 +245,7 @@ static int pm3393_interrupt_clear(struct cmac *cmac) static int pm3393_interrupt_handler(struct cmac *cmac) { u32 master_intr_status; -/* - 1. Read master interrupt register. - 2. Read BLOCK's interrupt status registers. - 3. Handle BLOCK interrupts. -*/ + /* Read the master interrupt status register. */ pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &master_intr_status); @@ -473,20 +453,29 @@ static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex, return 0; } +static void pm3393_rmon_update(struct adapter *adapter, u32 offs, u64 *val, + int over) +{ + u32 val0, val1, val2; + + t1_tpi_read(adapter, offs, &val0); + t1_tpi_read(adapter, offs + 4, &val1); + t1_tpi_read(adapter, offs + 8, &val2); + + *val &= ~0ull << 40; + *val |= val0 & 0xffff; + *val |= (val1 & 0xffff) << 16; + *val |= (u64)(val2 & 0xff) << 32; + + if (over) + *val += 1ull << 40; +} + #define RMON_UPDATE(mac, name, stat_name) \ - { \ - t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \ - t1_tpi_read((mac)->adapter, OFFSET(((name)+1)), &val1); \ - t1_tpi_read((mac)->adapter, OFFSET(((name)+2)), &val2); \ - (mac)->stats.stat_name = ((u64)val0 & 0xffff) | \ - (((u64)val1 & 0xffff) << 16) | \ - (((u64)val2 & 0xff) << 32) | \ - ((mac)->stats.stat_name & \ - (~(u64)0 << 40)); \ - if (ro & \ - ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2)) \ - (mac)->stats.stat_name += ((u64)1 << 40); \ - } + pm3393_rmon_update((mac)->adapter, OFFSET(name), \ + &(mac)->stats.stat_name, \ + (ro &((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) + static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac, int flag) -- cgit v1.2.3 From 57834ca152d5979f3f84f4e25f29f423e19d38fa Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:19 -0800 Subject: [PATCH] chelsio: use standard CRC routines Replace driver crc calculation with existing library. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 1 + drivers/net/chelsio/pm3393.c | 31 +++---------------------------- 2 files changed, 4 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ee391f29dae7..9de0eed6755b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2360,6 +2360,7 @@ menu "Ethernet (10000 Mbit)" config CHELSIO_T1 tristate "Chelsio 10Gb Ethernet support" depends on PCI + select CRC32 help This driver supports Chelsio gigabit and 10-gigabit Ethernet cards. More information about adapter features and diff --git a/drivers/net/chelsio/pm3393.c b/drivers/net/chelsio/pm3393.c index a1d15eebe12c..63cabeb98afe 100644 --- a/drivers/net/chelsio/pm3393.c +++ b/drivers/net/chelsio/pm3393.c @@ -43,6 +43,8 @@ #include "elmer0.h" #include "suni1x10gexp_regs.h" +#include + #define OFFSET(REG_ADDR) (REG_ADDR << 2) /* Max frame size PM3393 can handle. Includes Ethernet header and CRC. */ @@ -345,33 +347,6 @@ static int pm3393_set_mtu(struct cmac *cmac, int mtu) return 0; } -static u32 calc_crc(u8 *b, int len) -{ - int i; - u32 crc = (u32)~0; - - /* calculate crc one bit at a time */ - while (len--) { - crc ^= *b++; - for (i = 0; i < 8; i++) { - if (crc & 0x1) - crc = (crc >> 1) ^ 0xedb88320; - else - crc = (crc >> 1); - } - } - - /* reverse bits */ - crc = ((crc >> 4) & 0x0f0f0f0f) | ((crc << 4) & 0xf0f0f0f0); - crc = ((crc >> 2) & 0x33333333) | ((crc << 2) & 0xcccccccc); - crc = ((crc >> 1) & 0x55555555) | ((crc << 1) & 0xaaaaaaaa); - /* swap bytes */ - crc = (crc >> 16) | (crc << 16); - crc = (crc >> 8 & 0x00ff00ff) | (crc << 8 & 0xff00ff00); - - return crc; -} - static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) { int enabled = cmac->instance->enabled & MAC_DIRECTION_RX; @@ -405,7 +380,7 @@ static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm) u16 mc_filter[4] = { 0, }; while ((addr = t1_get_next_mcaddr(rm))) { - bit = (calc_crc(addr, ETH_ALEN) >> 23) & 0x3f; /* bit[23:28] */ + bit = (ether_crc(ETH_ALEN, addr) >> 23) & 0x3f; /* bit[23:28] */ mc_filter[bit >> 4] |= 1 << (bit & 0xf); } pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]); -- cgit v1.2.3 From 325dde48914e8ec1614d79ffacdbf9c0b8d24f42 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:20 -0800 Subject: [PATCH] chelsio: add MSI support Using MSI can avoid sharing IRQ and associated overhead. Tested on PCI-X. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/common.h | 1 + drivers/net/chelsio/cxgb2.c | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/common.h b/drivers/net/chelsio/common.h index 55f1eaad115c..b265941e1372 100644 --- a/drivers/net/chelsio/common.h +++ b/drivers/net/chelsio/common.h @@ -228,6 +228,7 @@ struct adapter_params { unsigned short chip_revision; unsigned char chip_version; unsigned char is_asic; + unsigned char has_msi; }; struct link_config { diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 571aa06ddfd4..0ca5b07c1a6b 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -107,6 +107,10 @@ static int t1powersave = 1; /* HW default is powersave mode. */ module_param(t1powersave, int, 0); MODULE_PARM_DESC(t1powersave, "Enable/Disable T1 powersaving mode"); +static int disable_msi = 0; +module_param(disable_msi, int, 0); +MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)"); + static const char pci_speed[][4] = { "33", "66", "100", "133" }; @@ -215,11 +219,19 @@ static int cxgb_up(struct adapter *adapter) } t1_interrupts_clear(adapter); - if ((err = request_irq(adapter->pdev->irq, - t1_select_intr_handler(adapter), IRQF_SHARED, - adapter->name, adapter))) { + + adapter->params.has_msi = !disable_msi && pci_enable_msi(adapter->pdev) == 0; + err = request_irq(adapter->pdev->irq, + t1_select_intr_handler(adapter), + adapter->params.has_msi ? 0 : IRQF_SHARED, + adapter->name, adapter); + if (err) { + if (adapter->params.has_msi) + pci_disable_msi(adapter->pdev); + goto out_err; } + t1_sge_start(adapter->sge); t1_interrupts_enable(adapter); out_err: @@ -234,6 +246,8 @@ static void cxgb_down(struct adapter *adapter) t1_sge_stop(adapter->sge); t1_interrupts_disable(adapter); free_irq(adapter->pdev->irq, adapter); + if (adapter->params.has_msi) + pci_disable_msi(adapter->pdev); } static int cxgb_open(struct net_device *dev) -- cgit v1.2.3 From 56f643c28c5df63693d7c66e56f8e4767cfd7a65 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:21 -0800 Subject: [PATCH] chelsio: statistics improvement Cleanup statistics management: * Get rid of duplicate or unused statistics * Convert high volume stats to per-cpu and 64 bit Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/cxgb2.c | 74 +++++++++++++++++++++++---------------------- drivers/net/chelsio/sge.c | 65 ++++++++++++++++++++++++++++++--------- drivers/net/chelsio/sge.h | 29 ++++++++---------- 3 files changed, 100 insertions(+), 68 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c index 0ca5b07c1a6b..53bec6739812 100644 --- a/drivers/net/chelsio/cxgb2.c +++ b/drivers/net/chelsio/cxgb2.c @@ -390,13 +390,19 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "RxOutOfRangeLengthField", "RxFrameTooLongErrors", - "TSO", - "VLANextractions", - "VLANinsertions", + /* Port stats */ + "RxPackets", "RxCsumGood", + "TxPackets", "TxCsumOffload", - "RxDrops" - + "TxTso", + "RxVlan", + "TxVlan", + + /* Interrupt stats */ + "rx drops", + "pure_rsps", + "unhandled irqs", "respQ_empty", "respQ_overflow", "freelistQ_empty", @@ -404,10 +410,6 @@ static char stats_strings[][ETH_GSTRING_LEN] = { "pkt_mismatch", "cmdQ_full0", "cmdQ_full1", - "tx_ipfrags", - "tx_reg_pkts", - "tx_lso_pkts", - "tx_do_cksum", "espi_DIP2ParityErr", "espi_DIP4Err", @@ -451,12 +453,10 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, struct adapter *adapter = dev->priv; struct cmac *mac = adapter->port[dev->if_port].mac; const struct cmac_statistics *s; - const struct sge_port_stats *ss; const struct sge_intr_counts *t; + struct sge_port_stats ss; s = mac->ops->statistics_update(mac, MAC_STATS_UPDATE_FULL); - ss = t1_sge_get_port_stats(adapter->sge, dev->if_port); - t = t1_sge_get_intr_counts(adapter->sge); *data++ = s->TxOctetsOK; *data++ = s->TxOctetsBad; @@ -492,35 +492,37 @@ static void get_stats(struct net_device *dev, struct ethtool_stats *stats, *data++ = s->RxOutOfRangeLengthField; *data++ = s->RxFrameTooLongErrors; - *data++ = ss->tso; - *data++ = ss->vlan_xtract; - *data++ = ss->vlan_insert; - *data++ = ss->rx_cso_good; - *data++ = ss->tx_cso; - *data++ = ss->rx_drops; - - *data++ = (u64)t->respQ_empty; - *data++ = (u64)t->respQ_overflow; - *data++ = (u64)t->freelistQ_empty; - *data++ = (u64)t->pkt_too_big; - *data++ = (u64)t->pkt_mismatch; - *data++ = (u64)t->cmdQ_full[0]; - *data++ = (u64)t->cmdQ_full[1]; - *data++ = (u64)t->tx_ipfrags; - *data++ = (u64)t->tx_reg_pkts; - *data++ = (u64)t->tx_lso_pkts; - *data++ = (u64)t->tx_do_cksum; + t1_sge_get_port_stats(adapter->sge, dev->if_port, &ss); + *data++ = ss.rx_packets; + *data++ = ss.rx_cso_good; + *data++ = ss.tx_packets; + *data++ = ss.tx_cso; + *data++ = ss.tx_tso; + *data++ = ss.vlan_xtract; + *data++ = ss.vlan_insert; + + t = t1_sge_get_intr_counts(adapter->sge); + *data++ = t->rx_drops; + *data++ = t->pure_rsps; + *data++ = t->unhandled_irqs; + *data++ = t->respQ_empty; + *data++ = t->respQ_overflow; + *data++ = t->freelistQ_empty; + *data++ = t->pkt_too_big; + *data++ = t->pkt_mismatch; + *data++ = t->cmdQ_full[0]; + *data++ = t->cmdQ_full[1]; if (adapter->espi) { const struct espi_intr_counts *e; e = t1_espi_get_intr_counts(adapter->espi); - *data++ = (u64) e->DIP2_parity_err; - *data++ = (u64) e->DIP4_err; - *data++ = (u64) e->rx_drops; - *data++ = (u64) e->tx_drops; - *data++ = (u64) e->rx_ovflw; - *data++ = (u64) e->parity_err; + *data++ = e->DIP2_parity_err; + *data++ = e->DIP4_err; + *data++ = e->rx_drops; + *data++ = e->tx_drops; + *data++ = e->rx_ovflw; + *data++ = e->parity_err; } } diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 26df2049d849..9911048d8213 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -274,7 +274,7 @@ struct sge { struct sk_buff *espibug_skb[MAX_NPORTS]; u32 sge_control; /* shadow value of sge control reg */ struct sge_intr_counts stats; - struct sge_port_stats port_stats[MAX_NPORTS]; + struct sge_port_stats *port_stats[MAX_NPORTS]; struct sched *tx_sched; struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp; }; @@ -820,6 +820,11 @@ static inline unsigned int jumbo_payload_capacity(const struct sge *sge) */ void t1_sge_destroy(struct sge *sge) { + int i; + + for_each_port(sge->adapter, i) + free_percpu(sge->port_stats[i]); + kfree(sge->tx_sched); free_tx_resources(sge); free_rx_resources(sge); @@ -985,14 +990,28 @@ int t1_sge_intr_error_handler(struct sge *sge) return 0; } -const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge) +const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge) { return &sge->stats; } -const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port) +void t1_sge_get_port_stats(const struct sge *sge, int port, + struct sge_port_stats *ss) { - return &sge->port_stats[port]; + int cpu; + + memset(ss, 0, sizeof(*ss)); + for_each_possible_cpu(cpu) { + struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu); + + ss->rx_packets += st->rx_packets; + ss->rx_cso_good += st->rx_cso_good; + ss->tx_packets += st->tx_packets; + ss->tx_cso += st->tx_cso; + ss->tx_tso += st->tx_tso; + ss->vlan_xtract += st->vlan_xtract; + ss->vlan_insert += st->vlan_insert; + } } /** @@ -1361,36 +1380,39 @@ static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len) struct sk_buff *skb; struct cpl_rx_pkt *p; struct adapter *adapter = sge->adapter; + struct sge_port_stats *st; - sge->stats.ethernet_pkts++; skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad, sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES, SGE_RX_DROP_THRES); - if (!skb) { - sge->port_stats[0].rx_drops++; /* charge only port 0 for now */ + if (unlikely(!skb)) { + sge->stats.rx_drops++; return 0; } p = (struct cpl_rx_pkt *)skb->data; skb_pull(skb, sizeof(*p)); - skb->dev = adapter->port[p->iff].dev; if (p->iff >= adapter->params.nports) { kfree_skb(skb); return 0; } + skb->dev = adapter->port[p->iff].dev; skb->dev->last_rx = jiffies; + st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id()); + st->rx_packets++; + skb->protocol = eth_type_trans(skb, skb->dev); if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff && skb->protocol == htons(ETH_P_IP) && (skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) { - sge->port_stats[p->iff].rx_cso_good++; + ++st->rx_cso_good; skb->ip_summed = CHECKSUM_UNNECESSARY; } else skb->ip_summed = CHECKSUM_NONE; if (unlikely(adapter->vlan_grp && p->vlan_valid)) { - sge->port_stats[p->iff].vlan_xtract++; + st->vlan_xtract++; if (adapter->params.sge.polling) vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, ntohs(p->vlan)); @@ -1862,8 +1884,8 @@ static inline int eth_hdr_len(const void *data) int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct adapter *adapter = dev->priv; - struct sge_port_stats *st = &adapter->sge->port_stats[dev->if_port]; struct sge *sge = adapter->sge; + struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id()); struct cpl_tx_pkt *cpl; if (skb->protocol == htons(ETH_P_CPL5)) @@ -1873,7 +1895,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) int eth_type; struct cpl_tx_pkt_lso *hdr; - st->tso++; + ++st->tx_tso; eth_type = skb->nh.raw - skb->data == ETH_HLEN ? CPL_ETH_II : CPL_ETH_II_VLAN; @@ -1887,7 +1909,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_shinfo(skb)->gso_size)); hdr->len = htonl(skb->len - sizeof(*hdr)); cpl = (struct cpl_tx_pkt *)hdr; - sge->stats.tx_lso_pkts++; } else { /* * Packets shorter than ETH_HLEN can break the MAC, drop them @@ -1955,8 +1976,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) /* the length field isn't used so don't bother setting it */ st->tx_cso += (skb->ip_summed == CHECKSUM_PARTIAL); - sge->stats.tx_do_cksum += (skb->ip_summed == CHECKSUM_PARTIAL); - sge->stats.tx_reg_pkts++; } cpl->iff = dev->if_port; @@ -1970,6 +1989,7 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) cpl->vlan_valid = 0; send: + st->tx_packets++; dev->trans_start = jiffies; return t1_sge_tx(skb, adapter, 0, dev); } @@ -2151,6 +2171,7 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, struct sge_params *p) { struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL); + int i; if (!sge) return NULL; @@ -2160,6 +2181,12 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2; sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0; + for_each_port(adapter, i) { + sge->port_stats[i] = alloc_percpu(struct sge_port_stats); + if (!sge->port_stats[i]) + goto nomem_port; + } + init_timer(&sge->tx_reclaim_timer); sge->tx_reclaim_timer.data = (unsigned long)sge; sge->tx_reclaim_timer.function = sge_tx_reclaim_cb; @@ -2199,4 +2226,12 @@ struct sge * __devinit t1_sge_create(struct adapter *adapter, p->polling = 0; return sge; +nomem_port: + while (i >= 0) { + free_percpu(sge->port_stats[i]); + --i; + } + kfree(sge); + return NULL; + } diff --git a/drivers/net/chelsio/sge.h b/drivers/net/chelsio/sge.h index 4691c4f58e7f..7ceb0117d039 100644 --- a/drivers/net/chelsio/sge.h +++ b/drivers/net/chelsio/sge.h @@ -44,6 +44,9 @@ #include struct sge_intr_counts { + unsigned int rx_drops; /* # of packets dropped due to no mem */ + unsigned int pure_rsps; /* # of non-payload responses */ + unsigned int unhandled_irqs; /* # of unhandled interrupts */ unsigned int respQ_empty; /* # times respQ empty */ unsigned int respQ_overflow; /* # respQ overflow (fatal) */ unsigned int freelistQ_empty; /* # times freelist empty */ @@ -51,24 +54,16 @@ struct sge_intr_counts { unsigned int pkt_mismatch; unsigned int cmdQ_full[3]; /* not HW IRQ, host cmdQ[] full */ unsigned int cmdQ_restarted[3];/* # of times cmdQ X was restarted */ - unsigned int ethernet_pkts; /* # of Ethernet packets received */ - unsigned int offload_pkts; /* # of offload packets received */ - unsigned int offload_bundles; /* # of offload pkt bundles delivered */ - unsigned int pure_rsps; /* # of non-payload responses */ - unsigned int unhandled_irqs; /* # of unhandled interrupts */ - unsigned int tx_ipfrags; - unsigned int tx_reg_pkts; - unsigned int tx_lso_pkts; - unsigned int tx_do_cksum; }; struct sge_port_stats { - unsigned long rx_cso_good; /* # of successful RX csum offloads */ - unsigned long tx_cso; /* # of TX checksum offloads */ - unsigned long vlan_xtract; /* # of VLAN tag extractions */ - unsigned long vlan_insert; /* # of VLAN tag extractions */ - unsigned long tso; /* # of TSO requests */ - unsigned long rx_drops; /* # of packets dropped due to no mem */ + u64 rx_packets; /* # of Ethernet packets received */ + u64 rx_cso_good; /* # of successful RX csum offloads */ + u64 tx_packets; /* # of TX packets */ + u64 tx_cso; /* # of TX checksum offloads */ + u64 tx_tso; /* # of TSO requests */ + u64 vlan_xtract; /* # of VLAN tag extractions */ + u64 vlan_insert; /* # of VLAN tag insertions */ }; struct sk_buff; @@ -90,8 +85,8 @@ int t1_sge_intr_error_handler(struct sge *); void t1_sge_intr_enable(struct sge *); void t1_sge_intr_disable(struct sge *); void t1_sge_intr_clear(struct sge *); -const struct sge_intr_counts *t1_sge_get_intr_counts(struct sge *sge); -const struct sge_port_stats *t1_sge_get_port_stats(struct sge *sge, int port); +const struct sge_intr_counts *t1_sge_get_intr_counts(const struct sge *sge); +void t1_sge_get_port_stats(const struct sge *sge, int port, struct sge_port_stats *); void t1_sched_set_max_avail_bytes(struct sge *, unsigned int); void t1_sched_set_drain_bits_per_us(struct sge *, unsigned int, unsigned int); unsigned int t1_sched_update_parms(struct sge *, unsigned int, unsigned int, -- cgit v1.2.3 From cabdfb373ae74036225826ce260c16a8e260eb0b Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 1 Dec 2006 16:36:22 -0800 Subject: [PATCH] chelesio: transmit locking (plus bug fix). If transmit lock is contended on, then push return code back and retry at higher level. Bugfix: If buffer is reallocated because of lack of headroom and the send is blocked, then drop packet. This is necessary because caller would end up requeuing a freed skb. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/chelsio/sge.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c index 9911048d8213..0ca8d876e16f 100644 --- a/drivers/net/chelsio/sge.c +++ b/drivers/net/chelsio/sge.c @@ -1778,7 +1778,9 @@ static int t1_sge_tx(struct sk_buff *skb, struct adapter *adapter, struct cmdQ *q = &sge->cmdQ[qid]; unsigned int credits, pidx, genbit, count, use_sched_skb = 0; - spin_lock(&q->lock); + if (!spin_trylock(&q->lock)) + return NETDEV_TX_LOCKED; + reclaim_completed_tx(sge, q); pidx = q->pidx; @@ -1887,6 +1889,8 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) struct sge *sge = adapter->sge; struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id()); struct cpl_tx_pkt *cpl; + struct sk_buff *orig_skb = skb; + int ret; if (skb->protocol == htons(ETH_P_CPL5)) goto send; @@ -1930,8 +1934,6 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) * Complain when this happens but try to fix things up. */ if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) { - struct sk_buff *orig_skb = skb; - pr_debug("%s: headroom %d header_len %d\n", dev->name, skb_headroom(skb), dev->hard_header_len); @@ -1991,7 +1993,16 @@ int t1_start_xmit(struct sk_buff *skb, struct net_device *dev) send: st->tx_packets++; dev->trans_start = jiffies; - return t1_sge_tx(skb, adapter, 0, dev); + ret = t1_sge_tx(skb, adapter, 0, dev); + + /* If transmit busy, and we reallocated skb's due to headroom limit, + * then silently discard to avoid leak. + */ + if (unlikely(ret != NETDEV_TX_OK && skb != orig_skb)) { + dev_kfree_skb_any(skb); + ret = NETDEV_TX_OK; + } + return ret; } /* -- cgit v1.2.3 From e8a2b6a4207332a2d59628a12cece9e8c1d769e4 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 1 Dec 2006 12:01:06 -0600 Subject: [PATCH] PHY: Add support for configuring the PHY connection interface Most PHYs connect to an ethernet controller over a GMII or MII interface. However, a growing number are connected over different interfaces, such as RGMII or SGMII. The ethernet driver will tell the PHY what type of connection it is by setting it manually, or passing it in through phy_connect (or phy_attach). Changes include: * Updates to documentation * Updates to PHY Lib consumers * Changes to PHY Lib to add interface support * Some minor changes to whitespace in phy.h * gianfar driver now detects interface and passes appropriate value to PHY Lib Signed-off-by: Andrew Fleming Signed-off-by: Jeff Garzik --- Documentation/networking/phy.txt | 13 +++++++++---- drivers/net/au1000_eth.c | 3 ++- drivers/net/fs_enet/fs_enet-main.c | 3 ++- drivers/net/gianfar.c | 39 ++++++++++++++++++++++++++++++++++++-- drivers/net/gianfar.h | 3 +++ drivers/net/phy/phy_device.c | 29 +++++++++++++++++++--------- include/linux/phy.h | 26 +++++++++++++++++++------ 7 files changed, 93 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index 29ccae409031..0bc95eab1512 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt @@ -1,7 +1,7 @@ ------- PHY Abstraction Layer -(Updated 2005-07-21) +(Updated 2006-11-30) Purpose @@ -97,11 +97,12 @@ Letting the PHY Abstraction Layer do Everything Next, you need to know the device name of the PHY connected to this device. The name will look something like, "phy0:0", where the first number is the - bus id, and the second is the PHY's address on that bus. + bus id, and the second is the PHY's address on that bus. Typically, + the bus is responsible for making its ID unique. Now, to connect, just call this function: - phydev = phy_connect(dev, phy_name, &adjust_link, flags); + phydev = phy_connect(dev, phy_name, &adjust_link, flags, interface); phydev is a pointer to the phy_device structure which represents the PHY. If phy_connect is successful, it will return the pointer. dev, here, is the @@ -115,6 +116,10 @@ Letting the PHY Abstraction Layer do Everything This is useful if the system has put hardware restrictions on the PHY/controller, of which the PHY needs to be aware. + interface is a u32 which specifies the connection type used + between the controller and the PHY. Examples are GMII, MII, + RGMII, and SGMII. For a full list, see include/linux/phy.h + Now just make sure that phydev->supported and phydev->advertising have any values pruned from them which don't make sense for your controller (a 10/100 controller may be connected to a gigabit capable PHY, so you would need to @@ -191,7 +196,7 @@ Doing it all yourself start, or disables then frees them for stop. struct phy_device * phy_attach(struct net_device *dev, const char *phy_id, - u32 flags); + u32 flags, phy_interface_t interface); Attaches a network device to a particular PHY, binding the PHY to a generic driver if none was found during bus initialization. Passes in diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 7db3c8af0894..f0b6879a1c7d 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -360,7 +360,8 @@ static int mii_probe (struct net_device *dev) BUG_ON(!phydev); BUG_ON(phydev->attached_dev); - phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0); + phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, + PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index cb3958704a87..889d3a13e95e 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -779,7 +779,8 @@ static int fs_init_phy(struct net_device *dev) fep->oldspeed = 0; fep->oldduplex = -1; if(fep->fpi->bus_id) - phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0); + phydev = phy_connect(dev, fep->fpi->bus_id, &fs_adjust_link, 0, + PHY_INTERFACE_MODE_MII); else { printk("No phy bus ID specified in BSP code\n"); return -EINVAL; diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6bf18c82083d..baa35144134c 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -9,7 +9,7 @@ * Author: Andy Fleming * Maintainer: Kumar Gala * - * Copyright (c) 2002-2004 Freescale Semiconductor, Inc. + * Copyright (c) 2002-2006 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 @@ -398,6 +398,38 @@ static int gfar_remove(struct platform_device *pdev) } +/* Reads the controller's registers to determine what interface + * connects it to the PHY. + */ +static phy_interface_t gfar_get_interface(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + u32 ecntrl = gfar_read(&priv->regs->ecntrl); + + if (ecntrl & ECNTRL_SGMII_MODE) + return PHY_INTERFACE_MODE_SGMII; + + if (ecntrl & ECNTRL_TBI_MODE) { + if (ecntrl & ECNTRL_REDUCED_MODE) + return PHY_INTERFACE_MODE_RTBI; + else + return PHY_INTERFACE_MODE_TBI; + } + + if (ecntrl & ECNTRL_REDUCED_MODE) { + if (ecntrl & ECNTRL_REDUCED_MII_MODE) + return PHY_INTERFACE_MODE_RMII; + else + return PHY_INTERFACE_MODE_RGMII; + } + + if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT) + return PHY_INTERFACE_MODE_GMII; + + return PHY_INTERFACE_MODE_MII; +} + + /* Initializes driver's PHY state, and attaches to the PHY. * Returns 0 on success. */ @@ -409,6 +441,7 @@ static int init_phy(struct net_device *dev) SUPPORTED_1000baseT_Full : 0; struct phy_device *phydev; char phy_id[BUS_ID_SIZE]; + phy_interface_t interface; priv->oldlink = 0; priv->oldspeed = 0; @@ -416,7 +449,9 @@ static int init_phy(struct net_device *dev) snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); - phydev = phy_connect(dev, phy_id, &adjust_link, 0); + interface = gfar_get_interface(dev); + + phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 9e81a50cf2be..39e9e321fcbc 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -160,7 +160,10 @@ extern const char gfar_driver_version[]; #define ECNTRL_INIT_SETTINGS 0x00001000 #define ECNTRL_TBI_MODE 0x00000020 +#define ECNTRL_REDUCED_MODE 0x00000010 #define ECNTRL_R100 0x00000008 +#define ECNTRL_REDUCED_MII_MODE 0x00000004 +#define ECNTRL_SGMII_MODE 0x00000002 #define MRBLR_INIT_SETTINGS DEFAULT_RX_BUFFER_SIZE diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 2a08b2b62c4c..b01fc70a57db 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -59,6 +59,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) dev->duplex = -1; dev->pause = dev->asym_pause = 0; dev->link = 1; + dev->interface = PHY_INTERFACE_MODE_GMII; dev->autoneg = AUTONEG_ENABLE; @@ -137,11 +138,12 @@ void phy_prepare_link(struct phy_device *phydev, * the desired functionality. */ struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, - void (*handler)(struct net_device *), u32 flags) + void (*handler)(struct net_device *), u32 flags, + u32 interface) { struct phy_device *phydev; - phydev = phy_attach(dev, phy_id, flags); + phydev = phy_attach(dev, phy_id, flags, interface); if (IS_ERR(phydev)) return phydev; @@ -186,7 +188,7 @@ static int phy_compare_id(struct device *dev, void *data) } struct phy_device *phy_attach(struct net_device *dev, - const char *phy_id, u32 flags) + const char *phy_id, u32 flags, u32 interface) { struct bus_type *bus = &mdio_bus_type; struct phy_device *phydev; @@ -231,6 +233,20 @@ struct phy_device *phy_attach(struct net_device *dev, phydev->dev_flags = flags; + phydev->interface = interface; + + /* Do initial configuration here, now that + * we have certain key parameters + * (dev_flags and interface) */ + if (phydev->drv->config_init) { + int err; + + err = phydev->drv->config_init(phydev); + + if (err < 0) + return ERR_PTR(err); + } + return phydev; } EXPORT_SYMBOL(phy_attach); @@ -612,13 +628,8 @@ static int phy_probe(struct device *dev) spin_unlock(&phydev->lock); - if (err < 0) - return err; - - if (phydev->drv->config_init) - err = phydev->drv->config_init(phydev); - return err; + } static int phy_remove(struct device *dev) diff --git a/include/linux/phy.h b/include/linux/phy.h index ce8bc80b3c86..edd4c88ca7d8 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -47,15 +47,26 @@ #define PHY_HAS_INTERRUPT 0x00000001 #define PHY_HAS_MAGICANEG 0x00000002 +/* Interface Mode definitions */ +typedef enum { + PHY_INTERFACE_MODE_MII, + PHY_INTERFACE_MODE_GMII, + PHY_INTERFACE_MODE_SGMII, + PHY_INTERFACE_MODE_TBI, + PHY_INTERFACE_MODE_RMII, + PHY_INTERFACE_MODE_RGMII, + PHY_INTERFACE_MODE_RTBI +} phy_interface_t; + #define MII_BUS_MAX 4 -#define PHY_INIT_TIMEOUT 100000 +#define PHY_INIT_TIMEOUT 100000 #define PHY_STATE_TIME 1 #define PHY_FORCE_TIMEOUT 10 #define PHY_AN_TIMEOUT 10 -#define PHY_MAX_ADDR 32 +#define PHY_MAX_ADDR 32 /* Used when trying to connect to a specific phy (mii bus id:phy device id) */ #define PHY_ID_FMT "%x:%02x" @@ -87,8 +98,8 @@ struct mii_bus { int *irq; }; -#define PHY_INTERRUPT_DISABLED 0x0 -#define PHY_INTERRUPT_ENABLED 0x80000000 +#define PHY_INTERRUPT_DISABLED 0x0 +#define PHY_INTERRUPT_ENABLED 0x80000000 /* PHY state machine states: * @@ -230,6 +241,8 @@ struct phy_device { u32 dev_flags; + phy_interface_t interface; + /* Bus address of the PHY (0-32) */ int addr; @@ -345,9 +358,10 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); int phy_clear_interrupt(struct phy_device *phydev); int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); struct phy_device * phy_attach(struct net_device *dev, - const char *phy_id, u32 flags); + const char *phy_id, u32 flags, phy_interface_t interface); struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, - void (*handler)(struct net_device *), u32 flags); + void (*handler)(struct net_device *), u32 flags, + phy_interface_t interface); void phy_disconnect(struct phy_device *phydev); void phy_detach(struct phy_device *phydev); void phy_start(struct phy_device *phydev); -- cgit v1.2.3 From 71bd7877d470b4037c9ef0d060ac39228f0f6289 Mon Sep 17 00:00:00 2001 From: "Amit S. Kale" Date: Fri, 1 Dec 2006 05:36:22 -0800 Subject: [PATCH] NetXen: driver cleanup, removed unnecessary __iomem type casts Signed-off-by: Amit S. Kale netxen_nic.h | 38 ++++++++------------------------------ netxen_nic_ethtool.c | 5 ++--- netxen_nic_hw.c | 12 +++++------- netxen_nic_main.c | 8 +++----- 4 files changed, 18 insertions(+), 45 deletions(-) Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 38 +++++++-------------------------- drivers/net/netxen/netxen_nic_ethtool.c | 5 ++--- drivers/net/netxen/netxen_nic_hw.c | 12 +++++------ drivers/net/netxen/netxen_nic_main.c | 8 +++---- 4 files changed, 18 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 1bee560d7d0a..d925053fe597 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -343,7 +343,6 @@ typedef enum { NETXEN_BRDTYPE_P2_SB31_10G_HMEZ = 0x000e, NETXEN_BRDTYPE_P2_SB31_10G_CX4 = 0x000f } netxen_brdtype_t; -#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(netxen_brdinfo_t)) typedef enum { NETXEN_BRDMFG_INVENTEC = 1 @@ -937,9 +936,7 @@ static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) /* * ISR_INT_MASK: Can be read from window 0 or 1. */ - writel(0x7ff, - (void __iomem - *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); + writel(0x7ff, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); } @@ -959,14 +956,12 @@ static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) break; } - writel(mask, - (void __iomem - *)(PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK))); + writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK)); if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) { mask = 0xbff; - writel(mask, (void __iomem *) - (PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_TARGET_MASK))); + writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, + ISR_INT_TARGET_MASK)); } } @@ -975,13 +970,13 @@ static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) */ #define NETXEN_MAX_SHORT_NAME 16 -typedef struct { +struct netxen_brdinfo { netxen_brdtype_t brdtype; /* type of board */ long ports; /* max no of physical ports */ char short_name[NETXEN_MAX_SHORT_NAME]; -} netxen_brdinfo_t; +}; -static const netxen_brdinfo_t netxen_boards[] = { +static const struct netxen_brdinfo netxen_boards[] = { {NETXEN_BRDTYPE_P2_SB31_10G_CX4, 1, "XGb CX4"}, {NETXEN_BRDTYPE_P2_SB31_10G_HMEZ, 1, "XGb HMEZ"}, {NETXEN_BRDTYPE_P2_SB31_10G_IMEZ, 2, "XGb IMEZ"}, @@ -990,24 +985,7 @@ static const netxen_brdinfo_t netxen_boards[] = { {NETXEN_BRDTYPE_P2_SB31_2G, 2, "Dual Gb"}, }; -#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(netxen_brdinfo_t)) - -static inline void get_brd_ports_name_by_type(u32 type, int *ports, char *name) -{ - int i, found = 0; - for (i = 0; i < NUM_SUPPORTED_BOARDS; ++i) { - if (netxen_boards[i].brdtype == type) { - *ports = netxen_boards[i].ports; - strcpy(name, netxen_boards[i].short_name); - found = 1; - break; - } - } - if (!found) { - *ports = 0; - name = "Unknown"; - } -} +#define NUM_SUPPORTED_BOARDS (sizeof(netxen_boards)/sizeof(struct netxen_brdinfo)) static inline void get_brd_port_by_type(u32 type, int *ports) { diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index f3fc35cf8af7..9a914aeba5bc 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -139,8 +139,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) { struct netxen_port *port = netdev_priv(dev); struct netxen_adapter *adapter = port->adapter; - struct netxen_board_info *boardinfo; - boardinfo = &adapter->ahw.boardcfg; + struct netxen_board_info *boardinfo = &adapter->ahw.boardcfg; /* read which mode */ if (adapter->ahw.board_type == NETXEN_NIC_GBE) { @@ -208,7 +207,7 @@ netxen_nic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) ecmd->autoneg = AUTONEG_DISABLE; break; default: - printk("ERROR: Unsupported board model %d\n", + printk(KERN_ERR "netxen-nic: Unsupported board model %d\n", (netxen_brdtype_t) boardinfo->board_type); return -EIO; diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 99e647a5ae76..105c24f0ad4c 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -275,10 +275,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter) rcv_desc->desc_head = (struct rcv_desc *)addr; } - addr = netxen_alloc(adapter->ahw.pdev, - STATUS_DESC_RINGSIZE, - &recv_ctx-> - rcv_status_desc_phys_addr, + addr = netxen_alloc(adapter->ahw.pdev, STATUS_DESC_RINGSIZE, + &recv_ctx->rcv_status_desc_phys_addr, &recv_ctx->rcv_status_desc_pdev); if (addr == NULL) { DPRINTK(ERR, "bad return from" @@ -675,7 +673,7 @@ void netxen_nic_write_w0(struct netxen_adapter *adapter, u32 index, u32 value) void __iomem *addr; netxen_nic_pci_change_crbwindow(adapter, 0); - addr = (void __iomem *)(pci_base_offset(adapter, index)); + addr = pci_base_offset(adapter, index); writel(value, addr); netxen_nic_pci_change_crbwindow(adapter, 1); } @@ -685,7 +683,7 @@ void netxen_nic_read_w0(struct netxen_adapter *adapter, u32 index, u32 * value) { void __iomem *addr; - addr = (void __iomem *)(pci_base_offset(adapter, index)); + addr = pci_base_offset(adapter, index); netxen_nic_pci_change_crbwindow(adapter, 0); *value = readl(addr); @@ -865,7 +863,7 @@ netxen_crb_writelit_adapter(struct netxen_adapter *adapter, unsigned long off, writel(data, NETXEN_CRB_NORMALIZE(adapter, off)); } else { netxen_nic_pci_change_crbwindow(adapter, 0); - addr = (void __iomem *)(pci_base_offset(adapter, off)); + addr = pci_base_offset(adapter, off); writel(data, addr); netxen_nic_pci_change_crbwindow(adapter, 1); } diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index cd1336e899b1..1cb662d5bd76 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -969,11 +969,9 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev) netxen_nic_disable_int(adapter); /* Window = 0 or 1 */ do { - writel(0xffffffff, (void __iomem *) - (PCI_OFFSET_SECOND_RANGE - (adapter, ISR_INT_TARGET_STATUS))); - mask = readl((void __iomem *) - pci_base_offset(adapter, ISR_INT_VECTOR)); + writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter, + ISR_INT_TARGET_STATUS)); + mask = readl(pci_base_offset(adapter, ISR_INT_VECTOR)); } while (((mask & 0x80) != 0) && (++count < 32)); if ((mask & 0x80) != 0) printk("Could not disable interrupt completely\n"); -- cgit v1.2.3 From aae343d493df965ac3abec1bd97cccfe44a7d920 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sat, 2 Dec 2006 07:14:39 -0500 Subject: [netdrvr] skge: build fix Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 010fc6541122..27b537c8d5e3 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2252,6 +2252,7 @@ static void skge_phy_reset(struct skge_port *skge) { struct skge_hw *hw = skge->hw; int port = skge->port; + struct net_device *dev = hw->dev[port]; netif_stop_queue(skge->netdev); netif_carrier_off(skge->netdev); -- cgit v1.2.3 From 90833aa4f496d69ca374af6acef7d1614c8693ff Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 13 Nov 2006 16:02:22 -0800 Subject: [NET]: The scheduled removal of the frame diverter. This patch contains the scheduled removal of the frame diverter. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 15 - drivers/net/Space.c | 1 - include/linux/Kbuild | 1 - include/linux/divert.h | 132 ------- include/linux/netdevice.h | 6 - include/linux/sockios.h | 4 +- net/Kconfig | 27 -- net/core/Makefile | 1 - net/core/dev.c | 20 +- net/core/dv.c | 546 ----------------------------- net/core/sysctl_net_core.c | 14 - net/socket.c | 6 - 12 files changed, 6 insertions(+), 767 deletions(-) delete mode 100644 include/linux/divert.h delete mode 100644 net/core/dv.c (limited to 'drivers') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d52c4aaaf17f..b3949cd3d013 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -227,21 +227,6 @@ Who: Patrick McHardy --------------------------- -What: frame diverter -When: November 2006 -Why: The frame diverter is included in most distribution kernels, but is - broken. It does not correctly handle many things: - - IPV6 - - non-linear skb's - - network device RCU on removal - - input frames not correctly checked for protocol errors - It also adds allocation overhead even if not enabled. - It is not clear if anyone is still using it. -Who: Stephen Hemminger - ---------------------------- - - What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment When: October 2008 Why: The stacking of class devices makes these values misleading and diff --git a/drivers/net/Space.c b/drivers/net/Space.c index a67f5efc983f..602ed31a5dd9 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -33,7 +33,6 @@ #include #include #include -#include /* A unified ethernet device probe. This is the easiest way to have every ethernet adaptor have the name "eth[0123...]". diff --git a/include/linux/Kbuild b/include/linux/Kbuild index a1155a2beb32..d7e04689304c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -193,7 +193,6 @@ unifdef-y += cuda.h unifdef-y += cyclades.h unifdef-y += dccp.h unifdef-y += dirent.h -unifdef-y += divert.h unifdef-y += dlm.h unifdef-y += elfcore.h unifdef-y += errno.h diff --git a/include/linux/divert.h b/include/linux/divert.h deleted file mode 100644 index 8fb4e9de6843..000000000000 --- a/include/linux/divert.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Frame Diversion, Benoit Locher - * - * Changes: - * 06/09/2000 BL: initial version - * - */ - -#ifndef _LINUX_DIVERT_H -#define _LINUX_DIVERT_H - -#include - -#define MAX_DIVERT_PORTS 8 /* Max number of ports to divert (tcp, udp) */ - -/* Divertable protocols */ -#define DIVERT_PROTO_NONE 0x0000 -#define DIVERT_PROTO_IP 0x0001 -#define DIVERT_PROTO_ICMP 0x0002 -#define DIVERT_PROTO_TCP 0x0004 -#define DIVERT_PROTO_UDP 0x0008 - -/* - * This is an Ethernet Frame Diverter option block - */ -struct divert_blk -{ - int divert; /* are we active */ - unsigned int protos; /* protocols */ - __u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */ - __u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */ - __u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */ - __u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */ -}; - -/* - * Diversion control block, for configuration with the userspace tool - * divert - */ - -typedef union _divert_cf_arg -{ - __s16 int16; - __u16 uint16; - __s32 int32; - __u32 uint32; - __s64 int64; - __u64 uint64; - void __user *ptr; -} divert_cf_arg; - - -struct divert_cf -{ - int cmd; /* Command */ - divert_cf_arg arg1, - arg2, - arg3; - int dev_index; /* device index (eth0=0, etc...) */ -}; - - -/* Diversion commands */ -#define DIVCMD_DIVERT 1 /* ENABLE/DISABLE diversion */ -#define DIVCMD_IP 2 /* ENABLE/DISABLE whold IP diversion */ -#define DIVCMD_TCP 3 /* ENABLE/DISABLE whold TCP diversion */ -#define DIVCMD_TCPDST 4 /* ADD/REMOVE TCP DST port for diversion */ -#define DIVCMD_TCPSRC 5 /* ADD/REMOVE TCP SRC port for diversion */ -#define DIVCMD_UDP 6 /* ENABLE/DISABLE whole UDP diversion */ -#define DIVCMD_UDPDST 7 /* ADD/REMOVE UDP DST port for diversion */ -#define DIVCMD_UDPSRC 8 /* ADD/REMOVE UDP SRC port for diversion */ -#define DIVCMD_ICMP 9 /* ENABLE/DISABLE whole ICMP diversion */ -#define DIVCMD_GETSTATUS 10 /* GET the status of the diverter */ -#define DIVCMD_RESET 11 /* Reset the diverter on the specified dev */ -#define DIVCMD_GETVERSION 12 /* Retrieve the diverter code version (char[32]) */ - -/* General syntax of the commands: - * - * DIVCMD_xxxxxx(arg1, arg2, arg3, dev_index) - * - * SIOCSIFDIVERT: - * DIVCMD_DIVERT(DIVARG1_ENABLE|DIVARG1_DISABLE, , ,ifindex) - * DIVCMD_IP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_TCP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_TCPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_TCPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_UDP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_UDPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_UDPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) - * DIVCMD_ICMP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) - * DIVCMD_RESET(, , , ifindex) - * - * SIOGIFDIVERT: - * DIVCMD_GETSTATUS(divert_blk, , , ifindex) - * DIVCMD_GETVERSION(string[3]) - */ - - -/* Possible values for arg1 */ -#define DIVARG1_ENABLE 0 /* ENABLE something */ -#define DIVARG1_DISABLE 1 /* DISABLE something */ -#define DIVARG1_ADD 2 /* ADD something */ -#define DIVARG1_REMOVE 3 /* REMOVE something */ - - -#ifdef __KERNEL__ - -/* diverter functions */ -#include - -#ifdef CONFIG_NET_DIVERT -#include - -int alloc_divert_blk(struct net_device *); -void free_divert_blk(struct net_device *); -int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg); -void divert_frame(struct sk_buff *skb); -static inline void handle_diverter(struct sk_buff *skb) -{ - /* if diversion is supported on device, then divert */ - if (skb->dev->divert && skb->dev->divert->divert) - divert_frame(skb); -} - -#else -# define alloc_divert_blk(dev) (0) -# define free_divert_blk(dev) do {} while (0) -# define divert_ioctl(cmd, arg) (-ENOPKG) -# define handle_diverter(skb) do {} while (0) -#endif -#endif -#endif /* _LINUX_DIVERT_H */ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 83b8c4f1d69d..4e967b2e22cc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -38,7 +38,6 @@ #include #include -struct divert_blk; struct vlan_group; struct ethtool_ops; struct netpoll_info; @@ -517,11 +516,6 @@ struct net_device /* bridge stuff */ struct net_bridge_port *br_port; -#ifdef CONFIG_NET_DIVERT - /* this will get initialized at each interface type init routine */ - struct divert_blk *divert; -#endif /* CONFIG_NET_DIVERT */ - /* class/net/name entry */ struct class_device class_dev; /* space for optional statistics and wireless sysfs groups */ diff --git a/include/linux/sockios.h b/include/linux/sockios.h index e6b9d1d36ea2..abef7596655a 100644 --- a/include/linux/sockios.h +++ b/include/linux/sockios.h @@ -72,8 +72,8 @@ #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ -#define SIOCGIFDIVERT 0x8944 /* Frame diversion support */ -#define SIOCSIFDIVERT 0x8945 /* Set frame diversion options */ +/* SIOCGIFDIVERT was: 0x8944 Frame diversion support */ +/* SIOCSIFDIVERT was: 0x8945 Set frame diversion options */ #define SIOCETHTOOL 0x8946 /* Ethtool interface */ diff --git a/net/Kconfig b/net/Kconfig index 67e39ad8b8b6..867f95032513 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -175,33 +175,6 @@ source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" - -config NET_DIVERT - bool "Frame Diverter (EXPERIMENTAL)" - depends on EXPERIMENTAL && BROKEN - ---help--- - The Frame Diverter allows you to divert packets from the - network, that are not aimed at the interface receiving it (in - promisc. mode). Typically, a Linux box setup as an Ethernet bridge - with the Frames Diverter on, can do some *really* transparent www - caching using a Squid proxy for example. - - This is very useful when you don't want to change your router's - config (or if you simply don't have access to it). - - The other possible usages of diverting Ethernet Frames are - numberous: - - reroute smtp traffic to another interface - - traffic-shape certain network streams - - transparently proxy smtp connections - - etc... - - For more informations, please refer to: - - - - If unsure, say N. - source "net/econet/Kconfig" source "net/wanrouter/Kconfig" source "net/sched/Kconfig" diff --git a/net/core/Makefile b/net/core/Makefile index 119568077dab..73272d506e93 100644 --- a/net/core/Makefile +++ b/net/core/Makefile @@ -12,7 +12,6 @@ obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ obj-$(CONFIG_XFRM) += flow.o obj-$(CONFIG_SYSFS) += net-sysfs.o -obj-$(CONFIG_NET_DIVERT) += dv.o obj-$(CONFIG_NET_PKTGEN) += pktgen.o obj-$(CONFIG_WIRELESS_EXT) += wireless.o obj-$(CONFIG_NETPOLL) += netpoll.o diff --git a/net/core/dev.c b/net/core/dev.c index 411c2428d268..5bf13b132dd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -98,7 +98,6 @@ #include #include #include -#include #include #include #include @@ -1827,8 +1826,6 @@ int netif_receive_skb(struct sk_buff *skb) ncls: #endif - handle_diverter(skb); - if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) goto out; @@ -2898,10 +2895,6 @@ int register_netdevice(struct net_device *dev) spin_lock_init(&dev->ingress_lock); #endif - ret = alloc_divert_blk(dev); - if (ret) - goto out; - dev->iflink = -1; /* Init, if this function is available */ @@ -2910,13 +2903,13 @@ int register_netdevice(struct net_device *dev) if (ret) { if (ret > 0) ret = -EIO; - goto out_err; + goto out; } } if (!dev_valid_name(dev->name)) { ret = -EINVAL; - goto out_err; + goto out; } dev->ifindex = dev_new_index(); @@ -2930,7 +2923,7 @@ int register_netdevice(struct net_device *dev) = hlist_entry(p, struct net_device, name_hlist); if (!strncmp(d->name, dev->name, IFNAMSIZ)) { ret = -EEXIST; - goto out_err; + goto out; } } @@ -2974,7 +2967,7 @@ int register_netdevice(struct net_device *dev) ret = netdev_register_sysfs(dev); if (ret) - goto out_err; + goto out; dev->reg_state = NETREG_REGISTERED; /* @@ -3001,9 +2994,6 @@ int register_netdevice(struct net_device *dev) out: return ret; -out_err: - free_divert_blk(dev); - goto out; } /** @@ -3320,8 +3310,6 @@ int unregister_netdevice(struct net_device *dev) /* Notifier chain MUST detach us from master device. */ BUG_TRAP(!dev->master); - free_divert_blk(dev); - /* Finish processing unregister after unlock */ net_set_todo(dev); diff --git a/net/core/dv.c b/net/core/dv.c deleted file mode 100644 index 29ee77f15932..000000000000 --- a/net/core/dv.c +++ /dev/null @@ -1,546 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * Generic frame diversion - * - * Authors: - * Benoit LOCHER: initial integration within the kernel with support for ethernet - * Dave Miller: improvement on the code (correctness, performance and source files) - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -const char sysctl_divert_version[32]="0.46"; /* Current version */ - -static int __init dv_init(void) -{ - return 0; -} -module_init(dv_init); - -/* - * Allocate a divert_blk for a device. This must be an ethernet nic. - */ -int alloc_divert_blk(struct net_device *dev) -{ - int alloc_size = (sizeof(struct divert_blk) + 3) & ~3; - - dev->divert = NULL; - if (dev->type == ARPHRD_ETHER) { - dev->divert = kzalloc(alloc_size, GFP_KERNEL); - if (dev->divert == NULL) { - printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", - dev->name); - return -ENOMEM; - } - dev_hold(dev); - } - - return 0; -} - -/* - * Free a divert_blk allocated by the above function, if it was - * allocated on that device. - */ -void free_divert_blk(struct net_device *dev) -{ - if (dev->divert) { - kfree(dev->divert); - dev->divert=NULL; - dev_put(dev); - } -} - -/* - * Adds a tcp/udp (source or dest) port to an array - */ -static int add_port(u16 ports[], u16 port) -{ - int i; - - if (port == 0) - return -EINVAL; - - /* Storing directly in network format for performance, - * thanks Dave :) - */ - port = htons(port); - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == port) - return -EALREADY; - } - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == 0) { - ports[i] = port; - return 0; - } - } - - return -ENOBUFS; -} - -/* - * Removes a port from an array tcp/udp (source or dest) - */ -static int remove_port(u16 ports[], u16 port) -{ - int i; - - if (port == 0) - return -EINVAL; - - /* Storing directly in network format for performance, - * thanks Dave ! - */ - port = htons(port); - - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - if (ports[i] == port) { - ports[i] = 0; - return 0; - } - } - - return -EINVAL; -} - -/* Some basic sanity checks on the arguments passed to divert_ioctl() */ -static int check_args(struct divert_cf *div_cf, struct net_device **dev) -{ - char devname[32]; - int ret; - - if (dev == NULL) - return -EFAULT; - - /* GETVERSION: all other args are unused */ - if (div_cf->cmd == DIVCMD_GETVERSION) - return 0; - - /* Network device index should reasonably be between 0 and 1000 :) */ - if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) - return -EINVAL; - - /* Let's try to find the ifname */ - sprintf(devname, "eth%d", div_cf->dev_index); - *dev = dev_get_by_name(devname); - - /* dev should NOT be null */ - if (*dev == NULL) - return -EINVAL; - - ret = 0; - - /* user issuing the ioctl must be a super one :) */ - if (!capable(CAP_SYS_ADMIN)) { - ret = -EPERM; - goto out; - } - - /* Device must have a divert_blk member NOT null */ - if ((*dev)->divert == NULL) - ret = -EINVAL; -out: - dev_put(*dev); - return ret; -} - -/* - * control function of the diverter - */ -#if 0 -#define DVDBG(a) \ - printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a)) -#else -#define DVDBG(a) -#endif - -int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg) -{ - struct divert_cf div_cf; - struct divert_blk *div_blk; - struct net_device *dev; - int ret; - - switch (cmd) { - case SIOCGIFDIVERT: - DVDBG("SIOCGIFDIVERT, copy_from_user"); - if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) - return -EFAULT; - DVDBG("before check_args"); - ret = check_args(&div_cf, &dev); - if (ret) - return ret; - DVDBG("after checkargs"); - div_blk = dev->divert; - - DVDBG("befre switch()"); - switch (div_cf.cmd) { - case DIVCMD_GETSTATUS: - /* Now, just give the user the raw divert block - * for him to play with :) - */ - if (copy_to_user(div_cf.arg1.ptr, dev->divert, - sizeof(struct divert_blk))) - return -EFAULT; - break; - - case DIVCMD_GETVERSION: - DVDBG("GETVERSION: checking ptr"); - if (div_cf.arg1.ptr == NULL) - return -EINVAL; - DVDBG("GETVERSION: copying data to userland"); - if (copy_to_user(div_cf.arg1.ptr, - sysctl_divert_version, 32)) - return -EFAULT; - DVDBG("GETVERSION: data copied"); - break; - - default: - return -EINVAL; - } - - break; - - case SIOCSIFDIVERT: - if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) - return -EFAULT; - - ret = check_args(&div_cf, &dev); - if (ret) - return ret; - - div_blk = dev->divert; - - switch(div_cf.cmd) { - case DIVCMD_RESET: - div_blk->divert = 0; - div_blk->protos = DIVERT_PROTO_NONE; - memset(div_blk->tcp_dst, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->tcp_src, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->udp_dst, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - memset(div_blk->udp_src, 0, - MAX_DIVERT_PORTS * sizeof(u16)); - return 0; - - case DIVCMD_DIVERT: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->divert) - return -EALREADY; - div_blk->divert = 1; - break; - - case DIVARG1_DISABLE: - if (!div_blk->divert) - return -EALREADY; - div_blk->divert = 0; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_IP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_IP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_IP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_IP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_IP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_TCP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_TCP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_TCP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_TCP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCPDST: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->tcp_dst, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->tcp_dst, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_TCPSRC: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->tcp_src, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->tcp_src, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_UDP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_UDP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_UDP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_UDP; - break; - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDPDST: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->udp_dst, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->udp_dst, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_UDPSRC: - switch(div_cf.arg1.int32) { - case DIVARG1_ADD: - return add_port(div_blk->udp_src, - div_cf.arg2.uint16); - - case DIVARG1_REMOVE: - return remove_port(div_blk->udp_src, - div_cf.arg2.uint16); - - default: - return -EINVAL; - } - - break; - - case DIVCMD_ICMP: - switch(div_cf.arg1.int32) { - case DIVARG1_ENABLE: - if (div_blk->protos & DIVERT_PROTO_ICMP) - return -EALREADY; - div_blk->protos |= DIVERT_PROTO_ICMP; - break; - - case DIVARG1_DISABLE: - if (!(div_blk->protos & DIVERT_PROTO_ICMP)) - return -EALREADY; - div_blk->protos &= ~DIVERT_PROTO_ICMP; - break; - - default: - return -EINVAL; - } - - break; - - default: - return -EINVAL; - } - - break; - - default: - return -EINVAL; - } - - return 0; -} - - -/* - * Check if packet should have its dest mac address set to the box itself - * for diversion - */ - -#define ETH_DIVERT_FRAME(skb) \ - memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \ - skb->pkt_type=PACKET_HOST - -void divert_frame(struct sk_buff *skb) -{ - struct ethhdr *eth = eth_hdr(skb); - struct iphdr *iph; - struct tcphdr *tcph; - struct udphdr *udph; - struct divert_blk *divert = skb->dev->divert; - int i, src, dst; - unsigned char *skb_data_end = skb->data + skb->len; - - /* Packet is already aimed at us, return */ - if (!compare_ether_addr(eth->h_dest, skb->dev->dev_addr)) - return; - - /* proto is not IP, do nothing */ - if (eth->h_proto != htons(ETH_P_IP)) - return; - - /* Divert all IP frames ? */ - if (divert->protos & DIVERT_PROTO_IP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP frame (thanks Dave) */ - iph = (struct iphdr *) skb->data; - if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) { - printk(KERN_INFO "divert: malformed IP packet !\n"); - return; - } - - switch (iph->protocol) { - /* Divert all ICMP frames ? */ - case IPPROTO_ICMP: - if (divert->protos & DIVERT_PROTO_ICMP) { - ETH_DIVERT_FRAME(skb); - return; - } - break; - - /* Divert all TCP frames ? */ - case IPPROTO_TCP: - if (divert->protos & DIVERT_PROTO_TCP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP - * frame (thanx Dave) - */ - tcph = (struct tcphdr *) - (((unsigned char *)iph) + (iph->ihl<<2)); - if (((unsigned char *)(tcph+1)) >= skb_data_end) { - printk(KERN_INFO "divert: malformed TCP packet !\n"); - return; - } - - /* Divert some tcp dst/src ports only ?*/ - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - dst = divert->tcp_dst[i]; - src = divert->tcp_src[i]; - if ((dst && dst == tcph->dest) || - (src && src == tcph->source)) { - ETH_DIVERT_FRAME(skb); - return; - } - } - break; - - /* Divert all UDP frames ? */ - case IPPROTO_UDP: - if (divert->protos & DIVERT_PROTO_UDP) { - ETH_DIVERT_FRAME(skb); - return; - } - - /* Check for possible (maliciously) malformed IP - * packet (thanks Dave) - */ - udph = (struct udphdr *) - (((unsigned char *)iph) + (iph->ihl<<2)); - if (((unsigned char *)(udph+1)) >= skb_data_end) { - printk(KERN_INFO - "divert: malformed UDP packet !\n"); - return; - } - - /* Divert some udp dst/src ports only ? */ - for (i = 0; i < MAX_DIVERT_PORTS; i++) { - dst = divert->udp_dst[i]; - src = divert->udp_src[i]; - if ((dst && dst == udph->dest) || - (src && src == udph->source)) { - ETH_DIVERT_FRAME(skb); - return; - } - } - break; - } -} diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 02534131d88e..1e75b1585460 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -21,10 +21,6 @@ extern __u32 sysctl_rmem_max; extern int sysctl_core_destroy_delay; -#ifdef CONFIG_NET_DIVERT -extern char sysctl_divert_version[]; -#endif /* CONFIG_NET_DIVERT */ - #ifdef CONFIG_XFRM extern u32 sysctl_xfrm_aevent_etime; extern u32 sysctl_xfrm_aevent_rseqth; @@ -105,16 +101,6 @@ ctl_table core_table[] = { .mode = 0644, .proc_handler = &proc_dointvec }, -#ifdef CONFIG_NET_DIVERT - { - .ctl_name = NET_CORE_DIVERT_VERSION, - .procname = "divert_version", - .data = (void *)sysctl_divert_version, - .maxlen = 32, - .mode = 0444, - .proc_handler = &proc_dostring - }, -#endif /* CONFIG_NET_DIVERT */ #ifdef CONFIG_XFRM { .ctl_name = NET_CORE_AEVENT_ETIME, diff --git a/net/socket.c b/net/socket.c index 6c9b9b326d76..e8db54702a69 100644 --- a/net/socket.c +++ b/net/socket.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include @@ -852,11 +851,6 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) err = vlan_ioctl_hook(argp); mutex_unlock(&vlan_ioctl_mutex); break; - case SIOCGIFDIVERT: - case SIOCSIFDIVERT: - /* Convert this to call through a hook */ - err = divert_ioctl(cmd, argp); - break; case SIOCADDDLCI: case SIOCDELDLCI: err = -ENOPKG; -- cgit v1.2.3 From 5f3f24faf322e54752d1df00cdb768a013de5d1f Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 13 Nov 2006 16:12:08 -0800 Subject: [ATM] ambassador,firestream: "-1 >>" is implementation defined 6.5.7(5): The result of E1 >> E2 is E1 right-shifted E2 bit positions. ... If E1 has a signed type and a negative value, the resulting value is implementation defined. So, cast -1 to unsigned type to make result well-defined. [ Modified to use ~0U based upon recommendation from Al Viro. -DaveM ] Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- drivers/atm/ambassador.c | 2 +- drivers/atm/firestream.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index 9fffa7af6db1..afa7d750a593 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -972,7 +972,7 @@ static int make_rate (unsigned int rate, rounding r, } case round_up: { // check all bits that we are discarding - if (man & (-1>>9)) { + if (man & (~0U>>9)) { man = (man>>(32-9)) + 1; if (man == (1<<9)) { // no need to check for round up outside of range diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 697ad82f6634..9c67df5ccfa4 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -512,7 +512,7 @@ static unsigned int make_rate (unsigned int rate, int r, } case ROUND_UP: { /* check all bits that we are discarding */ - if (man & (-1>>9)) { + if (man & (~0U>>9)) { man = (man>>(32-9)) + 1; if (man == (1<<9)) { /* no need to check for round up outside of range */ -- cgit v1.2.3 From b41848b61bae30e3661efd4ec62ea380cedef687 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:52 -0700 Subject: netpoll setup error handling The beast was not always healthy. When it was sick, it tended to be laconic and not tell anyone the real problem. A few small changes had it telling the world about its problems, if they really wanted to hear. Signed-off-by: Stephen Hemminger --- drivers/net/netconsole.c | 7 +++++-- net/core/netpoll.c | 20 +++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index bf58db29e2ed..e6e8a9797b6d 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -102,6 +102,8 @@ __setup("netconsole=", option_setup); static int init_netconsole(void) { + int err; + if(strlen(config)) option_setup(config); @@ -110,8 +112,9 @@ static int init_netconsole(void) return 0; } - if(netpoll_setup(&np)) - return -EINVAL; + err = netpoll_setup(&np); + if (err) + return err; register_console(&netconsole); printk(KERN_INFO "netconsole: network logging started\n"); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index ac4e8b8f57d1..621baa5da49f 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -611,20 +611,23 @@ int netpoll_setup(struct netpoll *np) struct in_device *in_dev; struct netpoll_info *npinfo; unsigned long flags; + int err; if (np->dev_name) ndev = dev_get_by_name(np->dev_name); if (!ndev) { printk(KERN_ERR "%s: %s doesn't exist, aborting.\n", np->name, np->dev_name); - return -1; + return -ENODEV; } np->dev = ndev; if (!ndev->npinfo) { npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); - if (!npinfo) + if (!npinfo) { + err = -ENOMEM; goto release; + } npinfo->rx_flags = 0; npinfo->rx_np = NULL; @@ -645,6 +648,7 @@ int netpoll_setup(struct netpoll *np) if (!ndev->poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", np->name, np->dev_name); + err = -ENOTSUPP; goto release; } @@ -655,13 +659,14 @@ int netpoll_setup(struct netpoll *np) np->name, np->dev_name); rtnl_lock(); - if (dev_change_flags(ndev, ndev->flags | IFF_UP) < 0) { + err = dev_open(ndev); + rtnl_unlock(); + + if (err) { printk(KERN_ERR "%s: failed to open %s\n", - np->name, np->dev_name); - rtnl_unlock(); + np->name, ndev->name); goto release; } - rtnl_unlock(); atleast = jiffies + HZ/10; atmost = jiffies + 4*HZ; @@ -699,6 +704,7 @@ int netpoll_setup(struct netpoll *np) rcu_read_unlock(); printk(KERN_ERR "%s: no IP address for %s, aborting\n", np->name, np->dev_name); + err = -EDESTADDRREQ; goto release; } @@ -731,7 +737,7 @@ int netpoll_setup(struct netpoll *np) kfree(npinfo); np->dev = NULL; dev_put(ndev); - return -1; + return err; } static int __init netpoll_init(void) { -- cgit v1.2.3 From 5de4a473bda49554e4e9bd93b78f43c49a7ea69c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 26 Oct 2006 15:46:55 -0700 Subject: netpoll queue cleanup The beast had a long and not very happy history. At one point, a friend (netdump) had asked that he open up a little. Well, the friend was long gone now, and the beast had this dangling piece hanging (netpoll_queue). It wasn't hard to stitch the netpoll_queue back in where it belonged and make everything tidy. Signed-off-by: Stephen Hemminger --- drivers/net/netconsole.c | 1 - include/linux/netpoll.h | 4 ++-- net/core/netpoll.c | 23 +++-------------------- 3 files changed, 5 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index e6e8a9797b6d..69233f6aa05c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -60,7 +60,6 @@ static struct netpoll np = { .local_port = 6665, .remote_port = 6666, .remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - .drop = netpoll_queue, }; static int configured = 0; diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h index c65d12ec7bb0..b7eb008c43de 100644 --- a/include/linux/netpoll.h +++ b/include/linux/netpoll.h @@ -18,7 +18,7 @@ struct netpoll { struct net_device *dev; char dev_name[16], *name; void (*rx_hook)(struct netpoll *, int, char *, int); - void (*drop)(struct sk_buff *skb); + u32 local_ip, remote_ip; u16 local_port, remote_port; unsigned char local_mac[6], remote_mac[6]; @@ -44,7 +44,7 @@ int netpoll_trap(void); void netpoll_set_trap(int trap); void netpoll_cleanup(struct netpoll *np); int __netpoll_rx(struct sk_buff *skb); -void netpoll_queue(struct sk_buff *skb); + #ifdef CONFIG_NETPOLL static inline int netpoll_rx(struct sk_buff *skb) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6b34c394672f..0d1de3c47a01 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -77,19 +77,6 @@ static void queue_process(void *p) } } -void netpoll_queue(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct netpoll_info *npinfo = dev->npinfo; - - if (!npinfo) - kfree_skb(skb); - else { - skb_queue_tail(&npinfo->txq, skb); - schedule_work(&npinfo->tx_work); - } -} - static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, u32 saddr, u32 daddr) { @@ -256,7 +243,7 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } /* don't get messages out of order, and no recursion */ - if ( !(np->drop == netpoll_queue && skb_queue_len(&npinfo->txq)) + if ( skb_queue_len(&npinfo->txq) == 0 && npinfo->poll_owner != smp_processor_id() && netif_tx_trylock(dev)) { @@ -277,11 +264,8 @@ static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb) } if (status != NETDEV_TX_OK) { - /* requeue for later */ - if (np->drop) - np->drop(skb); - else - __kfree_skb(skb); + skb_queue_tail(&npinfo->txq, skb); + schedule_work(&npinfo->tx_work); } } @@ -809,4 +793,3 @@ EXPORT_SYMBOL(netpoll_setup); EXPORT_SYMBOL(netpoll_cleanup); EXPORT_SYMBOL(netpoll_send_udp); EXPORT_SYMBOL(netpoll_poll); -EXPORT_SYMBOL(netpoll_queue); -- cgit v1.2.3 From b09b845ca6724c3bbdc00c0cb2313258c7189ca9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 20:52:19 -0800 Subject: [RANDOM]: Annotate random.h IP helpers. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/char/random.c | 48 ++++++++++++++++++++++++------------------------ include/linux/random.h | 20 ++++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index eb6b13f4211a..d40df30c2b10 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1466,8 +1466,8 @@ static __init int seqgen_init(void) late_initcall(seqgen_init); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -__u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, - __u16 sport, __u16 dport) +__u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport) { struct timeval tv; __u32 seq; @@ -1479,10 +1479,10 @@ __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, */ memcpy(hash, saddr, 16); - hash[4]=(sport << 16) + dport; + hash[4]=((__force u16)sport << 16) + (__force u16)dport; memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7); - seq = twothirdsMD4Transform(daddr, hash) & HASH_MASK; + seq = twothirdsMD4Transform((const __u32 *)daddr, hash) & HASH_MASK; seq += keyptr->count; do_gettimeofday(&tv); @@ -1496,7 +1496,7 @@ EXPORT_SYMBOL(secure_tcpv6_sequence_number); /* The code below is shamelessly stolen from secure_tcp_sequence_number(). * All blames to Andrey V. Savochkin . */ -__u32 secure_ip_id(__u32 daddr) +__u32 secure_ip_id(__be32 daddr) { struct keydata *keyptr; __u32 hash[4]; @@ -1508,7 +1508,7 @@ __u32 secure_ip_id(__u32 daddr) * The dest ip address is placed in the starting vector, * which is then hashed with random data. */ - hash[0] = daddr; + hash[0] = (__force __u32)daddr; hash[1] = keyptr->secret[9]; hash[2] = keyptr->secret[10]; hash[3] = keyptr->secret[11]; @@ -1518,8 +1518,8 @@ __u32 secure_ip_id(__u32 daddr) #ifdef CONFIG_INET -__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, - __u16 sport, __u16 dport) +__u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) { struct timeval tv; __u32 seq; @@ -1532,9 +1532,9 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, * Note that the words are placed into the starting vector, which is * then mixed with a partial MD4 over random data. */ - hash[0]=saddr; - hash[1]=daddr; - hash[2]=(sport << 16) + dport; + hash[0]=(__force u32)saddr; + hash[1]=(__force u32)daddr; + hash[2]=((__force u16)sport << 16) + (__force u16)dport; hash[3]=keyptr->secret[11]; seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK; @@ -1559,7 +1559,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, EXPORT_SYMBOL(secure_tcp_sequence_number); /* Generate secure starting point for ephemeral IPV4 transport port search */ -u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport) +u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) { struct keydata *keyptr = get_keyptr(); u32 hash[4]; @@ -1568,25 +1568,25 @@ u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport) * Pick a unique starting offset for each ephemeral port search * (saddr, daddr, dport) and 48bits of random data. */ - hash[0] = saddr; - hash[1] = daddr; - hash[2] = dport ^ keyptr->secret[10]; + hash[0] = (__force u32)saddr; + hash[1] = (__force u32)daddr; + hash[2] = (__force u32)dport ^ keyptr->secret[10]; hash[3] = keyptr->secret[11]; return half_md4_transform(hash, keyptr->secret); } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) -u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport) +u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, __be16 dport) { struct keydata *keyptr = get_keyptr(); u32 hash[12]; memcpy(hash, saddr, 16); - hash[4] = dport; + hash[4] = (__force u32)dport; memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7); - return twothirdsMD4Transform(daddr, hash); + return twothirdsMD4Transform((const __u32 *)daddr, hash); } #endif @@ -1595,17 +1595,17 @@ u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dpo * bit's 32-47 increase every key exchange * 0-31 hash(source, dest) */ -u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr, - __u16 sport, __u16 dport) +u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport) { struct timeval tv; u64 seq; __u32 hash[4]; struct keydata *keyptr = get_keyptr(); - hash[0] = saddr; - hash[1] = daddr; - hash[2] = (sport << 16) + dport; + hash[0] = (__force u32)saddr; + hash[1] = (__force u32)daddr; + hash[2] = ((__force u16)sport << 16) + (__force u16)dport; hash[3] = keyptr->secret[11]; seq = half_md4_transform(hash, keyptr->secret); @@ -1641,7 +1641,7 @@ unsigned int get_random_int(void) * drain on it), and uses halfMD4Transform within the second. We * also mix it with jiffies and the PID: */ - return secure_ip_id(current->pid + jiffies); + return secure_ip_id((__force __be32)(current->pid + jiffies)); } /* diff --git a/include/linux/random.h b/include/linux/random.h index 0248b30e306d..01ad71033d65 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -51,16 +51,16 @@ extern void add_interrupt_randomness(int irq); extern void get_random_bytes(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); -extern __u32 secure_ip_id(__u32 daddr); -extern u32 secure_ipv4_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport); -extern u32 secure_ipv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, - __u16 dport); -extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr, - __u16 sport, __u16 dport); -extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr, - __u16 sport, __u16 dport); -extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr, - __u16 sport, __u16 dport); +extern __u32 secure_ip_id(__be32 daddr); +extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); +extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, + __be16 dport); +extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); +extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr, + __be16 sport, __be16 dport); +extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr, + __be16 sport, __be16 dport); #ifndef MODULE extern struct file_operations random_fops, urandom_fops; -- cgit v1.2.3 From 3277c39f8d706afb6fefc02f49563a73bbd405b9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:13:53 -0800 Subject: [NET]: Kill direct includes of asm/checksum.h Signed-off-by: Al Viro Signed-off-by: David S. Miller --- arch/frv/lib/checksum.c | 1 - arch/sh/kernel/sh_ksyms.c | 1 - drivers/net/ioc3-eth.c | 1 - drivers/net/meth.c | 1 - drivers/net/myri_sbus.c | 1 - drivers/net/typhoon.c | 1 - fs/reiserfs/xattr.c | 2 +- net/802/hippi.c | 1 - net/bridge/br_netfilter.c | 1 - net/ethernet/eth.c | 1 - net/rxrpc/transport.c | 1 - 11 files changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers') diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c index 20e7dfc474ef..2581a960d58f 100644 --- a/arch/frv/lib/checksum.c +++ b/arch/frv/lib/checksum.c @@ -32,7 +32,6 @@ of the assembly has to go. */ #include -#include #include static inline unsigned short from32to16(unsigned long x) diff --git a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c index 9daad70bc305..8a2fd19dc9eb 100644 --- a/arch/sh/kernel/sh_ksyms.c +++ b/arch/sh/kernel/sh_ksyms.c @@ -18,7 +18,6 @@ #include #include #include -#include extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c index f56b00ee385e..f0d30cf67b5f 100644 --- a/drivers/net/ioc3-eth.c +++ b/drivers/net/ioc3-eth.c @@ -57,7 +57,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/meth.c b/drivers/net/meth.c index c1aa60b9a982..e1d97cdf649e 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c @@ -33,7 +33,6 @@ #include #include -#include #include #include diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 7747bfd99f91..ee26ef52289f 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c @@ -39,7 +39,6 @@ static char version[] = #include #include #include -#include #include "myri_sbus.h" #include "myri_code.h" diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 3bf9e630404f..8ddea1da7c05 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -127,7 +127,6 @@ static const int multicast_filter_limit = 32; #include #include #include -#include #include #include diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 7bdb0ed443e1..1e4d68590178 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/net/802/hippi.c b/net/802/hippi.c index 6d7fed3dd99a..579e2ddf5ebe 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c @@ -36,7 +36,6 @@ #include #include #include -#include #include /* diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 2a5d31b1a196..ac47ba2ba028 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -40,7 +40,6 @@ #include #include -#include #include "br_private.h" #ifdef CONFIG_SYSCTL #include diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 4bd78c8cfb26..2d31bf3f05c5 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -60,7 +60,6 @@ #include #include #include -#include __setup("ether=", netdev_boot_setup); diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c index 94b2e2fe6fdb..4268b38d92d2 100644 --- a/net/rxrpc/transport.c +++ b/net/rxrpc/transport.c @@ -31,7 +31,6 @@ #endif #include #include -#include #include "internal.h" struct errormsg { -- cgit v1.2.3 From 5a5a852e45b651c71dfeb3972b30d58742f8941e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 14 Nov 2006 21:43:44 -0800 Subject: [NET] driver/s390/net: Checksum annotations. Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/s390/net/lcs.c | 2 +- drivers/s390/net/lcs.h | 4 ++-- drivers/s390/net/qeth_eddp.c | 40 ++++++++++++++++++++-------------------- drivers/s390/net/qeth_eddp.h | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 16ac68c27a27..66a8aec6efa6 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1147,7 +1147,7 @@ list_modified: * get mac address for the relevant Multicast address */ static void -lcs_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev) +lcs_get_mac_for_ipm(__be32 ipm, char *mac, struct net_device *dev) { LCS_DBF_TEXT(4,trace, "getmac"); if (dev->type == ARPHRD_IEEE802_TR) diff --git a/drivers/s390/net/lcs.h b/drivers/s390/net/lcs.h index 93143932983b..b5247dc08b57 100644 --- a/drivers/s390/net/lcs.h +++ b/drivers/s390/net/lcs.h @@ -169,7 +169,7 @@ struct lcs_header { } __attribute__ ((packed)); struct lcs_ip_mac_pair { - __u32 ip_addr; + __be32 ip_addr; __u8 mac_addr[LCS_MAC_LENGTH]; __u8 reserved[2]; } __attribute__ ((packed)); @@ -287,7 +287,7 @@ struct lcs_card { enum lcs_dev_states state; struct net_device *dev; struct net_device_stats stats; - unsigned short (*lan_type_trans)(struct sk_buff *skb, + __be16 (*lan_type_trans)(struct sk_buff *skb, struct net_device *dev); struct ccwgroup_device *gdev; struct lcs_channel read; diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c index a363721cf28d..6bb558a9a032 100644 --- a/drivers/s390/net/qeth_eddp.c +++ b/drivers/s390/net/qeth_eddp.c @@ -258,7 +258,7 @@ qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx, static inline void qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, - u32 *hcsum) + __wsum *hcsum) { struct skb_frag_struct *frag; int left_in_frag; @@ -305,7 +305,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len, static inline void qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, struct qeth_eddp_data *eddp, int data_len, - u32 hcsum) + __wsum hcsum) { u8 *page; int page_remainder; @@ -349,10 +349,10 @@ qeth_eddp_create_segment_data_tcp(struct qeth_eddp_context *ctx, ((struct tcphdr *)eddp->th_in_ctx)->check = csum_fold(hcsum); } -static inline u32 +static inline __wsum qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) { - u32 phcsum; /* pseudo header checksum */ + __wsum phcsum; /* pseudo header checksum */ QETH_DBF_TEXT(trace, 5, "eddpckt4"); eddp->th.tcp.h.check = 0; @@ -363,11 +363,11 @@ qeth_eddp_check_tcp4_hdr(struct qeth_eddp_data *eddp, int data_len) return csum_partial((u8 *)&eddp->th, eddp->thl, phcsum); } -static inline u32 +static inline __wsum qeth_eddp_check_tcp6_hdr(struct qeth_eddp_data *eddp, int data_len) { - u32 proto; - u32 phcsum; /* pseudo header checksum */ + __be32 proto; + __wsum phcsum; /* pseudo header checksum */ QETH_DBF_TEXT(trace, 5, "eddpckt6"); eddp->th.tcp.h.check = 0; @@ -405,7 +405,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, { struct tcphdr *tcph; int data_len; - u32 hcsum; + __wsum hcsum; QETH_DBF_TEXT(trace, 5, "eddpftcp"); eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl; @@ -433,22 +433,22 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, eddp->qh.hdr.l3.length = data_len + eddp->nhl + eddp->thl; /* prepare ip hdr */ - if (eddp->skb->protocol == ETH_P_IP){ - eddp->nh.ip4.h.tot_len = data_len + eddp->nhl + - eddp->thl; + if (eddp->skb->protocol == htons(ETH_P_IP)){ + eddp->nh.ip4.h.tot_len = htons(data_len + eddp->nhl + + eddp->thl); eddp->nh.ip4.h.check = 0; eddp->nh.ip4.h.check = ip_fast_csum((u8 *)&eddp->nh.ip4.h, eddp->nh.ip4.h.ihl); } else - eddp->nh.ip6.h.payload_len = data_len + eddp->thl; + eddp->nh.ip6.h.payload_len = htons(data_len + eddp->thl); /* prepare tcp hdr */ if (data_len == (eddp->skb->len - eddp->skb_offset)){ /* last segment -> set FIN and PSH flags */ eddp->th.tcp.h.fin = tcph->fin; eddp->th.tcp.h.psh = tcph->psh; } - if (eddp->skb->protocol == ETH_P_IP) + if (eddp->skb->protocol == htons(ETH_P_IP)) hcsum = qeth_eddp_check_tcp4_hdr(eddp, data_len); else hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len); @@ -458,9 +458,9 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, if (eddp->skb_offset >= eddp->skb->len) break; /* prepare headers for next round */ - if (eddp->skb->protocol == ETH_P_IP) - eddp->nh.ip4.h.id++; - eddp->th.tcp.h.seq += data_len; + if (eddp->skb->protocol == htons(ETH_P_IP)) + eddp->nh.ip4.h.id = htons(ntohs(eddp->nh.ip4.h.id) + 1); + eddp->th.tcp.h.seq = htonl(ntohl(eddp->th.tcp.h.seq) + data_len); } } @@ -472,7 +472,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, QETH_DBF_TEXT(trace, 5, "eddpficx"); /* create our segmentation headers and copy original headers */ - if (skb->protocol == ETH_P_IP) + if (skb->protocol == htons(ETH_P_IP)) eddp = qeth_eddp_create_eddp_data(qhdr, (u8 *)skb->nh.iph, skb->nh.iph->ihl*4, (u8 *)skb->h.th, skb->h.th->doff*4); @@ -490,7 +490,7 @@ qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx, memcpy(&eddp->mac, eth_hdr(skb), ETH_HLEN); #ifdef CONFIG_QETH_VLAN if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q)) { - eddp->vlan[0] = __constant_htons(skb->protocol); + eddp->vlan[0] = skb->protocol; eddp->vlan[1] = htons(vlan_tx_tag_get(skb)); } #endif /* CONFIG_QETH_VLAN */ @@ -588,11 +588,11 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb, struct qeth_eddp_context *ctx = NULL; QETH_DBF_TEXT(trace, 5, "creddpct"); - if (skb->protocol == ETH_P_IP) + if (skb->protocol == htons(ETH_P_IP)) ctx = qeth_eddp_create_context_generic(card, skb, sizeof(struct qeth_hdr) + skb->nh.iph->ihl*4 + skb->h.th->doff*4); - else if (skb->protocol == ETH_P_IPV6) + else if (skb->protocol == htons(ETH_P_IPV6)) ctx = qeth_eddp_create_context_generic(card, skb, sizeof(struct qeth_hdr) + sizeof(struct ipv6hdr) + skb->h.th->doff*4); diff --git a/drivers/s390/net/qeth_eddp.h b/drivers/s390/net/qeth_eddp.h index cae9ba265056..103768d3bab2 100644 --- a/drivers/s390/net/qeth_eddp.h +++ b/drivers/s390/net/qeth_eddp.h @@ -54,7 +54,7 @@ qeth_eddp_check_buffers_for_context(struct qeth_qdio_out_q *, struct qeth_eddp_data { struct qeth_hdr qh; struct ethhdr mac; - u16 vlan[2]; + __be16 vlan[2]; union { struct { struct iphdr h; -- cgit v1.2.3 From 58a5a7b9555ea231b557ebef5cabeaf8e951df0b Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 16 Nov 2006 14:06:06 -0200 Subject: [NET]: Conditionally use bh_lock_sock_nested in sk_receive_skb Spotted by Ian McDonald, tentatively fixed by Gerrit Renker: http://www.mail-archive.com/dccp%40vger.kernel.org/msg00599.html Rewritten not to unroll sk_receive_skb, in the common case, i.e. no lock debugging, its optimized away. Signed-off-by: Arnaldo Carvalho de Melo --- drivers/net/pppoe.c | 2 +- include/net/sock.h | 3 ++- net/core/sock.c | 7 +++++-- net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 2 +- net/decnet/dn_nsp_in.c | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 0adee733b761..315d5c3fc66a 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -393,7 +393,7 @@ static int pppoe_rcv(struct sk_buff *skb, po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source); if (po != NULL) - return sk_receive_skb(sk_pppox(po), skb); + return sk_receive_skb(sk_pppox(po), skb, 0); drop: kfree_skb(skb); out: diff --git a/include/net/sock.h b/include/net/sock.h index dc4b92b8abea..26fc0b16bc0c 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -954,7 +954,8 @@ static inline void sock_put(struct sock *sk) sk_free(sk); } -extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb); +extern int sk_receive_skb(struct sock *sk, struct sk_buff *skb, + const int nested); /* Detach socket from process context. * Announce socket dead, detach it from wait queue and inode. diff --git a/net/core/sock.c b/net/core/sock.c index 32ff1c551d69..ab8fafadb4ba 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -270,7 +270,7 @@ out: } EXPORT_SYMBOL(sock_queue_rcv_skb); -int sk_receive_skb(struct sock *sk, struct sk_buff *skb) +int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) { int rc = NET_RX_SUCCESS; @@ -279,7 +279,10 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb) skb->dev = NULL; - bh_lock_sock(sk); + if (nested) + bh_lock_sock_nested(sk); + else + bh_lock_sock(sk); if (!sock_owned_by_user(sk)) { /* * trylock + unlock semantics: diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index a20eb71d45db..7114befe7d50 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -899,7 +899,7 @@ static int dccp_v4_rcv(struct sk_buff *skb) goto discard_and_relse; nf_reset(skb); - return sk_receive_skb(sk, skb); + return sk_receive_skb(sk, skb, 1); no_dccp_socket: if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 6eda430ae929..03bb8298250a 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -888,7 +888,7 @@ static int dccp_v6_rcv(struct sk_buff **pskb) if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) goto discard_and_relse; - return sk_receive_skb(sk, skb) ? -1 : 0; + return sk_receive_skb(sk, skb, 1) ? -1 : 0; no_dccp_socket: if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index 7683d4f754d2..39a6cf7fb566 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -804,7 +804,7 @@ got_it: goto free_out; } - return sk_receive_skb(sk, skb); + return sk_receive_skb(sk, skb, 0); } return dn_nsp_no_socket(skb, reason); -- cgit v1.2.3 From 7510873d8659f4192cb5b3327f748e401d216399 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:06:40 -0800 Subject: [BNX2]: Fix Xen problem. This fixes the problem of not receiving packets in the Xen bridging environment. The Xen script sets the device's MAC address to FE:FF:FF:FF:FF:FF and puts the device in promiscuous mode. The firmware had problem receiving all packets in this configuration. New firmware and setting the PROM_VLAN bit when in promiscuous mode will fix this problem. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 3 +- drivers/net/bnx2_fw.h | 1069 +++++++++++++++++++++++++++++++------------------ 2 files changed, 691 insertions(+), 381 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 01b76d3aa42f..b60e45d1ce3d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -2040,7 +2040,8 @@ bnx2_set_rx_mode(struct net_device *dev) if (dev->flags & IFF_PROMISC) { /* Promiscuous mode. */ rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS; - sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN; + sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN | + BNX2_RPM_SORT_USER0_PROM_VLAN; } else if (dev->flags & IFF_ALLMULTI) { for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) { diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index 2d753dca0d75..4adc8de30631 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -673,389 +673,698 @@ static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = { static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 }; static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; -static int bnx2_RXP_b06FwReleaseMajor = 0x1; -static int bnx2_RXP_b06FwReleaseMinor = 0x0; -static int bnx2_RXP_b06FwReleaseFix = 0x0; -static u32 bnx2_RXP_b06FwStartAddr = 0x08003184; -static u32 bnx2_RXP_b06FwTextAddr = 0x08000000; -static int bnx2_RXP_b06FwTextLen = 0x588c; -static u32 bnx2_RXP_b06FwDataAddr = 0x080058e0; -static int bnx2_RXP_b06FwDataLen = 0x0; -static u32 bnx2_RXP_b06FwRodataAddr = 0x08005890; -static int bnx2_RXP_b06FwRodataLen = 0x28; -static u32 bnx2_RXP_b06FwBssAddr = 0x08005900; -static int bnx2_RXP_b06FwBssLen = 0x13a4; -static u32 bnx2_RXP_b06FwSbssAddr = 0x080058e0; -static int bnx2_RXP_b06FwSbssLen = 0x1c; +static const int bnx2_RXP_b06FwReleaseMajor = 0x2; +static const int bnx2_RXP_b06FwReleaseMinor = 0x8; +static const int bnx2_RXP_b06FwReleaseFix = 0x17; +static const u32 bnx2_RXP_b06FwStartAddr = 0x08003184; +static const u32 bnx2_RXP_b06FwTextAddr = 0x08000000; +static const int bnx2_RXP_b06FwTextLen = 0x6728; +static const u32 bnx2_RXP_b06FwDataAddr = 0x080069c0; +static const int bnx2_RXP_b06FwDataLen = 0x0; +static const u32 bnx2_RXP_b06FwRodataAddr = 0x08006728; +static const int bnx2_RXP_b06FwRodataLen = 0x278; +static const u32 bnx2_RXP_b06FwBssAddr = 0x080069f0; +static const int bnx2_RXP_b06FwBssLen = 0x13dc; +static const u32 bnx2_RXP_b06FwSbssAddr = 0x080069c0; +static const int bnx2_RXP_b06FwSbssLen = 0x2c; static u8 bnx2_RXP_b06FwText[] = { - 0x1f, 0x8b, 0x08, 0x08, 0x07, 0x87, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, - 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x5d, 0x6c, - 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x43, 0x71, 0x49, 0x91, 0xd4, 0x70, 0xb9, - 0x62, 0x57, 0x12, 0x65, 0xed, 0x8a, 0x43, 0x71, 0x6d, 0x31, 0xce, 0x50, - 0x58, 0xdb, 0x82, 0xb1, 0x48, 0xc7, 0xb3, 0xa4, 0xc8, 0x24, 0x02, 0x42, - 0x1b, 0x42, 0xab, 0xa4, 0xa9, 0xc1, 0x90, 0x72, 0x91, 0x22, 0x2c, 0xa0, - 0x1a, 0x79, 0xf0, 0x43, 0x10, 0x2f, 0x56, 0x3f, 0xa6, 0xd1, 0x8d, 0x96, - 0xb6, 0x1c, 0x53, 0x08, 0x82, 0x82, 0xe5, 0x52, 0x52, 0x0b, 0x2c, 0xb4, - 0x96, 0xed, 0x36, 0x7e, 0xa8, 0x23, 0x9a, 0x92, 0x8d, 0xa6, 0x68, 0x81, - 0x22, 0xad, 0xd1, 0xf4, 0x4d, 0x95, 0x9a, 0x4a, 0x75, 0x5f, 0xd4, 0xa2, - 0x48, 0xda, 0x46, 0xcd, 0xf4, 0xfb, 0xee, 0xcc, 0x88, 0xd4, 0x9a, 0xb2, - 0x2c, 0x3b, 0x0d, 0x62, 0x74, 0x0e, 0x30, 0xd8, 0xb9, 0x7f, 0xe7, 0xef, - 0x9e, 0x73, 0xee, 0x39, 0x77, 0x28, 0x7d, 0xa5, 0x43, 0xda, 0x25, 0x84, - 0x4e, 0x3c, 0x99, 0xc3, 0xcf, 0x3c, 0xfd, 0xe0, 0xc3, 0x0f, 0xee, 0xc1, - 0xeb, 0xb0, 0xa1, 0x6d, 0xd0, 0xa3, 0xfe, 0x18, 0x62, 0x88, 0x21, 0x86, - 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, - 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, - 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, - 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0x18, 0x62, 0x88, - 0x21, 0x86, 0x18, 0x62, 0x88, 0x21, 0x86, 0xff, 0xef, 0x60, 0x88, 0x58, - 0xfc, 0xed, 0x0c, 0x1f, 0x49, 0xe8, 0x85, 0xcb, 0x07, 0x3d, 0x5b, 0x12, - 0x46, 0x61, 0x69, 0x66, 0xda, 0x16, 0x71, 0xeb, 0xbb, 0x33, 0x45, 0xf9, - 0x1f, 0xbf, 0x94, 0x32, 0x85, 0xfd, 0xdb, 0x0b, 0x37, 0x9f, 0x7d, 0xf3, - 0x91, 0xec, 0x8d, 0x05, 0x43, 0x12, 0x56, 0xe1, 0xe8, 0xb0, 0xb5, 0x4b, - 0x12, 0x7d, 0x58, 0xf3, 0xdd, 0xc1, 0xcf, 0x59, 0xd2, 0x15, 0xe1, 0xba, - 0xee, 0xbf, 0x39, 0x68, 0xc9, 0x2b, 0x8d, 0x94, 0x5c, 0x68, 0x6c, 0xdf, - 0x24, 0x5d, 0xd9, 0x52, 0x09, 0xfd, 0x6e, 0x8a, 0xe3, 0x96, 0x94, 0xab, - 0x2d, 0xe2, 0x2a, 0xba, 0x7d, 0x5a, 0x71, 0xfe, 0x3e, 0xcd, 0x9b, 0x7f, - 0x9e, 0xff, 0x1e, 0x24, 0xa5, 0xcb, 0x7d, 0x68, 0xf7, 0xa1, 0xcd, 0xf7, - 0x81, 0xf4, 0x94, 0x98, 0x72, 0xa4, 0x91, 0x90, 0xa3, 0xd5, 0x8c, 0xe8, - 0x05, 0x71, 0xbd, 0xbc, 0x9d, 0x2e, 0xa3, 0x6f, 0xea, 0x00, 0xdb, 0x29, - 0xe0, 0xf9, 0x0e, 0xd7, 0x59, 0x5e, 0x5e, 0x4a, 0xb7, 0xc6, 0x14, 0x0d, - 0x8e, 0xb1, 0x0f, 0xbf, 0x58, 0x5f, 0xae, 0x76, 0x00, 0x6f, 0xd6, 0x71, - 0x41, 0xdc, 0x73, 0x2c, 0xd0, 0xf6, 0xfd, 0xdf, 0x75, 0x32, 0xb2, 0xe2, - 0x74, 0x81, 0xa7, 0x16, 0x69, 0xb5, 0xc5, 0xd2, 0x0b, 0xb6, 0xb5, 0x22, - 0x6d, 0x1c, 0xeb, 0x34, 0x0a, 0xbe, 0x3f, 0x9d, 0x97, 0xae, 0xa0, 0x6f, - 0xb7, 0xe2, 0x63, 0x72, 0x42, 0xc3, 0xbc, 0x57, 0x49, 0x0f, 0x3a, 0xe2, - 0x3b, 0x7f, 0xf3, 0x52, 0xac, 0x6c, 0x97, 0xc9, 0x54, 0xf6, 0xa0, 0x1b, - 0xd0, 0x74, 0x3d, 0x67, 0x2b, 0x70, 0x6a, 0xe0, 0x4f, 0xdb, 0x81, 0xf5, - 0xee, 0x0a, 0x68, 0x1a, 0x85, 0xcd, 0x62, 0x6c, 0x66, 0x9f, 0xe8, 0x3b, - 0x87, 0x93, 0xe1, 0x78, 0x97, 0x36, 0x32, 0x6f, 0x88, 0x6e, 0xff, 0x81, - 0xe6, 0xd5, 0x7a, 0xe5, 0xd8, 0xbc, 0x8e, 0x77, 0x5d, 0xae, 0xe6, 0x4b, - 0x9a, 0xdb, 0xa8, 0x68, 0xde, 0xd9, 0x59, 0xad, 0x78, 0xd6, 0x94, 0xa3, - 0xb6, 0x7f, 0xe1, 0xb4, 0x73, 0x42, 0x1b, 0x39, 0x7b, 0x46, 0x1b, 0x3d, - 0xfb, 0x86, 0x36, 0xde, 0xd8, 0xb2, 0x49, 0xda, 0xb3, 0xd0, 0x1e, 0x71, - 0x90, 0xbf, 0x4f, 0x87, 0xba, 0xec, 0xa2, 0xde, 0x4a, 0xe4, 0x7d, 0x9f, - 0xf3, 0x86, 0xe6, 0x55, 0x6d, 0x8b, 0xfb, 0xe6, 0xa6, 0x22, 0x1a, 0xed, - 0x72, 0x74, 0xde, 0x94, 0x63, 0xd5, 0x94, 0x3c, 0x57, 0x2d, 0x29, 0x5a, - 0x86, 0x5d, 0xd2, 0xbc, 0x06, 0xc7, 0x2b, 0xa0, 0x75, 0x42, 0xdb, 0x07, - 0x9a, 0xde, 0x59, 0x29, 0x5d, 0x71, 0xe6, 0x40, 0xaf, 0x03, 0x78, 0xff, - 0x58, 0x1b, 0x6d, 0xf4, 0x6a, 0xde, 0xc9, 0x9b, 0xe2, 0x39, 0x59, 0xeb, - 0x4b, 0x62, 0xba, 0xb0, 0x01, 0xc8, 0x0c, 0xfd, 0x38, 0xd0, 0x49, 0xca, - 0xf7, 0xf5, 0x82, 0xff, 0x2c, 0x74, 0x6f, 0x5d, 0xa1, 0xfc, 0x8d, 0x5e, - 0x29, 0xcf, 0x53, 0xd7, 0xa6, 0x36, 0x52, 0xf5, 0x2f, 0x78, 0x8e, 0xf4, - 0x19, 0xe2, 0xfb, 0x47, 0x9d, 0x81, 0xf4, 0x21, 0x39, 0x03, 0xdc, 0x75, - 0xad, 0xd8, 0xa0, 0xae, 0xc1, 0xdf, 0x2d, 0x39, 0x02, 0xbd, 0x15, 0x9d, - 0x5e, 0x99, 0xb4, 0xb2, 0x2e, 0xf6, 0x68, 0x53, 0x20, 0x57, 0x32, 0xb4, - 0x17, 0xd2, 0xe7, 0xde, 0x67, 0xd3, 0x9e, 0xa1, 0xcb, 0x53, 0x2f, 0x3d, - 0xdf, 0xb3, 0x38, 0xb4, 0x91, 0x32, 0x43, 0xff, 0xf2, 0x45, 0xcf, 0xf6, - 0xb6, 0xb4, 0x48, 0x29, 0x6d, 0x48, 0x16, 0xfb, 0xb4, 0x43, 0x4e, 0x3b, - 0x22, 0x87, 0x2a, 0xd0, 0x8d, 0x6d, 0x5a, 0x8b, 0x62, 0x67, 0xca, 0x32, - 0x50, 0x32, 0x75, 0x74, 0x26, 0x49, 0x97, 0x3a, 0xd2, 0xe5, 0x7a, 0x9e, - 0x7a, 0xa2, 0x3d, 0x7f, 0x28, 0x5d, 0x69, 0xab, 0xba, 0x5a, 0xd5, 0xd3, - 0xf8, 0x2f, 0x5d, 0x4f, 0xd4, 0xc9, 0x72, 0x28, 0xb7, 0x03, 0xdc, 0x8f, - 0x40, 0x5f, 0xe2, 0xea, 0xc3, 0x0f, 0xb1, 0x6f, 0x93, 0x51, 0xb0, 0xd3, - 0x17, 0x61, 0x14, 0x7a, 0x61, 0x37, 0x64, 0x19, 0xa6, 0xee, 0xe0, 0xc3, - 0x1f, 0x49, 0x5e, 0xf9, 0xd5, 0x90, 0x97, 0xfc, 0xdb, 0x32, 0x55, 0x49, - 0x80, 0x06, 0x65, 0xd4, 0xe5, 0xbd, 0x7c, 0x64, 0x1b, 0x7b, 0x20, 0x5f, - 0x5e, 0xa6, 0xbe, 0x45, 0x7f, 0xa2, 0xfd, 0xf3, 0x9d, 0xb2, 0xfe, 0xcc, - 0xbf, 0xee, 0x7c, 0x92, 0xf6, 0x96, 0x7c, 0x27, 0xe4, 0x78, 0x35, 0xc9, - 0x3d, 0xd4, 0x56, 0x54, 0x6c, 0x8a, 0x64, 0x14, 0xdd, 0x28, 0x74, 0x48, - 0x51, 0xed, 0xf7, 0x5e, 0xd0, 0x43, 0x2c, 0xa8, 0xf2, 0xbd, 0xa0, 0x64, - 0x9b, 0xb6, 0xed, 0xcc, 0x11, 0xc9, 0xc2, 0xbe, 0x45, 0x8e, 0xcc, 0x99, - 0x32, 0x6d, 0xff, 0x63, 0xa7, 0xb4, 0x2f, 0xdf, 0x6f, 0xa8, 0xb8, 0xae, - 0xf7, 0x6e, 0x90, 0x4d, 0xe0, 0x77, 0xf9, 0x7e, 0x5d, 0xe4, 0xa6, 0x59, - 0xc8, 0x5a, 0x23, 0x08, 0xf6, 0x46, 0x81, 0xb1, 0x4c, 0x43, 0x2c, 0x93, - 0x44, 0x8b, 0x4d, 0x7d, 0xf9, 0xfe, 0xf8, 0xf0, 0xdd, 0xf5, 0x75, 0x64, - 0x9e, 0xb4, 0xa9, 0x2f, 0xc6, 0xa8, 0x12, 0xf4, 0xc1, 0xf8, 0x74, 0xbb, - 0xae, 0x8a, 0xa1, 0xae, 0x46, 0xfe, 0xef, 0xed, 0xc2, 0xf5, 0xaa, 0xa2, - 0x79, 0xce, 0xbb, 0xa1, 0x2f, 0xd8, 0x32, 0x02, 0x7f, 0x37, 0xec, 0x4f, - 0xcb, 0x91, 0x54, 0x76, 0xc2, 0x95, 0xc0, 0xe6, 0xaf, 0xad, 0xb1, 0xf9, - 0xd1, 0xbb, 0xc8, 0x75, 0x3c, 0x94, 0xcb, 0x0d, 0xe5, 0x1a, 0x85, 0x5c, - 0x63, 0x90, 0x6b, 0xe5, 0x23, 0xc8, 0xb5, 0xf2, 0x91, 0xe5, 0xd2, 0xa4, - 0xec, 0x3c, 0x08, 0x5a, 0xa6, 0xfc, 0xab, 0x13, 0xd8, 0xf2, 0xbf, 0x38, - 0x9f, 0x14, 0x19, 0x7c, 0x7f, 0x70, 0xd8, 0x16, 0xef, 0x5b, 0xe0, 0xd5, - 0x71, 0x40, 0x8b, 0xef, 0xef, 0x97, 0xe1, 0x6e, 0xfe, 0x38, 0x8b, 0x7d, - 0x5d, 0xcf, 0x1f, 0x29, 0x87, 0x3e, 0x7c, 0xef, 0xfe, 0xa8, 0x6b, 0x1f, - 0x55, 0x0e, 0xc6, 0x9c, 0x4f, 0x35, 0x9d, 0xab, 0x1f, 0x56, 0x86, 0xf5, - 0x63, 0xca, 0x2f, 0x4f, 0x86, 0xc7, 0x64, 0x72, 0x33, 0xed, 0xa9, 0xa4, - 0x8d, 0x0c, 0x92, 0xef, 0xb5, 0xfc, 0x4a, 0x26, 0xe0, 0x0d, 0x39, 0xd1, - 0xd2, 0x46, 0x39, 0xb2, 0x60, 0x49, 0x69, 0xe9, 0x4e, 0x71, 0x57, 0x03, - 0x6f, 0xb4, 0x47, 0xf6, 0x7d, 0xd2, 0x7c, 0x2a, 0xc8, 0x2b, 0x2e, 0x54, - 0x91, 0x83, 0x56, 0x13, 0x72, 0xd9, 0x48, 0xcb, 0x9b, 0x83, 0x87, 0xe5, - 0xf3, 0xd5, 0x24, 0xe8, 0x31, 0x9f, 0x2c, 0xe7, 0x10, 0x17, 0xb5, 0xb2, - 0x63, 0x08, 0x79, 0xaf, 0xd9, 0x9c, 0x13, 0xc4, 0x96, 0x72, 0x10, 0x83, - 0x5d, 0x6f, 0x50, 0xe5, 0x14, 0x90, 0x4f, 0x64, 0x0c, 0xb1, 0xb7, 0x66, - 0xb3, 0xcd, 0xfe, 0xa0, 0xef, 0xb3, 0x95, 0x5e, 0xad, 0xc8, 0xbc, 0x64, - 0xf0, 0xa6, 0x4c, 0x3b, 0x41, 0xdf, 0xe7, 0x2a, 0xa3, 0x9b, 0x98, 0x1f, - 0x1a, 0x05, 0xc9, 0x94, 0x9d, 0xf7, 0x7c, 0xd7, 0xba, 0x7d, 0xcd, 0xfa, - 0x78, 0xb2, 0x13, 0x81, 0xce, 0x45, 0xfb, 0xaa, 0xad, 0xf7, 0xb6, 0x4a, - 0x09, 0x27, 0x5d, 0xd6, 0x1a, 0x47, 0xe7, 0xbe, 0x4a, 0x79, 0x5b, 0xab, - 0xdc, 0x34, 0x80, 0x3f, 0x6d, 0x68, 0x62, 0x1e, 0xaa, 0x94, 0xbb, 0xd9, - 0xa6, 0xbe, 0x74, 0x4d, 0x12, 0xa3, 0x15, 0x5f, 0xae, 0x3a, 0x41, 0xee, - 0x63, 0x68, 0x7a, 0x6f, 0x5b, 0xb8, 0x56, 0xd7, 0x76, 0x39, 0x97, 0x44, - 0x3a, 0x0e, 0x55, 0xc4, 0x2a, 0x56, 0x76, 0x39, 0x6f, 0x4b, 0xb9, 0xa7, - 0x6d, 0x75, 0x5d, 0x8a, 0xeb, 0x76, 0x0e, 0xaf, 0x9d, 0xbb, 0xcb, 0xb9, - 0x28, 0xe5, 0x2d, 0x6d, 0xab, 0xb4, 0xd2, 0x58, 0xdb, 0x17, 0xac, 0xe5, - 0xf8, 0x66, 0x71, 0xbb, 0x39, 0x47, 0xef, 0x6d, 0xbf, 0x45, 0x43, 0x32, - 0xc5, 0x4a, 0xb9, 0xa7, 0x7d, 0x15, 0xaf, 0x4d, 0xbc, 0xde, 0x1a, 0xbc, - 0xc4, 0xd9, 0xbe, 0x8a, 0x33, 0x07, 0x9c, 0x43, 0xab, 0x38, 0x39, 0x7e, - 0x58, 0x8a, 0x38, 0xd3, 0x5a, 0x0a, 0x32, 0xbc, 0x54, 0xc9, 0x48, 0x79, - 0x28, 0x01, 0xdd, 0xf7, 0x1f, 0xfc, 0x9a, 0xaa, 0x43, 0xcc, 0x61, 0x0f, - 0xba, 0x32, 0x55, 0x5e, 0x87, 0xd8, 0x08, 0xdb, 0xf8, 0x5a, 0x5d, 0x86, - 0x17, 0xeb, 0xa6, 0x1c, 0x6f, 0x70, 0xbf, 0x98, 0xe3, 0x05, 0x75, 0xc6, - 0x85, 0x46, 0x4e, 0xdb, 0x87, 0xbd, 0x66, 0x9d, 0xb0, 0xaf, 0x61, 0x6a, - 0xa3, 0x3c, 0x1f, 0x80, 0x97, 0x76, 0x7e, 0xac, 0x41, 0xdb, 0x79, 0x03, - 0xb6, 0x41, 0xce, 0xa3, 0x9c, 0xbd, 0x95, 0xb9, 0x53, 0x66, 0xd1, 0x51, - 0x75, 0x88, 0x56, 0xcb, 0x77, 0x20, 0x07, 0x4d, 0xa0, 0xd6, 0x80, 0xcd, - 0xdb, 0x78, 0x6f, 0x70, 0xde, 0x32, 0xe6, 0x6d, 0xe0, 0x3c, 0xec, 0xcd, - 0x25, 0xe5, 0x0f, 0xa6, 0xcd, 0xf1, 0x77, 0xb1, 0xc7, 0x68, 0xd7, 0x59, - 0x57, 0x58, 0x02, 0x5f, 0xc1, 0x3e, 0xa2, 0x6e, 0x48, 0xed, 0x60, 0x7e, - 0x8f, 0xb9, 0x19, 0xcc, 0xcd, 0x66, 0x18, 0xcf, 0x3d, 0xfb, 0x99, 0x0e, - 0xe9, 0x42, 0xbb, 0xce, 0x35, 0xd9, 0x0c, 0x72, 0x5b, 0xdf, 0xcb, 0xb7, - 0xc9, 0x4a, 0xca, 0xbf, 0x60, 0xd8, 0xd1, 0xdc, 0x08, 0x6f, 0xf3, 0x5c, - 0xe6, 0xc5, 0xc4, 0xbd, 0x21, 0xcc, 0x83, 0xc7, 0xc5, 0x6d, 0xfc, 0x49, - 0xb7, 0x74, 0xb9, 0xf8, 0x8d, 0xe6, 0x4c, 0x6f, 0x0e, 0x6a, 0x2e, 0xbe, - 0xb7, 0x50, 0x3e, 0x17, 0xe7, 0xa1, 0x56, 0xac, 0x66, 0x26, 0x59, 0x1f, - 0x15, 0xeb, 0x6c, 0xef, 0x85, 0x3f, 0x04, 0x75, 0xd7, 0x85, 0x5b, 0xbe, - 0x70, 0x19, 0x7a, 0x4b, 0x43, 0x6f, 0x29, 0x39, 0xdf, 0x60, 0x9d, 0xe6, - 0x42, 0x5f, 0x19, 0xf1, 0x1a, 0xe3, 0x58, 0x2b, 0x87, 0x81, 0x03, 0x3a, - 0x17, 0x47, 0x2f, 0x64, 0x65, 0xca, 0xda, 0x1d, 0xf1, 0x00, 0x5c, 0x88, - 0x1f, 0x85, 0x36, 0xf4, 0xf1, 0x1d, 0x9a, 0x53, 0xff, 0x86, 0x7f, 0x94, - 0xed, 0x09, 0xbd, 0x30, 0xd6, 0xd4, 0xbf, 0x6e, 0xfc, 0xa1, 0x1c, 0x68, - 0x33, 0x06, 0x31, 0xfe, 0xe8, 0xa8, 0xf3, 0x18, 0x8b, 0x48, 0xd7, 0x92, - 0x23, 0x4b, 0x23, 0xdc, 0x37, 0x8b, 0xf1, 0xa7, 0x5c, 0xe7, 0x9e, 0x29, - 0x5c, 0xc0, 0x19, 0xad, 0xf1, 0xfd, 0x11, 0x87, 0x6b, 0x7c, 0x99, 0x70, - 0x3a, 0xc4, 0x48, 0x96, 0xb4, 0xc7, 0x07, 0x11, 0x7b, 0x1e, 0xe0, 0x3e, - 0x32, 0x06, 0x6d, 0x17, 0xb0, 0xea, 0xb4, 0x3c, 0x3c, 0xc8, 0x75, 0xa0, - 0xdd, 0x2a, 0x7a, 0x92, 0x34, 0xf3, 0x21, 0x4f, 0x43, 0xdd, 0x81, 0xbe, - 0x06, 0xac, 0x40, 0x7f, 0x9f, 0xe9, 0x5e, 0xd5, 0x1f, 0xd7, 0x35, 0xf3, - 0xcb, 0x18, 0x96, 0x90, 0x81, 0x33, 0x1b, 0x65, 0xe7, 0xa2, 0x25, 0xf6, - 0x99, 0x55, 0xfe, 0x76, 0x9e, 0x5b, 0xcb, 0x5f, 0xf4, 0x7f, 0x15, 0x5c, - 0xd0, 0xc5, 0x8e, 0xfa, 0x1e, 0x4b, 0x05, 0xb8, 0xa3, 0xf6, 0x7b, 0xe1, - 0x5e, 0xf1, 0xfd, 0x99, 0x70, 0x4f, 0xb0, 0x07, 0x88, 0x95, 0xe7, 0x6f, - 0xc5, 0xa9, 0x0c, 0xf6, 0x06, 0xb6, 0xa7, 0xe2, 0x11, 0xe3, 0x18, 0xed, - 0xbb, 0x63, 0xd2, 0x2c, 0xb0, 0x8e, 0xe6, 0x3e, 0xc9, 0x44, 0xb9, 0x22, - 0xa5, 0xad, 0x85, 0x67, 0x7d, 0xd8, 0xcf, 0xa4, 0xa5, 0x6c, 0xaf, 0x63, - 0xaf, 0x97, 0x37, 0xa0, 0x1b, 0x8c, 0xc1, 0x26, 0xf5, 0x42, 0x42, 0x8a, - 0x8d, 0x44, 0xc2, 0x3c, 0x31, 0xf0, 0x23, 0xcf, 0x48, 0x24, 0xf4, 0x13, - 0x81, 0x9d, 0x4d, 0xd6, 0x6f, 0x20, 0x56, 0x6a, 0x72, 0x74, 0xe8, 0x86, - 0xcf, 0x1a, 0xd8, 0xdb, 0x0b, 0x9b, 0x1b, 0x82, 0xcf, 0x80, 0x8f, 0x72, - 0xa3, 0xa3, 0x37, 0xe0, 0xed, 0x2b, 0x11, 0x8f, 0xa6, 0x8e, 0xdc, 0xd3, - 0xcb, 0xfb, 0xbe, 0x51, 0xd8, 0x90, 0x98, 0xce, 0x8f, 0x6f, 0xd1, 0xcf, - 0xed, 0xdf, 0x62, 0x9c, 0x2b, 0x6d, 0x01, 0x3e, 0xdd, 0xcb, 0xe3, 0xf7, - 0x9c, 0xc8, 0x44, 0x15, 0x3a, 0xdf, 0x03, 0x3d, 0x59, 0xf0, 0xc5, 0x3d, - 0xa6, 0xca, 0xd1, 0xf5, 0x3d, 0x2f, 0x6e, 0x0a, 0x70, 0xf0, 0xfd, 0x27, - 0x7e, 0x70, 0x86, 0x5e, 0x0e, 0xfb, 0x7e, 0x3f, 0xdc, 0x87, 0x5f, 0x45, - 0xb9, 0x78, 0x5e, 0x44, 0xb2, 0xad, 0x3d, 0x37, 0xb2, 0xe3, 0x25, 0x9c, - 0x33, 0xa7, 0x1d, 0xdf, 0x7f, 0x07, 0xcf, 0x35, 0xa7, 0xd9, 0x46, 0xde, - 0x7f, 0xf6, 0x31, 0x07, 0xf8, 0x2c, 0xce, 0xbd, 0xd1, 0xa6, 0xb3, 0xff, - 0x5e, 0xcf, 0xbd, 0x7b, 0x3f, 0xfb, 0xc9, 0xf3, 0x1d, 0x7d, 0xef, 0x03, - 0xce, 0xfe, 0x0f, 0x5c, 0x77, 0x0f, 0x3e, 0x1b, 0xd8, 0x6d, 0xb1, 0xd1, - 0x1c, 0x5f, 0xee, 0xd5, 0x7f, 0x7f, 0xad, 0xfb, 0x76, 0xff, 0xb5, 0xbb, - 0x6f, 0xf7, 0xdf, 0xcd, 0xdd, 0xbf, 0x18, 0xff, 0xcd, 0x01, 0x0f, 0x7d, - 0x70, 0xad, 0xff, 0xae, 0xe7, 0x93, 0xd4, 0xf7, 0xf3, 0x3d, 0xe5, 0xa1, - 0xce, 0x30, 0x1f, 0x52, 0xe7, 0xf5, 0x17, 0xa7, 0x6d, 0xef, 0x7e, 0x53, - 0x4a, 0xb9, 0x16, 0xc9, 0xe6, 0x6a, 0xb2, 0x43, 0x8e, 0x3b, 0x22, 0x4b, - 0xaa, 0x16, 0x31, 0x51, 0x8b, 0x0f, 0xa0, 0x3e, 0x0b, 0xf4, 0xba, 0xa4, - 0xf4, 0xf2, 0x02, 0x78, 0x89, 0xf0, 0x74, 0xdd, 0x05, 0x0f, 0x71, 0x10, - 0x17, 0xf1, 0x0c, 0xe2, 0x7c, 0xb7, 0xd7, 0xc1, 0x85, 0x73, 0xea, 0x25, - 0xd4, 0x64, 0xb6, 0xde, 0xa3, 0x07, 0x67, 0xb2, 0x5b, 0x96, 0xdd, 0xe9, - 0xeb, 0xf2, 0x05, 0x9e, 0x59, 0x0a, 0xae, 0xce, 0x21, 0x56, 0x0f, 0x8d, - 0x85, 0x75, 0xd2, 0xdc, 0x41, 0xcf, 0x8e, 0xee, 0x49, 0x78, 0x47, 0x92, - 0x90, 0x92, 0x9a, 0xb5, 0x04, 0x1d, 0x68, 0x72, 0x0d, 0x67, 0xd0, 0xd5, - 0xb9, 0x76, 0xe0, 0x45, 0xee, 0x77, 0x20, 0xbb, 0x57, 0xb4, 0x7e, 0xab, - 0x55, 0x6b, 0x87, 0x2f, 0x65, 0xc4, 0x55, 0x6d, 0x9e, 0xd3, 0xa7, 0x66, - 0x16, 0x2b, 0xc8, 0x03, 0x6d, 0x9c, 0xaf, 0x79, 0xbc, 0xd7, 0x49, 0x43, - 0x93, 0x2b, 0x73, 0xba, 0xfc, 0xd3, 0x9c, 0x21, 0xff, 0x8c, 0x3a, 0xf4, - 0x9a, 0x7d, 0x6a, 0xe6, 0xb4, 0x2d, 0xf7, 0x81, 0xd5, 0xf0, 0x0e, 0x4f, - 0x76, 0x9a, 0x42, 0x5b, 0x1d, 0x48, 0xff, 0x8e, 0x20, 0xff, 0xc1, 0x9a, - 0x2b, 0x73, 0xa4, 0xb5, 0x76, 0x8d, 0xf4, 0x22, 0x1f, 0x83, 0x5d, 0x0f, - 0x30, 0x27, 0xe2, 0x7c, 0xd4, 0xab, 0x03, 0xd6, 0x3e, 0xc5, 0x5b, 0x42, - 0x16, 0xeb, 0x9c, 0x6f, 0x82, 0xb7, 0x2e, 0x9c, 0x31, 0x59, 0x6b, 0x52, - 0xfe, 0xb0, 0x5b, 0xe5, 0xaa, 0x1a, 0xfb, 0x0d, 0xb5, 0xc7, 0xef, 0xef, - 0xe7, 0xde, 0x1b, 0x32, 0x95, 0x62, 0x9b, 0x63, 0x59, 0xd4, 0x9c, 0xc4, - 0x97, 0xdd, 0xeb, 0x0a, 0x79, 0x0e, 0xde, 0xaf, 0x08, 0x65, 0xdb, 0x6d, - 0x5d, 0x97, 0xd7, 0x7d, 0xf7, 0x00, 0xe5, 0x89, 0x72, 0x8b, 0x39, 0x9f, - 0xb1, 0xd8, 0x28, 0xcc, 0xc0, 0x8e, 0xbf, 0x2a, 0xdf, 0x6f, 0x1c, 0x92, - 0xef, 0x35, 0x26, 0xe5, 0xcf, 0x1a, 0x5f, 0x96, 0x3f, 0x6d, 0x1c, 0x94, - 0xd7, 0x1b, 0x07, 0xe4, 0xb5, 0xc6, 0x84, 0xbc, 0xda, 0xd8, 0x0f, 0x1b, - 0x1f, 0x87, 0x8d, 0x9f, 0x9a, 0x99, 0xac, 0xf7, 0xcb, 0xd4, 0x49, 0xc4, - 0x20, 0xe7, 0x1b, 0xba, 0xba, 0xe3, 0xb3, 0xe9, 0xe7, 0x2d, 0x32, 0xad, - 0xee, 0xaf, 0x34, 0xe4, 0x89, 0x2d, 0xbc, 0x2b, 0x7c, 0xc5, 0x33, 0x2e, - 0x87, 0xf1, 0xe8, 0xe1, 0x94, 0xb4, 0x03, 0xbf, 0xca, 0x4b, 0x4d, 0x9e, - 0xdb, 0x62, 0x86, 0xf7, 0x9c, 0x87, 0x24, 0xc9, 0xfb, 0xb0, 0x9c, 0x67, - 0xa0, 0xde, 0x5e, 0xd7, 0x27, 0x73, 0xb4, 0x65, 0xe8, 0xc6, 0x95, 0x43, - 0xb0, 0x53, 0xc3, 0x7e, 0xcb, 0xa5, 0x1e, 0x16, 0x97, 0x28, 0xf7, 0x46, - 0x59, 0x5c, 0xa0, 0x6f, 0xff, 0x1b, 0x64, 0x6c, 0x97, 0xda, 0x82, 0x89, - 0xb9, 0x6e, 0x98, 0xab, 0x6c, 0xa7, 0x3d, 0x00, 0x1f, 0xf1, 0x7e, 0x10, - 0x4e, 0xab, 0x09, 0x27, 0xf1, 0x24, 0x54, 0x0c, 0x08, 0x70, 0x5b, 0x52, - 0x5b, 0x4a, 0xca, 0xc2, 0x42, 0x0f, 0x9e, 0x94, 0x2c, 0xd4, 0x6d, 0x3c, - 0x39, 0x3c, 0x43, 0x78, 0xd2, 0xb0, 0x53, 0xca, 0xc8, 0xd8, 0x12, 0xc9, - 0x88, 0x78, 0x5c, 0xed, 0x0d, 0x6b, 0x2a, 0xf2, 0xa3, 0x85, 0xfc, 0x74, - 0x87, 0x7d, 0x1d, 0x52, 0xab, 0x38, 0x32, 0x55, 0xfd, 0x94, 0x3e, 0xa5, - 0x74, 0x07, 0xfc, 0x95, 0x21, 0xb4, 0xef, 0x0f, 0xdb, 0x8f, 0xca, 0xf4, - 0xbc, 0xc8, 0xca, 0xcb, 0x03, 0x7a, 0x51, 0xb5, 0xf7, 0xa2, 0xad, 0xa3, - 0x9d, 0x0d, 0xdb, 0xcc, 0x8f, 0x0e, 0xe0, 0x71, 0xd5, 0xf3, 0xf5, 0xea, - 0xb8, 0x3c, 0x55, 0xed, 0x77, 0x5e, 0x87, 0xcd, 0xbd, 0x65, 0x46, 0xf7, - 0xd2, 0x04, 0x24, 0x79, 0xf6, 0x56, 0x75, 0xf7, 0xf1, 0x04, 0xe2, 0xad, - 0x9b, 0x34, 0xe5, 0x6f, 0x4f, 0x64, 0xad, 0xa7, 0xf5, 0x5c, 0x52, 0xda, - 0x7d, 0xff, 0x71, 0x3b, 0x3b, 0x3b, 0xa9, 0x77, 0xca, 0xdf, 0xbf, 0x98, - 0x91, 0x85, 0xb3, 0x5b, 0x65, 0xa1, 0x06, 0x99, 0x1a, 0xbf, 0x8e, 0x7d, - 0x35, 0xe5, 0xea, 0x9e, 0x47, 0xb1, 0x27, 0x8c, 0x5d, 0x49, 0xe4, 0x6c, - 0x1b, 0xc4, 0xec, 0x25, 0x5d, 0x49, 0x98, 0x85, 0x9c, 0x1c, 0x81, 0xdf, - 0x4f, 0xdb, 0xb9, 0x1e, 0x69, 0xc7, 0x7b, 0x7d, 0x04, 0x7c, 0x5b, 0x32, - 0xd5, 0x6b, 0xc9, 0x99, 0xc1, 0x68, 0xff, 0xb6, 0x62, 0x6e, 0x46, 0x16, - 0xcf, 0x66, 0xf0, 0x9b, 0x83, 0xfd, 0xec, 0x94, 0x57, 0x6a, 0xfd, 0xb2, - 0x54, 0xdb, 0x2a, 0x8b, 0xb5, 0xe6, 0x7d, 0xe8, 0xec, 0x09, 0xe2, 0x1d, - 0xf1, 0xf4, 0x5b, 0x53, 0xfa, 0x56, 0x71, 0xcd, 0x7e, 0xeb, 0x29, 0xfd, - 0x1f, 0xe4, 0x31, 0x33, 0xa0, 0xa9, 0x17, 0x7e, 0xa4, 0xee, 0x84, 0x26, - 0x79, 0xf6, 0x2a, 0xbc, 0x4f, 0x26, 0x49, 0xfb, 0xf5, 0xc6, 0x07, 0xd1, - 0x59, 0xcb, 0xcf, 0x9d, 0x68, 0x52, 0x06, 0xe2, 0xec, 0xbf, 0x71, 0x52, - 0xef, 0x95, 0xe5, 0x6d, 0x0f, 0x58, 0x4f, 0xea, 0xad, 0x88, 0x01, 0x3f, - 0x97, 0x9f, 0xee, 0xd9, 0x24, 0x3f, 0xfc, 0xcd, 0xec, 0xa9, 0x6f, 0x22, - 0xd9, 0xbf, 0xb2, 0xa7, 0x83, 0x71, 0x01, 0xef, 0xec, 0xcf, 0xde, 0x70, - 0x75, 0xea, 0xe1, 0x2f, 0xa0, 0x87, 0xec, 0x9c, 0xba, 0x9b, 0x56, 0x3c, - 0x90, 0x3e, 0xf5, 0x52, 0x06, 0x6f, 0x18, 0xab, 0xf7, 0x03, 0x57, 0x59, - 0xe9, 0xf9, 0x09, 0x27, 0x7b, 0x03, 0xe9, 0xb0, 0xbf, 0x68, 0xf7, 0xa7, - 0x77, 0xea, 0x3b, 0x64, 0x32, 0xfd, 0x80, 0xf5, 0xb4, 0x6c, 0x21, 0xce, - 0xd9, 0x05, 0xc1, 0xda, 0x79, 0xe2, 0xfb, 0x2b, 0xe0, 0x0b, 0x70, 0x28, - 0xff, 0x51, 0x38, 0x77, 0x59, 0x5f, 0xd7, 0x79, 0xc6, 0x63, 0x0c, 0x71, - 0xe1, 0xe2, 0x10, 0x65, 0x40, 0x82, 0x95, 0xca, 0xa6, 0x5d, 0xfd, 0xc3, - 0xc8, 0x47, 0xfc, 0xfd, 0x56, 0x51, 0x27, 0x0f, 0xe7, 0xc0, 0xcb, 0x4f, - 0xc0, 0x7f, 0x3f, 0x70, 0xa2, 0xf6, 0x48, 0x47, 0x74, 0xff, 0x4e, 0xd1, - 0x7d, 0xad, 0x21, 0xe6, 0x2a, 0x5d, 0xf4, 0xd5, 0x75, 0xc8, 0xdd, 0x07, - 0x7b, 0xb5, 0xf0, 0xcb, 0xbd, 0xe9, 0x0c, 0xf7, 0x98, 0xeb, 0x22, 0xba, - 0x11, 0xbf, 0x5c, 0x73, 0x27, 0x1e, 0xee, 0x75, 0x3e, 0xea, 0xd4, 0x03, - 0x09, 0x79, 0xf7, 0x44, 0xb4, 0x37, 0x07, 0x64, 0xba, 0x0a, 0xdd, 0xed, - 0xea, 0x0f, 0xfc, 0x27, 0x1d, 0xf1, 0x40, 0xde, 0xff, 0x06, 0xbc, 0x07, - 0xb8, 0x5b, 0x0b, 0xcd, 0xba, 0xc3, 0x58, 0x3d, 0xa0, 0x31, 0xb6, 0x0e, - 0x4f, 0x57, 0xf6, 0x44, 0xbe, 0x98, 0x84, 0x5f, 0xed, 0xb6, 0x9e, 0x10, - 0xd6, 0x63, 0xc4, 0x9b, 0x94, 0x1f, 0xbe, 0x0c, 0x1e, 0x92, 0xf4, 0x93, - 0x7f, 0x5f, 0xe3, 0x27, 0x1c, 0xdb, 0x2a, 0x35, 0xd4, 0xd4, 0x5e, 0xde, - 0x94, 0x69, 0x25, 0x03, 0xda, 0x35, 0xfa, 0x77, 0x29, 0xf4, 0xef, 0x47, - 0x80, 0xa3, 0x5d, 0x8c, 0x47, 0x1f, 0xc7, 0x59, 0x9d, 0xcd, 0x2c, 0xeb, - 0xcc, 0x03, 0x76, 0x4b, 0x51, 0xdd, 0x4f, 0xdf, 0x8b, 0xee, 0xa2, 0xd8, - 0x94, 0x96, 0x8b, 0x95, 0x28, 0x2e, 0xa5, 0x71, 0x9e, 0xb4, 0xcb, 0xa5, - 0xb9, 0x28, 0xe6, 0xb5, 0xcb, 0x12, 0xf2, 0x9a, 0x95, 0x97, 0x2c, 0x8c, - 0x25, 0xe5, 0xe2, 0x5c, 0x12, 0x31, 0xab, 0x47, 0x56, 0xe6, 0x7a, 0x30, - 0x96, 0xc2, 0xba, 0x14, 0xe6, 0xdb, 0xb2, 0x52, 0xb1, 0x81, 0x27, 0x87, - 0x76, 0x0e, 0xed, 0x21, 0xb9, 0xa4, 0xbe, 0x17, 0x30, 0x2f, 0x18, 0x42, - 0xdc, 0x62, 0x5e, 0x30, 0x82, 0x18, 0x32, 0x81, 0x27, 0x8a, 0x5d, 0xa7, - 0x66, 0xa6, 0x2a, 0xbc, 0x73, 0x84, 0x0e, 0xac, 0x53, 0x33, 0xd3, 0xb6, - 0x89, 0xba, 0xed, 0x1b, 0xda, 0x54, 0x83, 0x72, 0x41, 0xb7, 0x43, 0x1d, - 0xa2, 0x3f, 0x4a, 0x9b, 0xe4, 0x79, 0x67, 0x20, 0xc6, 0x77, 0x01, 0x9f, - 0x23, 0xfa, 0x6f, 0xd0, 0x17, 0xa0, 0xc3, 0x27, 0xba, 0xe4, 0xd2, 0xcb, - 0x8c, 0x35, 0xae, 0xbc, 0x7a, 0x96, 0x3a, 0x2c, 0xf6, 0xac, 0xea, 0x90, - 0x63, 0x0f, 0xe1, 0x8c, 0xd8, 0x0f, 0x7b, 0x32, 0x33, 0x87, 0x90, 0xcb, - 0x7c, 0x1b, 0xf6, 0x59, 0x66, 0xcd, 0x9d, 0x0e, 0x6a, 0x84, 0x20, 0x06, - 0xa0, 0xdd, 0x47, 0x5d, 0xb1, 0xdd, 0x07, 0xbb, 0xe3, 0x58, 0x9f, 0x1a, - 0x5b, 0x04, 0x8e, 0x60, 0x8c, 0xed, 0xcd, 0xb2, 0xa8, 0xc6, 0x0e, 0xaa, - 0xb1, 0xb2, 0xb2, 0x0f, 0x8e, 0x1d, 0x52, 0xb1, 0xe9, 0x7c, 0x23, 0xea, - 0xdf, 0x88, 0x58, 0xc2, 0x7e, 0xf6, 0xe5, 0x61, 0xeb, 0x7b, 0x71, 0xae, - 0x15, 0x64, 0xa9, 0x81, 0x3a, 0x30, 0xff, 0x7b, 0x98, 0xcb, 0x3d, 0xc8, - 0x9e, 0x2a, 0xe9, 0xe4, 0xf1, 0x20, 0xce, 0x83, 0xfd, 0x21, 0xad, 0xb6, - 0x90, 0xaf, 0x03, 0x61, 0xbb, 0x25, 0xa4, 0x4d, 0x3c, 0x36, 0x70, 0x1c, - 0xc3, 0x5a, 0x17, 0x38, 0x18, 0x63, 0x11, 0x23, 0x52, 0x29, 0xe8, 0x82, - 0x34, 0xdb, 0xa4, 0xac, 0xde, 0xf7, 0xc3, 0x76, 0xb9, 0x16, 0x3a, 0xb4, - 0xa2, 0x75, 0xa5, 0x70, 0xcf, 0x53, 0xea, 0x9c, 0xd1, 0x93, 0x9b, 0xc3, - 0x9c, 0x10, 0x7a, 0x45, 0x9c, 0xd5, 0x93, 0x8c, 0x37, 0xef, 0x84, 0x76, - 0xda, 0x8b, 0xbe, 0x87, 0x44, 0xef, 0x65, 0xdf, 0x51, 0xe0, 0x61, 0xed, - 0x3c, 0x0c, 0x99, 0xd9, 0xe6, 0xfa, 0x6c, 0xd3, 0xfa, 0xc4, 0x3a, 0xeb, - 0x3b, 0x9a, 0xfa, 0x32, 0x52, 0x9b, 0xef, 0x52, 0xf1, 0xf2, 0x7c, 0x18, - 0x2f, 0x17, 0x6b, 0x94, 0x05, 0x7e, 0x96, 0x7f, 0x5b, 0xe9, 0xa2, 0x76, - 0x36, 0xb0, 0xf5, 0xa5, 0x93, 0x3c, 0x17, 0x57, 0xe7, 0xd5, 0xd4, 0xbc, - 0xdf, 0x06, 0xff, 0xba, 0x1c, 0x55, 0x32, 0x70, 0x3e, 0xe6, 0xd5, 0x02, - 0xbf, 0x31, 0x6c, 0xce, 0xa1, 0x8f, 0x44, 0x6b, 0x38, 0xff, 0xe7, 0xa8, - 0x55, 0xbe, 0xac, 0xd6, 0xac, 0xfa, 0x0c, 0xf9, 0x71, 0x42, 0x9e, 0x7b, - 0xc0, 0x5f, 0x67, 0x28, 0x43, 0x7b, 0x28, 0x03, 0xf1, 0xfd, 0x27, 0x70, - 0xb7, 0x61, 0x1e, 0x79, 0xdd, 0x86, 0x3e, 0xbe, 0xff, 0x17, 0xfa, 0x76, - 0x23, 0xff, 0x23, 0x6f, 0x89, 0x26, 0xde, 0xfe, 0x03, 0x63, 0x3d, 0x4a, - 0xb7, 0x35, 0xd4, 0x26, 0x53, 0xbc, 0xef, 0x48, 0xe1, 0x1c, 0x38, 0xb9, - 0x4d, 0xd1, 0xad, 0x9d, 0xbd, 0x86, 0xf1, 0x5e, 0xac, 0x89, 0xda, 0xcd, - 0xb2, 0xe9, 0x58, 0xfb, 0x53, 0x25, 0xcf, 0x62, 0xed, 0x4e, 0xf2, 0x6f, - 0x5b, 0x23, 0x3b, 0xe5, 0x26, 0x4f, 0xe4, 0xa7, 0x1f, 0x4f, 0x2b, 0x72, - 0x21, 0xd8, 0x6d, 0xd2, 0x90, 0xd1, 0x7c, 0x9a, 0xdf, 0xf9, 0x12, 0xbc, - 0x17, 0x1d, 0x19, 0xe4, 0x9e, 0xa1, 0xdd, 0x60, 0x4e, 0x47, 0x7f, 0x4b, - 0xc8, 0x31, 0xd4, 0x24, 0xe5, 0x85, 0x8c, 0x56, 0x3c, 0x99, 0x45, 0x16, - 0xad, 0xbe, 0xd5, 0xc9, 0x8b, 0x4b, 0xb6, 0x7c, 0x1b, 0x7e, 0x7a, 0xb2, - 0x9e, 0x4d, 0x7f, 0x13, 0xf9, 0xc1, 0x91, 0x25, 0xe6, 0x13, 0x3d, 0x29, - 0x65, 0x9b, 0xf3, 0x9a, 0x6c, 0x60, 0x4c, 0x9b, 0x47, 0x7e, 0x6a, 0xdd, - 0x2d, 0x47, 0x82, 0x9f, 0x57, 0xd7, 0xc6, 0x0c, 0xca, 0xb1, 0x36, 0x66, - 0x10, 0x0f, 0x63, 0xc6, 0x4e, 0xec, 0x13, 0x63, 0x06, 0xf6, 0xff, 0x24, - 0x63, 0x86, 0x8d, 0x75, 0x8c, 0x19, 0x79, 0x59, 0xac, 0x32, 0x66, 0xec, - 0x45, 0x9b, 0x31, 0xa3, 0x80, 0x76, 0x10, 0x2f, 0x16, 0x55, 0xbc, 0xc8, - 0x5a, 0xcb, 0xc2, 0x38, 0x81, 0x3c, 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, - 0xb1, 0x8a, 0x3c, 0xb1, 0x8a, 0x3c, 0x11, 0xb6, 0xfe, 0x5a, 0x15, 0x79, - 0x22, 0xfc, 0xe7, 0x3c, 0x72, 0x92, 0xa0, 0xa6, 0x38, 0x8c, 0x9a, 0xc2, - 0xd5, 0xc6, 0xaa, 0xe3, 0xda, 0xbe, 0x2a, 0x6a, 0x43, 0xf5, 0x9d, 0x58, - 0x1f, 0xda, 0x80, 0xba, 0xa8, 0xe6, 0x6c, 0x01, 0x5f, 0xd7, 0xe0, 0x1b, - 0xd4, 0xd3, 0x56, 0x99, 0xca, 0xed, 0x80, 0x7c, 0xd8, 0x7f, 0xfb, 0xfb, - 0xe8, 0x43, 0x3e, 0x9f, 0x63, 0x0d, 0xc2, 0x78, 0xb5, 0x0f, 0x6d, 0x1d, - 0x6d, 0xec, 0xe9, 0x04, 0x7c, 0xc4, 0x7e, 0x90, 0xf9, 0x62, 0x7a, 0x41, - 0x9e, 0xdc, 0x1c, 0xd8, 0xf4, 0x6f, 0x31, 0x27, 0x5e, 0xd3, 0xde, 0x88, - 0x39, 0xf0, 0x17, 0xd8, 0x97, 0x5a, 0x03, 0x5c, 0xba, 0xfd, 0xe7, 0xc4, - 0xd1, 0xb7, 0xe1, 0xd6, 0x1c, 0xda, 0xd5, 0xf7, 0x9a, 0xfa, 0xb2, 0x98, - 0xcf, 0xef, 0xe2, 0x3b, 0xf0, 0xfb, 0x16, 0x7e, 0x61, 0x77, 0xf6, 0x05, - 0xcc, 0xe9, 0xc3, 0xef, 0x77, 0x9a, 0xe6, 0x42, 0x0a, 0xfb, 0x2f, 0xd1, - 0x77, 0x31, 0xa4, 0xc1, 0x6f, 0x89, 0x5f, 0x6a, 0xe2, 0xe3, 0x07, 0xe8, - 0xfb, 0x6b, 0xf4, 0xf9, 0xfe, 0xdb, 0x4e, 0xd4, 0x27, 0xa5, 0x96, 0x70, - 0xef, 0x46, 0xd5, 0xde, 0x69, 0xca, 0xe6, 0x8f, 0x2c, 0xe9, 0xaa, 0x0e, - 0x7a, 0xae, 0x8e, 0xea, 0x08, 0x71, 0xbe, 0xbc, 0x10, 0xd4, 0xad, 0xc7, - 0x51, 0x73, 0x16, 0xab, 0xb4, 0x91, 0x1c, 0xfa, 0x6d, 0x9c, 0x69, 0x32, - 0x69, 0xdc, 0xaa, 0x63, 0x13, 0x89, 0xc9, 0x7a, 0x9b, 0x48, 0x37, 0x69, - 0x32, 0x4f, 0x22, 0x8e, 0xd9, 0x99, 0xe2, 0xc2, 0xec, 0x8c, 0x07, 0x9c, - 0x63, 0x75, 0xae, 0xe5, 0x3c, 0x93, 0xf7, 0x63, 0x4d, 0x74, 0x69, 0x13, - 0x60, 0x06, 0xf4, 0x9e, 0xab, 0x93, 0x7e, 0x40, 0xb3, 0xac, 0x68, 0xda, - 0xe8, 0x8f, 0xea, 0xc7, 0x1c, 0x6a, 0x5d, 0x99, 0x64, 0xed, 0x5c, 0x0c, - 0x69, 0xba, 0x75, 0x49, 0x24, 0x0a, 0xcd, 0xf8, 0x82, 0x8c, 0xf3, 0xb9, - 0xfa, 0xec, 0x8c, 0xfe, 0x42, 0x36, 0xc7, 0x3b, 0x11, 0xd7, 0x9a, 0x9d, - 0x69, 0x1d, 0x48, 0xc8, 0x8f, 0x91, 0xbb, 0x1d, 0x53, 0x34, 0x66, 0x67, - 0x8c, 0x17, 0x02, 0x5b, 0x0c, 0xe8, 0xe0, 0x3c, 0xc9, 0xb7, 0x43, 0x4e, - 0xd2, 0x62, 0x4d, 0x1d, 0x8c, 0x4f, 0xaa, 0x7a, 0xd1, 0x94, 0x2b, 0x15, - 0x45, 0x3b, 0xac, 0xdb, 0xc9, 0xc3, 0xec, 0x8c, 0xfc, 0xd1, 0x2d, 0x1e, - 0xd6, 0x91, 0x87, 0x78, 0x49, 0x27, 0xd0, 0x5b, 0xc0, 0x7f, 0x12, 0xf5, - 0x7b, 0x54, 0xab, 0xfb, 0xfe, 0x8a, 0x93, 0x43, 0x5c, 0xe0, 0x3e, 0xb6, - 0xa8, 0x3c, 0xd7, 0x73, 0x32, 0xbc, 0xef, 0x9b, 0xe3, 0xdf, 0x39, 0x78, - 0xf9, 0x01, 0xd4, 0x4d, 0xbc, 0x1b, 0xa4, 0x7f, 0xe1, 0xf7, 0x36, 0xff, - 0xe2, 0x7c, 0xf6, 0x93, 0xe7, 0x81, 0xf4, 0x55, 0xf0, 0xe7, 0xe5, 0xd1, - 0x87, 0x58, 0x51, 0x6c, 0x44, 0xb8, 0x78, 0xc7, 0xce, 0x39, 0x2a, 0xff, - 0x6e, 0xf2, 0xd1, 0x96, 0xf0, 0xdc, 0xa5, 0x8e, 0xc8, 0x27, 0xf9, 0xe9, - 0x84, 0x4d, 0x90, 0x17, 0xce, 0x8f, 0xee, 0x25, 0xd8, 0xfe, 0xb8, 0x36, - 0x12, 0xdd, 0xa9, 0x7d, 0x9c, 0x3d, 0x8f, 0x74, 0x76, 0x37, 0x7e, 0x88, - 0x83, 0xb4, 0x23, 0xbe, 0x22, 0x9e, 0x88, 0x8f, 0xfc, 0x44, 0xbc, 0x28, - 0x1b, 0x5d, 0x97, 0x9f, 0x60, 0x5d, 0xc0, 0x4f, 0x69, 0x21, 0x0d, 0x9d, - 0x90, 0xa7, 0x11, 0x6d, 0xa4, 0xba, 0xde, 0x1d, 0xc7, 0x0f, 0x5c, 0xc6, - 0xd5, 0xb1, 0x06, 0xef, 0xa1, 0x48, 0x97, 0x7f, 0x3b, 0xb2, 0xa4, 0x8d, - 0x34, 0xf8, 0x9d, 0xa9, 0xae, 0xb9, 0x8d, 0x88, 0xde, 0x5a, 0x9d, 0x46, - 0xbf, 0xbc, 0x2b, 0xff, 0x0c, 0xf6, 0xa9, 0x3b, 0xf8, 0xbb, 0x14, 0x55, - 0x47, 0xb1, 0x6f, 0xb9, 0xd5, 0x73, 0xa2, 0xbf, 0xd3, 0xd9, 0x1f, 0xe6, - 0x43, 0x51, 0x6d, 0x1c, 0xd5, 0x59, 0xea, 0x9e, 0x7d, 0xaf, 0xe7, 0x68, - 0xc8, 0x4f, 0x99, 0x33, 0x05, 0x3a, 0x08, 0xf1, 0xde, 0x91, 0xcf, 0x91, - 0x26, 0x3e, 0x47, 0xc1, 0xe7, 0x3e, 0xf0, 0x39, 0x76, 0x8b, 0xcf, 0x5b, - 0xb6, 0x97, 0x29, 0xc3, 0xf6, 0x46, 0xd6, 0xb5, 0xbd, 0x55, 0x3a, 0xab, - 0x73, 0x83, 0xfb, 0x9a, 0x91, 0x86, 0x2f, 0xc7, 0x9d, 0x8f, 0x53, 0x37, - 0xb7, 0xcb, 0x99, 0x85, 0xbb, 0xd5, 0xb7, 0x11, 0xaf, 0x2a, 0x77, 0x94, - 0x4b, 0xf5, 0x80, 0x9f, 0x1f, 0x2f, 0xb1, 0x3d, 0x12, 0xea, 0x8a, 0x3a, - 0xcb, 0x3a, 0x25, 0xb9, 0x1b, 0x2f, 0xbf, 0xf8, 0x9c, 0x76, 0xa5, 0x12, - 0x9d, 0x4f, 0x5a, 0x78, 0xc6, 0xae, 0xe5, 0x29, 0xfa, 0x6e, 0x32, 0x66, - 0x45, 0xf7, 0x67, 0x22, 0xfc, 0xfe, 0xc0, 0xef, 0x75, 0x6b, 0xbf, 0x13, - 0xf0, 0x7c, 0x8a, 0x78, 0xd7, 0x53, 0x3c, 0x9f, 0xc6, 0x9c, 0x66, 0x19, - 0x5c, 0xd8, 0xa4, 0x9e, 0xe4, 0x98, 0xe7, 0xd0, 0x2f, 0x4c, 0xd0, 0x0c, - 0xee, 0xdd, 0x6a, 0x4b, 0xbe, 0x5c, 0x74, 0x36, 0x06, 0xe7, 0x28, 0x64, - 0xba, 0x6c, 0xf1, 0xfe, 0x0a, 0x31, 0x8c, 0x67, 0x83, 0xb2, 0xb5, 0x16, - 0xf5, 0x5c, 0x39, 0xd0, 0x0e, 0x1d, 0xb3, 0xdd, 0xd6, 0xcb, 0xfb, 0x0a, - 0xca, 0xbc, 0xa0, 0xf6, 0x21, 0xd2, 0x71, 0xf4, 0x7d, 0xae, 0x55, 0x96, - 0xc3, 0xbb, 0xad, 0xc5, 0x8a, 0xef, 0xbf, 0x83, 0x3c, 0xfc, 0x34, 0x74, - 0x5f, 0xae, 0xff, 0xcc, 0x5f, 0x4e, 0xf1, 0x6f, 0xa5, 0x22, 0x9b, 0xd8, - 0xd1, 0xcb, 0x7b, 0x20, 0xf8, 0x96, 0x1c, 0xaf, 0x87, 0x65, 0xbf, 0x70, - 0x9c, 0x7d, 0xff, 0x0d, 0xbe, 0x7d, 0xff, 0xf4, 0xaa, 0x9d, 0x02, 0xfe, - 0x17, 0x33, 0xe1, 0x9b, 0xdd, 0x90, 0x58, 0x00, 0x00, 0x00 }; + 0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c, + 0x1c, 0xc7, 0x75, 0x7f, 0x3b, 0xbb, 0xa4, 0x4e, 0xd4, 0x91, 0x5c, 0x1e, + 0x4f, 0xf4, 0x49, 0x66, 0x94, 0x5d, 0x71, 0x25, 0x5e, 0x2d, 0xc6, 0x5d, + 0x31, 0x57, 0x9b, 0x08, 0xce, 0xf1, 0x79, 0xef, 0x64, 0xb1, 0x86, 0x0a, + 0x51, 0x0d, 0x1d, 0x1b, 0x85, 0x6b, 0xb0, 0x47, 0x39, 0xae, 0xdb, 0x7e, + 0x90, 0x65, 0x1b, 0x30, 0xda, 0x10, 0xbe, 0x1c, 0xe9, 0x46, 0x75, 0x2f, + 0xdc, 0x8b, 0xc4, 0x98, 0x06, 0xfa, 0x07, 0x57, 0x92, 0xfa, 0x83, 0xe0, + 0xa0, 0x93, 0xe2, 0x26, 0xf5, 0x17, 0x57, 0x84, 0x2a, 0xc7, 0xf9, 0xe0, + 0x02, 0x4e, 0x63, 0x20, 0x06, 0xea, 0x16, 0xaa, 0xec, 0xd8, 0x46, 0x81, + 0xa2, 0x42, 0x1c, 0xd8, 0x46, 0xfc, 0x67, 0xfb, 0x7b, 0x33, 0xbb, 0xd4, + 0x91, 0x96, 0x6d, 0xa0, 0x1f, 0xfa, 0xa5, 0x3b, 0xc0, 0x61, 0x67, 0x66, + 0xe7, 0xbd, 0x79, 0xf3, 0xfe, 0xbf, 0x59, 0x4a, 0x7f, 0x90, 0xa4, 0x2e, + 0x0a, 0x5b, 0x37, 0x7e, 0xd6, 0x91, 0xc7, 0x8f, 0xde, 0x3c, 0x76, 0xf3, + 0x28, 0xd1, 0x97, 0x47, 0xf5, 0x1b, 0x12, 0x22, 0x9a, 0x8f, 0x5b, 0xdc, + 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, + 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, + 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, + 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, + 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, + 0x2d, 0x6e, 0x71, 0xfb, 0xff, 0xde, 0x74, 0x22, 0x93, 0x9f, 0xdd, 0xe1, + 0x8f, 0x12, 0x22, 0xbf, 0xfa, 0x90, 0xe7, 0x50, 0x42, 0xcf, 0xbf, 0x34, + 0x33, 0xed, 0x10, 0x15, 0x9a, 0x7b, 0xac, 0x22, 0x7d, 0x14, 0x54, 0xd2, + 0x06, 0xf1, 0xfc, 0x17, 0xf2, 0x1f, 0x3e, 0xf1, 0xfc, 0xad, 0xf6, 0xd5, + 0x86, 0x4e, 0x09, 0x33, 0x3f, 0xb7, 0xd7, 0xdc, 0x4d, 0x89, 0x41, 0xc0, + 0xfc, 0xf5, 0xf0, 0x7f, 0xf4, 0x50, 0x0f, 0x5d, 0xc3, 0xe3, 0x24, 0xe8, + 0xb2, 0xfe, 0x9c, 0xe6, 0xb5, 0x82, 0xe0, 0xa4, 0x1b, 0x04, 0x3f, 0xc6, + 0xef, 0x2d, 0x17, 0x63, 0xff, 0xe3, 0xa0, 0x60, 0xe8, 0x24, 0x9c, 0xbf, + 0xd4, 0xbc, 0xe5, 0x2e, 0xaa, 0x2e, 0x1a, 0x34, 0xeb, 0xa7, 0xe9, 0x98, + 0x5f, 0xd1, 0x4a, 0xad, 0x9a, 0xb6, 0xef, 0xf4, 0xbc, 0x76, 0xe7, 0xe9, + 0x63, 0xda, 0xfe, 0xd3, 0x75, 0xcd, 0x3b, 0x4d, 0x15, 0xb1, 0x37, 0x49, + 0x05, 0xf3, 0x8c, 0x56, 0x6c, 0x0d, 0x68, 0xde, 0x89, 0x0f, 0xc9, 0x73, + 0x6d, 0xf3, 0xf7, 0xc8, 0x28, 0x80, 0x16, 0xf2, 0x6a, 0x41, 0xe0, 0xb9, + 0x06, 0x15, 0xd2, 0x41, 0x20, 0xf2, 0xc1, 0x13, 0x5e, 0xce, 0x31, 0x85, + 0x96, 0xa6, 0x6a, 0x6b, 0x00, 0x78, 0x93, 0x5a, 0x71, 0xd1, 0xd0, 0x4a, + 0x7e, 0x70, 0xc1, 0x73, 0x69, 0x50, 0xa7, 0x20, 0x98, 0x73, 0x77, 0x65, + 0x0e, 0xd3, 0x29, 0xe0, 0x6d, 0x02, 0x1f, 0x99, 0x22, 0xcf, 0xf4, 0x31, + 0x9d, 0x4c, 0x72, 0x45, 0x2b, 0x0e, 0x47, 0xf4, 0x91, 0xc5, 0xf4, 0x97, + 0x57, 0x04, 0xe8, 0xdc, 0x42, 0xe5, 0x86, 0x49, 0x53, 0x2b, 0x1b, 0xd7, + 0x5f, 0x0e, 0x9e, 0x1f, 0x36, 0xe9, 0x5c, 0xcb, 0xae, 0x54, 0x28, 0x41, + 0x73, 0xbe, 0x45, 0x22, 0x4f, 0x05, 0x2f, 0x37, 0x48, 0x17, 0x5a, 0x19, + 0xfa, 0x41, 0xcb, 0xc9, 0x54, 0x69, 0x13, 0x95, 0xd3, 0x69, 0x3a, 0xdf, + 0x4a, 0xe3, 0x8c, 0xc1, 0x05, 0xe1, 0x38, 0x66, 0x15, 0x6b, 0xab, 0xad, + 0x97, 0xf8, 0xdf, 0xbf, 0x98, 0xd3, 0x39, 0x09, 0x53, 0x01, 0xdd, 0xe1, + 0x5a, 0x3e, 0x87, 0x5c, 0x2b, 0xcf, 0xa2, 0xd6, 0x52, 0x65, 0x3a, 0x87, + 0xb9, 0xd6, 0x1d, 0x6b, 0xfc, 0x2d, 0xa4, 0xf9, 0x69, 0x52, 0xd5, 0xef, + 0x00, 0x6f, 0xb8, 0x3f, 0x88, 0xb3, 0xee, 0xd0, 0xbc, 0xc5, 0x7f, 0x65, + 0xbc, 0x69, 0x41, 0x3b, 0x30, 0x1e, 0xc4, 0x98, 0xfb, 0xbb, 0x32, 0x65, + 0x02, 0x8f, 0x5b, 0x49, 0x8c, 0x99, 0xce, 0x20, 0xd8, 0xef, 0x92, 0x59, + 0x75, 0x7b, 0x01, 0x6b, 0x51, 0xd5, 0xed, 0x01, 0xbe, 0x0e, 0xea, 0x73, + 0xf8, 0x7c, 0xbc, 0xe7, 0x66, 0xcc, 0x07, 0xdd, 0x7a, 0x3e, 0x08, 0xa6, + 0x73, 0xd4, 0xa3, 0xe6, 0xf6, 0x48, 0x1c, 0x53, 0x13, 0x1a, 0xd6, 0xbd, + 0xc3, 0x7b, 0x24, 0x52, 0x79, 0xee, 0xf3, 0x33, 0x47, 0xde, 0xfc, 0x8e, + 0x90, 0xa6, 0x0c, 0x68, 0xba, 0x31, 0xec, 0x43, 0x0e, 0x3e, 0xf8, 0xe1, + 0xde, 0x80, 0xb1, 0xf6, 0x45, 0xe0, 0xc9, 0x56, 0x89, 0xf7, 0xe8, 0xa7, + 0xa5, 0x34, 0x89, 0x2b, 0x6e, 0x5f, 0xb8, 0xae, 0x07, 0xb4, 0x46, 0xfa, + 0x30, 0x40, 0x73, 0x8b, 0xcc, 0xf3, 0x1a, 0x64, 0x24, 0x68, 0xe7, 0x2d, + 0x15, 0xad, 0xd0, 0x3a, 0x86, 0xbe, 0x41, 0xd3, 0x4e, 0x70, 0x61, 0xce, + 0x9d, 0xd7, 0x8a, 0xa7, 0x4f, 0x69, 0xa5, 0xd3, 0xcf, 0x69, 0xfb, 0x5a, + 0x2f, 0x76, 0x53, 0x97, 0x8d, 0xd3, 0x27, 0xe8, 0x49, 0x5f, 0x23, 0xa6, + 0x73, 0x09, 0x3c, 0x2c, 0x98, 0x15, 0x32, 0x9c, 0x1e, 0xed, 0x4e, 0xe0, + 0xe9, 0x70, 0xfe, 0x2c, 0x49, 0x3d, 0x3a, 0x6d, 0x72, 0xa2, 0xb5, 0x69, + 0xfa, 0x73, 0xd0, 0x74, 0xd1, 0xdd, 0xca, 0x7c, 0xeb, 0x55, 0x30, 0xa9, + 0x90, 0x0e, 0xd6, 0x2f, 0x96, 0x9f, 0x6d, 0x7a, 0xba, 0xa0, 0xd2, 0xc2, + 0x5f, 0xf4, 0x57, 0x47, 0xb6, 0xf0, 0x3a, 0xd8, 0xc2, 0xd5, 0x87, 0xa6, + 0x1d, 0xaf, 0xcf, 0xa0, 0x8a, 0x29, 0xc8, 0x36, 0x8b, 0xf4, 0x45, 0x9a, + 0x73, 0x89, 0x8a, 0x35, 0xec, 0xeb, 0x18, 0xe0, 0x8f, 0x03, 0xfe, 0xec, + 0xaa, 0xe8, 0xe2, 0x1e, 0xa0, 0xa9, 0x68, 0x46, 0xc8, 0xcb, 0x25, 0xba, + 0x4b, 0xc2, 0x8b, 0xbc, 0x0b, 0x5d, 0xed, 0xe2, 0x3e, 0xf6, 0x4e, 0xc8, + 0xbd, 0xf5, 0xbc, 0x93, 0x59, 0x26, 0xd2, 0x44, 0x7e, 0x0f, 0xf0, 0xb1, + 0x0e, 0xf3, 0xba, 0x79, 0xd0, 0xc9, 0xf4, 0x73, 0xdf, 0x01, 0x4c, 0x02, + 0xfa, 0xde, 0xdd, 0x46, 0x2b, 0xe8, 0x49, 0x33, 0xbf, 0x99, 0x7f, 0xf2, + 0xac, 0xda, 0xb5, 0xb3, 0x7e, 0x10, 0x0c, 0x8f, 0x1a, 0xf4, 0x63, 0x79, + 0x66, 0xb6, 0x37, 0x5e, 0x97, 0x0e, 0xf5, 0x23, 0x01, 0x9d, 0x22, 0xad, + 0xec, 0x9a, 0x6b, 0xb8, 0xca, 0x44, 0x42, 0xcf, 0x27, 0xa9, 0x28, 0xe9, + 0x1b, 0xc3, 0x5e, 0x6c, 0x87, 0xb0, 0x27, 0x87, 0xcf, 0xc2, 0x73, 0x79, + 0xd8, 0xbb, 0xcd, 0x7d, 0x2a, 0xd7, 0xd9, 0xf6, 0x99, 0xb6, 0x55, 0x5b, + 0xfe, 0xd3, 0x2c, 0x89, 0x4f, 0x0c, 0xe8, 0xd4, 0x4b, 0x13, 0xee, 0x87, + 0x81, 0xd8, 0x8d, 0xf7, 0x23, 0x19, 0xd0, 0x66, 0x5b, 0xb0, 0xca, 0x94, + 0x4e, 0x1a, 0xe8, 0xde, 0x93, 0x31, 0xc9, 0xc1, 0xd9, 0xc0, 0xdf, 0x89, + 0x55, 0x30, 0xff, 0xd3, 0xe8, 0x54, 0x78, 0x41, 0x66, 0xc1, 0x03, 0x8d, + 0x9e, 0xfb, 0x65, 0xc9, 0x33, 0x13, 0xe7, 0xd7, 0xe7, 0x99, 0xbf, 0x5d, + 0xb0, 0x0b, 0x8d, 0xca, 0x2e, 0xe3, 0x8e, 0x70, 0x08, 0x1a, 0xbe, 0xa5, + 0x1d, 0x47, 0x24, 0x5f, 0xd6, 0x5d, 0x83, 0x46, 0x47, 0x79, 0x2d, 0xaf, + 0xe3, 0xf5, 0xf6, 0x98, 0x25, 0x3e, 0x08, 0xf6, 0xae, 0xdb, 0xd3, 0x21, + 0x31, 0x0f, 0x9a, 0x95, 0x2c, 0xc0, 0xc3, 0xcf, 0x5b, 0xcb, 0x72, 0xd8, + 0xc8, 0x6f, 0x5e, 0xdb, 0xbe, 0x0e, 0xfa, 0x3c, 0xc0, 0x34, 0x9c, 0x4c, + 0x2a, 0x3b, 0x8d, 0x68, 0x8a, 0x64, 0xa9, 0x85, 0x38, 0x3e, 0xeb, 0x1c, + 0xbc, 0x1e, 0xfe, 0xc3, 0x87, 0xff, 0x80, 0x4f, 0x3c, 0xef, 0xc3, 0xbf, + 0xf8, 0xec, 0x6f, 0x2c, 0x7a, 0x7e, 0x18, 0xfe, 0xf1, 0x9a, 0x7f, 0x42, + 0x1b, 0x47, 0x5f, 0x90, 0x0e, 0xff, 0x34, 0xdb, 0x10, 0xb0, 0x73, 0xf8, + 0x8a, 0x15, 0x9e, 0x83, 0x5f, 0x58, 0x29, 0xe1, 0xe9, 0x50, 0xb5, 0xc9, + 0x7a, 0x18, 0xf9, 0x61, 0xf6, 0x57, 0x19, 0xf8, 0x26, 0xf6, 0x47, 0xec, + 0xb7, 0x78, 0x6d, 0x10, 0x94, 0x5c, 0x86, 0x0d, 0x20, 0x47, 0xb6, 0xbb, + 0x24, 0x89, 0x54, 0x45, 0x3b, 0x34, 0x0c, 0x7b, 0xbc, 0x89, 0x7d, 0x0b, + 0xdb, 0xe5, 0x8d, 0x44, 0x9d, 0xbc, 0xdf, 0xaf, 0xbb, 0xd5, 0xbf, 0xd9, + 0xdb, 0x84, 0x35, 0xf2, 0xd9, 0xa3, 0xc6, 0x66, 0xe8, 0x97, 0xf8, 0xbd, + 0x6d, 0x15, 0x68, 0x57, 0x38, 0xe6, 0xfe, 0x1a, 0xbd, 0xae, 0xb8, 0x25, + 0x41, 0x3b, 0x4f, 0x29, 0x7f, 0xba, 0x73, 0x09, 0x9a, 0x71, 0x4a, 0xd1, + 0xb8, 0xf3, 0x6c, 0xe4, 0x57, 0x93, 0xc0, 0x07, 0xfa, 0xfc, 0xb5, 0x18, + 0x82, 0xf6, 0x9e, 0x06, 0xd3, 0xc2, 0xdc, 0x46, 0x5e, 0xb0, 0x2f, 0x67, + 0xfb, 0x34, 0xdb, 0xed, 0x73, 0x2f, 0xec, 0xd3, 0xed, 0x24, 0xdb, 0xfd, + 0x27, 0xd8, 0xe7, 0xb7, 0x5d, 0x0d, 0xbc, 0x21, 0xba, 0x54, 0xcb, 0xc0, + 0x3f, 0x18, 0x99, 0xd7, 0x69, 0x97, 0x35, 0x0b, 0xbd, 0x3c, 0xc9, 0x73, + 0x4d, 0xcc, 0x49, 0x3f, 0xae, 0xfc, 0xc7, 0x65, 0xfd, 0xbb, 0xa0, 0x2b, + 0x08, 0x66, 0x81, 0xb3, 0x3c, 0xa2, 0x87, 0xb6, 0x18, 0xcd, 0x5f, 0x45, + 0x3c, 0xf4, 0x7e, 0x43, 0xa7, 0x4a, 0xb6, 0x83, 0xec, 0xec, 0x12, 0x70, + 0x4f, 0xbb, 0xca, 0xee, 0xd9, 0x36, 0x96, 0x81, 0x7f, 0xce, 0x1f, 0x86, + 0x5f, 0x60, 0xbb, 0x01, 0x5d, 0xc0, 0xbf, 0x0c, 0xfc, 0x73, 0xad, 0x0e, + 0xfa, 0x96, 0x11, 0xc5, 0xd9, 0xe8, 0x3c, 0xdb, 0xb0, 0x2c, 0xda, 0xf7, + 0x08, 0xdd, 0xe5, 0xa7, 0xe0, 0x73, 0xd8, 0x27, 0x57, 0xb3, 0xb0, 0x2b, + 0xad, 0xea, 0xf2, 0xde, 0x3a, 0x2d, 0xaf, 0xad, 0xa1, 0x42, 0x55, 0xd9, + 0x6c, 0xc1, 0x1b, 0xae, 0x64, 0x74, 0xe9, 0x7b, 0x88, 0xee, 0x84, 0xad, + 0x2e, 0x3b, 0x3c, 0xe6, 0x79, 0x35, 0x37, 0x5e, 0x1b, 0xd0, 0x8a, 0xec, + 0xbf, 0x86, 0x3f, 0x04, 0x7d, 0x6a, 0xee, 0xb7, 0x6b, 0x0f, 0xb1, 0x8c, + 0x70, 0x16, 0xb2, 0xaa, 0xee, 0x7f, 0x06, 0xd0, 0xdf, 0x75, 0x30, 0xd7, + 0xc7, 0x63, 0x8f, 0x2b, 0x9d, 0x25, 0x6d, 0xbf, 0x23, 0x06, 0x3a, 0x43, + 0x9f, 0xb7, 0x1f, 0x93, 0xfb, 0x6a, 0xd5, 0xfe, 0x4e, 0xfa, 0x50, 0xe7, + 0x18, 0x7c, 0x85, 0xc8, 0xf0, 0x6a, 0xbb, 0xc1, 0x8f, 0x6a, 0x5f, 0xdb, + 0x5c, 0xa2, 0x54, 0x0b, 0xe8, 0xa2, 0xab, 0x60, 0x30, 0x4e, 0x16, 0x6b, + 0x62, 0x20, 0x41, 0x6b, 0x63, 0x93, 0x61, 0x56, 0x68, 0x77, 0x76, 0x99, + 0x24, 0x6c, 0x7f, 0xe2, 0x1a, 0x6c, 0xba, 0x54, 0xab, 0xf6, 0xb5, 0x8d, + 0x33, 0x45, 0xe0, 0x12, 0x7b, 0xd7, 0x60, 0x07, 0xaf, 0xc1, 0x6e, 0x25, + 0xab, 0x8f, 0xe1, 0xc5, 0xc0, 0xe6, 0x6b, 0xb8, 0xad, 0x90, 0x9e, 0xfe, + 0xcd, 0xd7, 0x70, 0x38, 0x8c, 0xb3, 0x6d, 0x9c, 0x65, 0x9c, 0x3b, 0xaf, + 0xe1, 0x1c, 0x59, 0x4f, 0xcf, 0x11, 0x82, 0x0f, 0x4a, 0x74, 0xe6, 0x69, + 0xef, 0xa5, 0xda, 0xd0, 0xc4, 0x5d, 0x84, 0xf8, 0x38, 0xb2, 0x29, 0xf4, + 0xe1, 0xc6, 0x5e, 0x0f, 0xbc, 0x32, 0x88, 0x7d, 0xa2, 0x46, 0x55, 0xc8, + 0xf9, 0x8f, 0x9a, 0xb4, 0xf7, 0x62, 0xd3, 0x08, 0x75, 0x89, 0x75, 0xe2, + 0x6d, 0xd8, 0x58, 0x72, 0xca, 0x40, 0x0c, 0xbf, 0x20, 0x6d, 0x8c, 0x26, + 0xaa, 0x35, 0xaa, 0x6c, 0xcf, 0x3f, 0x11, 0x40, 0x17, 0xa7, 0xe0, 0xd3, + 0xc0, 0xe3, 0xe4, 0x98, 0x97, 0xc3, 0x7c, 0x93, 0x6d, 0x0b, 0x7e, 0x05, + 0xb0, 0xd0, 0xb5, 0x84, 0x3e, 0xbf, 0xeb, 0x55, 0x4f, 0xe7, 0x7d, 0x2c, + 0xe4, 0x5c, 0x89, 0x84, 0x98, 0xbf, 0x1a, 0xb0, 0x9e, 0x4d, 0x8f, 0x5c, + 0x45, 0x8e, 0x63, 0x92, 0x37, 0x06, 0xff, 0x01, 0x7d, 0x9f, 0x6d, 0x11, + 0x72, 0x82, 0x3f, 0xed, 0x55, 0x36, 0xf6, 0x9d, 0xad, 0xea, 0x49, 0x06, + 0xfb, 0xf2, 0xe9, 0x1c, 0xe7, 0x0f, 0x9d, 0x09, 0x2f, 0x37, 0xbe, 0x4d, + 0x3f, 0x7b, 0x60, 0x9b, 0x38, 0x5b, 0xd9, 0x26, 0x10, 0x03, 0x60, 0x53, + 0xc2, 0xcb, 0xa1, 0x7f, 0x36, 0xb2, 0xa1, 0x0c, 0x6c, 0x88, 0x69, 0x65, + 0x3a, 0x7f, 0x04, 0x7b, 0x95, 0xb4, 0xd2, 0x84, 0x0f, 0x9a, 0x46, 0x3f, + 0x82, 0x9e, 0xe0, 0x2c, 0xf0, 0x81, 0x05, 0x70, 0x49, 0x8c, 0xfe, 0x2a, + 0xb4, 0x67, 0xee, 0xbf, 0x1b, 0xa8, 0x78, 0x72, 0x30, 0xdc, 0xff, 0x17, + 0xa1, 0x0f, 0x88, 0x70, 0x31, 0x9e, 0xac, 0x36, 0x81, 0x5c, 0x68, 0xa2, + 0x65, 0x68, 0xec, 0xcf, 0x8b, 0x3e, 0xe7, 0x30, 0x9c, 0xbf, 0x3c, 0x1e, + 0xfa, 0x45, 0xce, 0x5b, 0x92, 0x21, 0x4f, 0x73, 0x51, 0x5c, 0x94, 0xf6, + 0x86, 0x18, 0x65, 0x95, 0x5d, 0x99, 0xd3, 0x68, 0xd3, 0xb9, 0x24, 0xd6, + 0x61, 0xae, 0x85, 0x73, 0xc3, 0x2f, 0x21, 0x0f, 0xe2, 0xdc, 0x14, 0xeb, + 0x3b, 0x43, 0x9b, 0xbf, 0x44, 0x65, 0xf8, 0x54, 0xc3, 0xe1, 0xf7, 0x5e, + 0x2f, 0x75, 0x61, 0xdc, 0xc4, 0x5e, 0xf0, 0x13, 0xba, 0xe4, 0x33, 0x62, + 0x41, 0xfa, 0x06, 0xce, 0xaf, 0xb0, 0xd6, 0xc2, 0x5a, 0xf6, 0xbb, 0xbc, + 0xf6, 0x3c, 0xe8, 0xc0, 0xb8, 0xc9, 0x30, 0xec, 0xa3, 0x82, 0xf7, 0xbc, + 0xdc, 0x1e, 0x73, 0x82, 0x12, 0x21, 0x5e, 0xab, 0x0d, 0xef, 0xc6, 0xb5, + 0x9c, 0xd3, 0x04, 0x17, 0x74, 0x87, 0xf1, 0x47, 0x79, 0x18, 0xd1, 0xf4, + 0x09, 0xe4, 0x71, 0x4e, 0x07, 0xe2, 0x14, 0x8f, 0x86, 0x4c, 0x75, 0xce, + 0x08, 0xe6, 0x81, 0xfe, 0xf5, 0xe3, 0xbb, 0x53, 0xd7, 0xfc, 0x23, 0x5b, + 0x17, 0x15, 0x10, 0x1f, 0xc0, 0x27, 0x6b, 0x8a, 0x73, 0xbf, 0x62, 0x53, + 0xa2, 0xc4, 0xdc, 0x18, 0x7c, 0xa2, 0xca, 0xa3, 0x2e, 0xf8, 0x1b, 0xe5, + 0x66, 0x82, 0xd7, 0x05, 0xf0, 0xd7, 0x82, 0xfe, 0x8c, 0x03, 0x96, 0x8e, + 0x00, 0x07, 0xc7, 0x6a, 0x57, 0xe4, 0x53, 0x54, 0x36, 0x39, 0xa7, 0xe8, + 0x64, 0xfa, 0x0a, 0x6c, 0xfb, 0x22, 0xbf, 0x19, 0x73, 0xdc, 0x7f, 0xac, + 0x57, 0xc9, 0xab, 0x9b, 0xc7, 0x13, 0x22, 0xdf, 0xbb, 0x61, 0xfe, 0x9f, + 0xbb, 0x15, 0x6d, 0x72, 0x8c, 0xf9, 0x7f, 0xdb, 0x30, 0xfe, 0xe3, 0xd4, + 0xfa, 0xf1, 0xdd, 0xdb, 0x42, 0xfd, 0x43, 0xff, 0xf1, 0x90, 0x5e, 0xd0, + 0xb6, 0x46, 0x6b, 0x94, 0x2b, 0x53, 0x5d, 0x20, 0x5f, 0xf4, 0x72, 0xbb, + 0xac, 0x2a, 0x6c, 0xaa, 0xd4, 0x02, 0xdd, 0x6b, 0x71, 0x6c, 0x6d, 0x4d, + 0xe5, 0xda, 0x1a, 0xe5, 0xe7, 0x4b, 0xad, 0x00, 0x79, 0x56, 0x7b, 0xcc, + 0xcb, 0xa2, 0x5f, 0xc1, 0x3e, 0x05, 0x9a, 0xf6, 0x2f, 0x16, 0x84, 0x73, + 0x4c, 0xe6, 0x89, 0xc2, 0x79, 0x4a, 0x2b, 0x2d, 0x73, 0xfe, 0x08, 0x5b, + 0x72, 0x64, 0xdd, 0x80, 0x98, 0x72, 0x5c, 0x2b, 0x9c, 0x5e, 0x40, 0xfe, + 0xb8, 0x82, 0xdf, 0x19, 0xfc, 0x9a, 0xf8, 0x45, 0xf9, 0xfb, 0x33, 0xc8, + 0xff, 0xa5, 0x7f, 0x45, 0x2c, 0x50, 0xfb, 0xff, 0x62, 0x05, 0x3a, 0xb6, + 0x90, 0xa6, 0x6f, 0x3b, 0xa2, 0x5f, 0x28, 0x9f, 0x52, 0x40, 0xde, 0x6b, + 0xbe, 0x4d, 0xbf, 0x13, 0xe6, 0x50, 0x44, 0xaf, 0xd7, 0xc1, 0xc7, 0x91, + 0xfd, 0xa1, 0xbe, 0x66, 0x1f, 0xf4, 0xa4, 0xef, 0x0c, 0x73, 0x24, 0xe4, + 0x6a, 0x05, 0xb9, 0xea, 0xfb, 0xe0, 0x8d, 0x46, 0x6f, 0x41, 0x7f, 0x5e, + 0xaf, 0x77, 0x81, 0x1e, 0x87, 0xca, 0x93, 0xf6, 0x18, 0x69, 0x43, 0xe6, + 0x26, 0xad, 0x0b, 0x36, 0x0c, 0xfb, 0x96, 0x63, 0x4a, 0x74, 0xe4, 0xcf, + 0xcd, 0x2c, 0xd5, 0x04, 0xd6, 0x22, 0xef, 0xc9, 0xa1, 0x0f, 0xd9, 0x5f, + 0xa9, 0x33, 0x9c, 0xa0, 0x37, 0xea, 0x3a, 0xbd, 0x89, 0xbc, 0xeb, 0x2d, + 0xe7, 0xdc, 0x0c, 0x62, 0xd6, 0x00, 0xe2, 0x03, 0x6a, 0x98, 0x5d, 0xec, + 0xa3, 0x77, 0x1a, 0x78, 0x96, 0xf0, 0xbb, 0x13, 0x79, 0xe3, 0xf5, 0x61, + 0x3e, 0x6d, 0x3d, 0xd3, 0x96, 0x00, 0x0c, 0xaf, 0x37, 0x40, 0x5b, 0x0f, + 0xe4, 0x6f, 0x9b, 0x53, 0xf4, 0xcb, 0x5e, 0x99, 0xab, 0x68, 0x3c, 0xaf, + 0xfc, 0xd2, 0x27, 0xe7, 0x99, 0xcf, 0x3a, 0x74, 0x9c, 0xc7, 0xfc, 0x8e, + 0xfd, 0x27, 0xe3, 0xb3, 0xc7, 0x0a, 0x38, 0xcc, 0x95, 0xba, 0xea, 0x47, + 0x73, 0xa4, 0x45, 0x31, 0x8c, 0xfd, 0x62, 0x89, 0x0a, 0x92, 0xef, 0x13, + 0x24, 0x65, 0xb0, 0x4e, 0x9e, 0x94, 0x30, 0xf2, 0xf5, 0x99, 0x39, 0x87, + 0xe5, 0x0a, 0xff, 0x56, 0x8b, 0xe4, 0xca, 0x32, 0xea, 0xa4, 0x6a, 0xfd, + 0x29, 0xc8, 0x55, 0x84, 0xf5, 0x01, 0xec, 0x7b, 0x81, 0xe5, 0x8b, 0xba, + 0xb1, 0x8e, 0xbc, 0xa7, 0x4e, 0x29, 0x55, 0xdf, 0x1c, 0x47, 0x5d, 0x00, + 0xf9, 0xd5, 0x16, 0x80, 0x03, 0x36, 0x5a, 0x5b, 0xc1, 0x13, 0xb5, 0x48, + 0xed, 0x0c, 0x9e, 0x83, 0x78, 0x36, 0x59, 0x37, 0xc3, 0x3c, 0xe3, 0x13, + 0xf4, 0xc0, 0x9e, 0x4a, 0x6c, 0x4f, 0xf4, 0x8f, 0xad, 0x3c, 0xfd, 0x43, + 0x6b, 0x8c, 0x7e, 0xd4, 0xca, 0xd1, 0x0f, 0x5b, 0x2e, 0xfd, 0x7d, 0x6b, + 0x84, 0x9e, 0x6d, 0x65, 0xb9, 0x96, 0x43, 0xce, 0x64, 0x71, 0xce, 0x44, + 0x0f, 0xfa, 0xb7, 0xc3, 0xde, 0x59, 0xfe, 0xe7, 0x66, 0x0a, 0xcd, 0x21, + 0x2a, 0x9f, 0x80, 0x6f, 0x76, 0x6f, 0xe3, 0x1a, 0x94, 0x1e, 0x73, 0xb9, + 0x86, 0xe8, 0xe0, 0xf7, 0xa8, 0x23, 0xe0, 0xbb, 0xe1, 0xcb, 0xa6, 0xd2, + 0xf6, 0x39, 0x4f, 0x1f, 0x08, 0x7d, 0xc0, 0x5d, 0x29, 0xea, 0xc2, 0x5e, + 0xf0, 0x7f, 0x17, 0x9f, 0x86, 0x0d, 0xc8, 0x1a, 0x28, 0x01, 0x5f, 0xc3, + 0x79, 0x80, 0xc1, 0x76, 0xcc, 0xf5, 0x87, 0xe5, 0xe9, 0x5c, 0x17, 0xb2, + 0x3d, 0xeb, 0x08, 0x1a, 0x0c, 0x37, 0x69, 0xb2, 0xdc, 0x0c, 0x87, 0x7d, + 0x6a, 0x21, 0xf4, 0x6f, 0x89, 0x50, 0x2f, 0x4d, 0xcc, 0x3f, 0x15, 0xfa, + 0xe3, 0x8d, 0xfb, 0x20, 0x56, 0x20, 0x97, 0x54, 0xeb, 0x18, 0x56, 0x0b, + 0x61, 0xfb, 0xc3, 0xb9, 0x24, 0xf8, 0xed, 0x52, 0xd9, 0x7f, 0x43, 0xe3, + 0x1c, 0x5b, 0x38, 0xcc, 0xff, 0x11, 0x8c, 0x2f, 0x87, 0xe3, 0xaf, 0xd0, + 0xf4, 0x22, 0x81, 0xd6, 0xd7, 0xb4, 0xa2, 0x1c, 0x8f, 0x61, 0x2c, 0x30, + 0xd6, 0xb9, 0x6e, 0xe0, 0x0c, 0x23, 0xc5, 0xba, 0x2e, 0x9c, 0x71, 0xf0, + 0x71, 0x12, 0xbf, 0x82, 0xfc, 0x3d, 0xe2, 0x0f, 0x15, 0xde, 0x41, 0xbc, + 0xd0, 0x3a, 0xa2, 0xdc, 0x67, 0x3b, 0x6a, 0xcf, 0x20, 0x38, 0x84, 0x5a, + 0xdd, 0x4a, 0x19, 0xf4, 0x2f, 0xf3, 0xb6, 0x79, 0x48, 0xcc, 0xe1, 0x4c, + 0x41, 0x30, 0xe1, 0xd8, 0x95, 0x82, 0xe8, 0xa6, 0x9f, 0x1f, 0xe7, 0xb8, + 0x5b, 0x9f, 0x79, 0x01, 0xba, 0xd7, 0x58, 0xe9, 0xa4, 0x46, 0xc3, 0xa0, + 0x2b, 0xa3, 0x43, 0xa0, 0xd3, 0xa4, 0x46, 0x33, 0x85, 0x5c, 0x6e, 0x33, + 0xa1, 0x3c, 0x94, 0x0e, 0x43, 0xcf, 0x67, 0xa5, 0x8f, 0xf6, 0x1c, 0x3c, + 0x9b, 0x1f, 0xf4, 0xae, 0x3f, 0x73, 0x09, 0xf4, 0xf7, 0xa0, 0x0a, 0xd9, + 0x2e, 0xe5, 0x5c, 0xf6, 0x87, 0x4c, 0x4f, 0x20, 0x6e, 0x19, 0x43, 0xe6, + 0x7e, 0xf1, 0xab, 0xe0, 0x0e, 0x83, 0x65, 0xf7, 0xaa, 0xac, 0x77, 0x64, + 0x9c, 0xc3, 0x7e, 0x4b, 0x2b, 0xaf, 0x81, 0x16, 0x93, 0x9e, 0x6d, 0x6e, + 0x0f, 0xc7, 0x96, 0xe4, 0xc5, 0xb3, 0xcd, 0x2e, 0xfa, 0x61, 0x63, 0x0b, + 0x2d, 0x37, 0xf8, 0x7d, 0x27, 0x2d, 0x35, 0x86, 0xae, 0x1e, 0x15, 0x03, + 0xb4, 0x7a, 0xe3, 0x4d, 0xe6, 0x57, 0x05, 0xf2, 0x82, 0xc9, 0x8f, 0xe9, + 0xbd, 0xd1, 0x5e, 0xfa, 0xe9, 0x3d, 0x76, 0xfd, 0x7e, 0x01, 0x1b, 0x18, + 0x4d, 0xb2, 0x6d, 0xa3, 0xcf, 0xf3, 0xf6, 0x55, 0x4b, 0xb0, 0x6e, 0xff, + 0x04, 0x3c, 0xb5, 0x8f, 0x29, 0x3b, 0x60, 0xdc, 0x8c, 0x17, 0xba, 0xe1, + 0xbc, 0x08, 0x9c, 0x78, 0xd7, 0x1c, 0x02, 0xae, 0x17, 0x25, 0x2f, 0x0e, + 0xb9, 0xf6, 0x55, 0x42, 0x0e, 0x79, 0xc5, 0x19, 0xca, 0x0a, 0xb1, 0x9d, + 0x1a, 0x99, 0x9b, 0xcc, 0xf3, 0xf0, 0xff, 0xa8, 0xab, 0x2a, 0x97, 0xa9, + 0x3e, 0x73, 0xc9, 0x61, 0xfd, 0x67, 0xbf, 0xf1, 0x12, 0xf2, 0x4e, 0x93, + 0x4e, 0x34, 0xd9, 0x5f, 0x32, 0x2e, 0xce, 0xfd, 0x77, 0x9b, 0x5f, 0x13, + 0x9c, 0x23, 0xe0, 0x1d, 0xe6, 0xf5, 0x2f, 0xb1, 0x9c, 0x3b, 0x18, 0x36, + 0x6b, 0x89, 0x60, 0x03, 0x8f, 0x86, 0xcc, 0x5d, 0x82, 0xf7, 0xfb, 0x6f, + 0xec, 0xfb, 0x2e, 0x68, 0x1d, 0x02, 0x2c, 0xe2, 0x65, 0xa6, 0x7d, 0x8f, + 0x57, 0xe4, 0x1e, 0xc7, 0x9b, 0xc8, 0xf3, 0xd6, 0xf6, 0xc0, 0x5c, 0x53, + 0xe0, 0x9c, 0x86, 0x94, 0xcb, 0x95, 0x51, 0xe6, 0xef, 0x6d, 0x7d, 0x9c, + 0x63, 0xea, 0xf9, 0xbf, 0x09, 0xa2, 0x5a, 0xf3, 0x95, 0xf9, 0x49, 0xf8, + 0xe7, 0x20, 0xa8, 0xee, 0x1e, 0x52, 0x71, 0x68, 0x90, 0xdf, 0x1f, 0x90, + 0xb2, 0xa8, 0x8a, 0x4e, 0xba, 0xc3, 0xb0, 0x00, 0xcb, 0x73, 0x2f, 0x87, + 0x72, 0x84, 0x11, 0x75, 0xa1, 0xdf, 0x8c, 0xf4, 0x32, 0x05, 0x1d, 0xdb, + 0x63, 0x1e, 0x0a, 0x63, 0x32, 0xc7, 0xb4, 0x9f, 0x42, 0xe7, 0xac, 0x14, + 0xeb, 0x4d, 0xaa, 0xef, 0x9a, 0xde, 0xf0, 0xbb, 0xfa, 0x8c, 0x07, 0xda, + 0x8a, 0x0b, 0x9d, 0x54, 0xaa, 0x27, 0x90, 0x03, 0x19, 0x34, 0x97, 0xc3, + 0x18, 0x3a, 0x54, 0x6a, 0xb0, 0xce, 0x57, 0x42, 0x9d, 0x4f, 0x86, 0xb8, + 0x4f, 0x82, 0x17, 0xb6, 0xb5, 0x2a, 0xb8, 0x76, 0xda, 0x26, 0xeb, 0x5f, + 0x1d, 0xb6, 0x5c, 0xae, 0x71, 0xed, 0x89, 0xfc, 0xdb, 0x3c, 0x37, 0x33, + 0xed, 0x18, 0xa0, 0x6b, 0x44, 0x2b, 0xb7, 0x1c, 0xad, 0xec, 0x33, 0x7d, + 0xbb, 0x41, 0xb7, 0x26, 0x6b, 0xdc, 0xa5, 0xd6, 0x7b, 0xc1, 0xd2, 0xee, + 0x4d, 0xe8, 0x43, 0xe7, 0x27, 0x58, 0xae, 0x5f, 0x60, 0xba, 0xac, 0x82, + 0x60, 0x3e, 0xa7, 0xe9, 0xd4, 0xf0, 0xdf, 0xf5, 0x72, 0x3e, 0x75, 0x7a, + 0x98, 0xf1, 0x83, 0x8e, 0x74, 0x9a, 0x96, 0x7d, 0xde, 0xa3, 0x3e, 0xc3, + 0x3c, 0x2c, 0x2f, 0x98, 0xf4, 0x88, 0x94, 0xdb, 0x6b, 0xd2, 0xa6, 0xcb, + 0x2b, 0xb0, 0xa5, 0xd4, 0x90, 0x79, 0x94, 0xec, 0xab, 0x17, 0x75, 0xbb, + 0x3e, 0x05, 0x7b, 0x5e, 0x5a, 0xd4, 0x69, 0xa7, 0xac, 0xb1, 0x58, 0x36, + 0xf6, 0x31, 0x58, 0x7c, 0x78, 0xf6, 0x43, 0x6d, 0x67, 0xef, 0xa1, 0x4b, + 0x4f, 0xff, 0x16, 0x7c, 0x0d, 0xf3, 0xd5, 0xb0, 0x0e, 0x23, 0x9f, 0x58, + 0x40, 0xee, 0x51, 0x45, 0x6e, 0x5c, 0xc8, 0x30, 0x6c, 0xc4, 0xef, 0xad, + 0x92, 0xff, 0x42, 0xf2, 0x7f, 0x07, 0x55, 0xa5, 0x0d, 0x65, 0xe4, 0x3b, + 0x01, 0x1c, 0xea, 0x1d, 0x8f, 0x91, 0x2b, 0xc9, 0x77, 0xf7, 0x2a, 0x38, + 0xf6, 0x11, 0x19, 0x7e, 0x77, 0x14, 0x7b, 0x32, 0x8f, 0xa3, 0xf9, 0x6e, + 0x52, 0x36, 0x14, 0xf1, 0x1d, 0x89, 0x44, 0x33, 0x4d, 0xbf, 0x8b, 0x9a, + 0x67, 0xb2, 0x39, 0x48, 0xa5, 0xa6, 0x05, 0x19, 0xcc, 0xf4, 0xf1, 0xd9, + 0x8a, 0x2b, 0x38, 0x8f, 0x60, 0x5a, 0xef, 0xa5, 0xc3, 0x7e, 0x44, 0x4f, + 0x32, 0xa4, 0x6f, 0x32, 0x1c, 0x27, 0x42, 0x1a, 0xda, 0xf1, 0x25, 0x81, + 0x0b, 0x31, 0x3e, 0xf7, 0x57, 0x21, 0x1e, 0xf6, 0x1f, 0xa0, 0x75, 0x32, + 0x43, 0x2b, 0x3e, 0xd3, 0xb1, 0x85, 0xaa, 0x69, 0xee, 0x1f, 0x80, 0x9e, + 0x31, 0x9e, 0x4d, 0x9c, 0xc7, 0xac, 0xe3, 0xf1, 0x91, 0x66, 0x05, 0x3c, + 0x66, 0xfe, 0xf2, 0xba, 0x24, 0x2d, 0x7d, 0x85, 0xe5, 0xb7, 0x07, 0xf9, + 0x3b, 0xeb, 0xc2, 0x96, 0x50, 0xaf, 0xd4, 0x9e, 0xa5, 0x85, 0x1e, 0xc8, + 0x8a, 0xf7, 0xed, 0xa2, 0xbb, 0x61, 0xef, 0xc5, 0x06, 0xef, 0x3f, 0x09, + 0x3d, 0x7a, 0x59, 0xee, 0x5f, 0x5a, 0x19, 0x08, 0xe1, 0x19, 0xb6, 0x67, + 0x03, 0x6c, 0x27, 0xed, 0xab, 0x9b, 0xd7, 0x81, 0xff, 0x7d, 0xc0, 0x0b, + 0x3a, 0x99, 0x63, 0x78, 0xc6, 0x83, 0x75, 0x8d, 0xf4, 0x67, 0xe0, 0x49, + 0xc9, 0x5a, 0xbe, 0xd8, 0xe8, 0xa4, 0x62, 0x3d, 0xc2, 0xc5, 0x78, 0x3e, + 0x46, 0xad, 0x7b, 0x9f, 0xc4, 0x35, 0x2d, 0x71, 0xe1, 0x7d, 0x83, 0x7d, + 0xcd, 0xad, 0x80, 0x47, 0xbd, 0xee, 0x80, 0xb6, 0x54, 0x37, 0x2d, 0xc9, + 0x7a, 0xbd, 0x4b, 0xf9, 0x98, 0xd4, 0x66, 0xbc, 0xdf, 0x02, 0x5b, 0xdf, + 0x83, 0x3c, 0xa6, 0x07, 0x73, 0xd6, 0x86, 0xb9, 0x8d, 0xf4, 0x27, 0x36, + 0xd0, 0xdf, 0x89, 0x75, 0xfd, 0xd8, 0x53, 0xad, 0x2b, 0x61, 0xdd, 0xec, + 0x02, 0x6c, 0x82, 0x73, 0xf3, 0x34, 0xc7, 0xe4, 0x1b, 0x25, 0x2d, 0xb3, + 0x2b, 0xef, 0xe1, 0x5c, 0x03, 0x80, 0x8d, 0xc6, 0x8a, 0x0f, 0x75, 0xe0, + 0xf9, 0x5e, 0x43, 0xde, 0x4b, 0x40, 0x06, 0x9b, 0x53, 0x7c, 0xf6, 0x6a, + 0xe3, 0xf3, 0x78, 0x76, 0x63, 0x1b, 0xbf, 0x98, 0x57, 0x4c, 0x2f, 0xd3, + 0x0a, 0x3d, 0x25, 0xd8, 0x9b, 0x8b, 0x9a, 0x2f, 0xa5, 0x53, 0x29, 0x87, + 0x78, 0xee, 0xf3, 0x5d, 0x2d, 0xdb, 0xe5, 0xa0, 0xaa, 0x0b, 0x1c, 0x8e, + 0xeb, 0x86, 0x3c, 0xfb, 0xe1, 0x15, 0xbe, 0xaf, 0xb5, 0x10, 0x4f, 0xed, + 0x2c, 0xe1, 0xec, 0x0f, 0xaf, 0x38, 0xf4, 0x68, 0x33, 0x4b, 0x47, 0x9b, + 0xb6, 0x79, 0x3f, 0x7c, 0x40, 0x79, 0xed, 0x1e, 0x77, 0x57, 0x8a, 0xfd, + 0x96, 0x81, 0x9c, 0xb3, 0xc3, 0x51, 0x39, 0x48, 0x95, 0xeb, 0xb1, 0x05, + 0x9b, 0xef, 0x68, 0xcc, 0x06, 0x6d, 0xcc, 0x53, 0xfe, 0x2f, 0x73, 0x14, + 0xde, 0x9f, 0xfd, 0x34, 0x72, 0x12, 0x1f, 0x39, 0x89, 0x8f, 0x9c, 0xc4, + 0x47, 0x4e, 0xe2, 0x23, 0x27, 0xf1, 0x91, 0x93, 0xf8, 0xc8, 0x49, 0x7c, + 0xe4, 0x24, 0xc8, 0xff, 0x55, 0x5d, 0x30, 0x8e, 0x5c, 0x1b, 0xfe, 0xcb, + 0xff, 0x6a, 0x98, 0x53, 0x44, 0x31, 0x99, 0xe7, 0x56, 0x37, 0x79, 0x6e, + 0x74, 0x4f, 0x7c, 0x00, 0x73, 0x13, 0x61, 0xee, 0xc3, 0x6b, 0xa2, 0x98, + 0xcd, 0xeb, 0x68, 0xcc, 0x43, 0xbd, 0x59, 0x98, 0xe4, 0xdc, 0x48, 0xc5, + 0x2a, 0x95, 0x97, 0xbf, 0x8a, 0xfc, 0xc8, 0x42, 0x7e, 0x34, 0x88, 0x5c, + 0x88, 0xef, 0xb5, 0xa3, 0xfb, 0xa3, 0x82, 0x76, 0xc8, 0x1f, 0xd7, 0xbe, + 0xe6, 0x73, 0xde, 0xee, 0x58, 0x65, 0x21, 0x16, 0xfa, 0x29, 0xa0, 0xe2, + 0xe8, 0xb7, 0x90, 0x23, 0x7f, 0x4f, 0xde, 0x95, 0x4d, 0x0c, 0xb3, 0xcc, + 0x27, 0x3e, 0x25, 0x4f, 0x8e, 0xf8, 0xab, 0xee, 0xf8, 0xc4, 0x12, 0xf3, + 0x8f, 0xa8, 0xef, 0x2c, 0x18, 0x7e, 0x36, 0x41, 0xa9, 0x53, 0x5b, 0x30, + 0x67, 0x52, 0xbf, 0xbc, 0x27, 0x82, 0x28, 0xcf, 0xfe, 0x1a, 0xf2, 0x72, + 0x48, 0x9c, 0xe5, 0xdb, 0x04, 0xc6, 0xcb, 0xfe, 0xb5, 0x32, 0x53, 0x6c, + 0x54, 0xa4, 0x4e, 0x1d, 0x6a, 0x96, 0x90, 0x3f, 0xf5, 0xf6, 0x53, 0x97, + 0x81, 0x1a, 0x2a, 0xc2, 0xcd, 0x38, 0x7f, 0x99, 0x92, 0xb5, 0xcd, 0xd9, + 0x35, 0x79, 0x42, 0xd6, 0xbc, 0x4f, 0x65, 0xa6, 0x5a, 0xb7, 0x33, 0x5c, + 0xd7, 0x82, 0xd6, 0x99, 0x27, 0x81, 0x63, 0x19, 0x39, 0x81, 0x2e, 0xf7, + 0xae, 0xcc, 0xcc, 0xd6, 0xd5, 0x5d, 0x95, 0xa2, 0x01, 0xf1, 0x2f, 0xd7, + 0x45, 0xfa, 0x92, 0xba, 0xb3, 0x12, 0x12, 0x96, 0xe1, 0x18, 0xde, 0x00, + 0x1c, 0xcb, 0x2d, 0x0b, 0x58, 0x96, 0x1d, 0xd3, 0x50, 0x99, 0xa9, 0x34, + 0xda, 0x69, 0x60, 0x3c, 0x8c, 0x37, 0x3a, 0x0f, 0x9f, 0x25, 0x45, 0xe2, + 0x54, 0x10, 0x94, 0x47, 0x07, 0xc3, 0x3a, 0x12, 0xf5, 0xe3, 0x09, 0x43, + 0xea, 0xb9, 0x1a, 0x7f, 0x53, 0xc6, 0x29, 0x4b, 0xf0, 0x3c, 0x3f, 0xf1, + 0x2e, 0xf7, 0x24, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0x8a, 0x70, 0x6d, 0x77, + 0x1b, 0x3f, 0x3b, 0xc2, 0xfd, 0x98, 0x26, 0x3e, 0xe7, 0x65, 0xec, 0xc5, + 0x74, 0xf1, 0x1a, 0x13, 0xb4, 0x41, 0x96, 0xfe, 0xff, 0x96, 0xf7, 0xed, + 0x67, 0x62, 0x9e, 0x1a, 0x80, 0xe1, 0xf5, 0x8c, 0x23, 0x82, 0xc1, 0x8b, + 0xb3, 0x0a, 0x4e, 0xac, 0xdd, 0xed, 0x7d, 0xd6, 0xbe, 0xed, 0xb4, 0x46, + 0xfb, 0x47, 0x78, 0xb2, 0x4a, 0x6e, 0x6b, 0xf0, 0xf2, 0xff, 0x0a, 0xc3, + 0x13, 0xba, 0xf8, 0x89, 0x3b, 0xd2, 0x6c, 0x5b, 0x6d, 0x1c, 0xdd, 0x35, + 0x70, 0xcd, 0xcf, 0x35, 0x3c, 0x7f, 0x47, 0x68, 0xaf, 0x4b, 0x4b, 0x61, + 0x2c, 0x83, 0x2e, 0xaa, 0xbb, 0xd4, 0x70, 0x6c, 0x70, 0x6c, 0x43, 0xe3, + 0x1c, 0x3f, 0xb2, 0x91, 0xf6, 0x7b, 0x42, 0x95, 0x9b, 0x9c, 0x59, 0x8c, + 0x7c, 0x0e, 0xfc, 0xc1, 0xb0, 0x11, 0xfa, 0xed, 0x24, 0xfc, 0x56, 0x0f, + 0xed, 0x83, 0xbf, 0xb9, 0x13, 0xfe, 0x66, 0x3f, 0xea, 0xca, 0xf1, 0x95, + 0xf6, 0xfb, 0x57, 0xae, 0x65, 0xab, 0x74, 0x58, 0xca, 0xae, 0x12, 0xe8, + 0xce, 0xc7, 0x90, 0xdf, 0x2e, 0x99, 0xa3, 0x29, 0x79, 0xc2, 0x57, 0xba, + 0xfc, 0x2d, 0x62, 0xe3, 0x3d, 0x6f, 0x16, 0x7a, 0xdd, 0x55, 0x10, 0x32, + 0xff, 0x52, 0x7c, 0xab, 0x36, 0x14, 0xdf, 0xe0, 0x53, 0x81, 0xdf, 0xa0, + 0x4a, 0xd3, 0xa4, 0x0a, 0xf6, 0xad, 0x60, 0xdf, 0x0a, 0xea, 0xc1, 0xd9, + 0x66, 0xfb, 0x77, 0xaa, 0xee, 0xb0, 0xc6, 0x66, 0xd8, 0xa8, 0x6f, 0x86, + 0xe7, 0xd2, 0xda, 0x9e, 0xc7, 0xc0, 0xbb, 0x47, 0xc1, 0xbb, 0x23, 0xa8, + 0x83, 0xfe, 0x04, 0x75, 0xd0, 0x1f, 0xa2, 0x0e, 0x3a, 0x8c, 0x3a, 0x68, + 0x0a, 0x75, 0xd0, 0x7d, 0xb0, 0xfd, 0x7b, 0x61, 0xfb, 0x93, 0xb0, 0xfd, + 0x09, 0x79, 0xc7, 0x73, 0xc8, 0xdf, 0x78, 0xef, 0x11, 0xed, 0xc5, 0xed, + 0x4d, 0x22, 0x88, 0xaf, 0x7c, 0x62, 0x9c, 0x1a, 0x2d, 0xae, 0x87, 0x5c, + 0x79, 0x7f, 0x35, 0xed, 0x4e, 0x6a, 0x53, 0xc8, 0xb9, 0xef, 0x1f, 0xe1, + 0x3a, 0x29, 0xa5, 0xee, 0x2b, 0x73, 0xf6, 0x73, 0x1e, 0xd2, 0x2e, 0xe4, + 0x6d, 0x38, 0xb3, 0x7d, 0xa6, 0xa8, 0x47, 0x35, 0x4a, 0xdf, 0x5a, 0x8d, + 0xb2, 0x3c, 0xcf, 0x35, 0xca, 0xab, 0x6b, 0x35, 0xca, 0xf2, 0x3c, 0xd7, + 0x28, 0xaf, 0xac, 0xab, 0x51, 0xae, 0x3c, 0xfd, 0xf2, 0xba, 0x1a, 0xe5, + 0xca, 0xd3, 0x2f, 0x85, 0x63, 0xa6, 0x03, 0x7e, 0xc9, 0x0d, 0x69, 0x35, + 0x5d, 0x3c, 0x7b, 0xc3, 0x7c, 0xe1, 0xfb, 0xfd, 0xeb, 0xff, 0x1f, 0x3a, + 0x6e, 0x9d, 0x1a, 0x39, 0xdf, 0xd8, 0xaa, 0xea, 0x9a, 0xf6, 0xf9, 0xde, + 0xb6, 0xf9, 0x55, 0xf9, 0x6d, 0xb4, 0x5c, 0xdb, 0xfc, 0x3e, 0xbc, 0x27, + 0xad, 0x0c, 0xdb, 0xf5, 0x02, 0x7d, 0x1c, 0xf0, 0xf7, 0x3d, 0x4f, 0x74, + 0xc9, 0xef, 0x6a, 0x9e, 0xcc, 0x91, 0x61, 0xa3, 0xa3, 0x47, 0xb7, 0x2a, + 0x3b, 0xe6, 0x7e, 0x5a, 0x53, 0xbe, 0xf9, 0x41, 0xe0, 0x01, 0xaf, 0x7d, + 0x43, 0xde, 0xe1, 0xa8, 0xf3, 0xaa, 0xbb, 0x6c, 0x23, 0xbf, 0x8a, 0x38, + 0x03, 0x59, 0x4b, 0xdc, 0x5c, 0xf3, 0x71, 0x9d, 0x18, 0xf9, 0xef, 0x08, + 0xd7, 0xcf, 0xd2, 0x8a, 0xee, 0xdb, 0x50, 0xef, 0xf1, 0x9a, 0x68, 0xdc, + 0x5e, 0x1f, 0x26, 0xc3, 0xfb, 0xac, 0x55, 0x95, 0x13, 0x49, 0x7c, 0x46, + 0x88, 0xef, 0xbf, 0x02, 0xe5, 0x37, 0x18, 0xde, 0x6c, 0x83, 0x1f, 0x47, + 0x9e, 0xc6, 0x77, 0x2b, 0x9c, 0x6f, 0x19, 0xf4, 0xee, 0x7c, 0x37, 0xbd, + 0x73, 0x1c, 0xf9, 0xa6, 0x6b, 0x67, 0x5f, 0x46, 0xbd, 0x70, 0x8a, 0xf3, + 0xe2, 0x51, 0xa6, 0x73, 0xc8, 0x9a, 0x25, 0xab, 0x5f, 0xe5, 0xd1, 0x47, + 0xb4, 0x4f, 0xd2, 0x2d, 0xc2, 0x7d, 0x7e, 0xd6, 0xb6, 0x8f, 0xd5, 0xb6, + 0x4f, 0x81, 0xed, 0xad, 0xf1, 0x75, 0x9c, 0xb9, 0xb2, 0xfd, 0x26, 0x33, + 0x1d, 0xd6, 0x52, 0x8f, 0x8c, 0x6e, 0xa6, 0xfa, 0x80, 0x7d, 0xee, 0x15, + 0xe4, 0xda, 0xe5, 0x51, 0xcc, 0xa5, 0x87, 0xf0, 0x8e, 0xe7, 0xed, 0x06, + 0x09, 0xfb, 0x5c, 0x83, 0x90, 0x4c, 0x77, 0xd9, 0x15, 0xbe, 0x63, 0x4b, + 0x0b, 0xee, 0x4b, 0xda, 0x1a, 0xa1, 0xfd, 0x66, 0x2e, 0xe2, 0xcc, 0x53, + 0xa8, 0x99, 0x8e, 0xa8, 0xbb, 0xaf, 0x70, 0x9f, 0x5b, 0xb4, 0x8b, 0x32, + 0xaf, 0xcd, 0x69, 0x95, 0xb4, 0x3a, 0xe3, 0x37, 0x60, 0xeb, 0xba, 0x60, + 0xd8, 0x77, 0x81, 0x5b, 0xa3, 0xa5, 0xe3, 0xba, 0xbc, 0xeb, 0x2c, 0x8f, + 0xb2, 0xac, 0xf9, 0x79, 0x3d, 0xde, 0x45, 0x67, 0xfa, 0xdb, 0xf0, 0x4c, + 0x5f, 0x0a, 0x6b, 0xed, 0xe8, 0x4c, 0x09, 0x7a, 0x63, 0xde, 0x04, 0xec, + 0x08, 0xf8, 0x51, 0xa2, 0x95, 0x96, 0xf5, 0x39, 0x78, 0x6a, 0x6d, 0xbc, + 0x31, 0x36, 0xc8, 0x30, 0xaa, 0x59, 0xc0, 0x83, 0x89, 0x0c, 0xec, 0x70, + 0xba, 0x3f, 0xba, 0x83, 0xd5, 0x1d, 0xa1, 0xa9, 0xda, 0x9b, 0xe7, 0x07, + 0x61, 0x8b, 0x16, 0xec, 0x93, 0xf3, 0x9d, 0x12, 0xd7, 0x19, 0xe1, 0xf7, + 0x4b, 0xdb, 0x9c, 0xa4, 0x2c, 0x6a, 0x15, 0x3e, 0x7f, 0x9e, 0x96, 0x5b, + 0x11, 0x0d, 0x39, 0xd8, 0xe3, 0x18, 0x7e, 0x23, 0x78, 0xe7, 0xe2, 0xc7, + 0x75, 0x4e, 0x81, 0x1e, 0x93, 0x79, 0x34, 0xf2, 0xe4, 0x61, 0xa6, 0xef, + 0x00, 0xd6, 0xb3, 0x3e, 0xb3, 0x9e, 0x1e, 0x20, 0x6f, 0x80, 0x7d, 0x45, + 0x06, 0xb8, 0x01, 0xe3, 0xbf, 0x0e, 0x5b, 0x1f, 0xc4, 0xd3, 0x36, 0xcb, + 0xcc, 0x5b, 0x89, 0x3f, 0x08, 0xf4, 0x1c, 0x7f, 0x3b, 0x18, 0x0f, 0xc7, + 0x43, 0xe6, 0xdd, 0xac, 0x7b, 0x99, 0x1d, 0x74, 0x6e, 0x31, 0x8a, 0x61, + 0x33, 0xb0, 0x41, 0xbe, 0x53, 0x1d, 0x07, 0x5f, 0x78, 0xac, 0x85, 0xb1, + 0x0c, 0xf3, 0xcb, 0x0b, 0x38, 0x77, 0x9e, 0x4e, 0xa1, 0x66, 0xa7, 0x01, + 0x7e, 0x22, 0x57, 0xf5, 0xb7, 0x84, 0xfa, 0xbe, 0x1e, 0x5e, 0x77, 0xb8, + 0x3f, 0x0e, 0xfa, 0x8c, 0x36, 0x78, 0x86, 0x51, 0xb5, 0xc5, 0x45, 0x42, + 0x2c, 0xcd, 0x04, 0xb7, 0x8b, 0xfc, 0x7d, 0xf4, 0x80, 0x3c, 0x53, 0x9e, + 0x0e, 0x2f, 0x06, 0x81, 0x97, 0x1b, 0xca, 0x2e, 0x93, 0x9d, 0x7d, 0x92, + 0xf6, 0x98, 0xfb, 0x48, 0x97, 0xdf, 0xe0, 0x50, 0x13, 0xdf, 0xde, 0x91, + 0x0f, 0x82, 0x93, 0xa0, 0xfd, 0x05, 0xb9, 0xcf, 0x7d, 0xa0, 0x1f, 0xbc, + 0x92, 0xf5, 0x04, 0xd3, 0x0a, 0xde, 0xa4, 0x99, 0xde, 0x24, 0x1d, 0x6e, + 0x9d, 0x0f, 0x65, 0xf3, 0x28, 0x79, 0xfe, 0xdb, 0x3a, 0xdf, 0x47, 0x97, + 0x5b, 0x4f, 0x86, 0xb4, 0xe5, 0x41, 0x2f, 0xf6, 0x6f, 0xbd, 0x90, 0x66, + 0xdf, 0xc0, 0x32, 0xf7, 0x90, 0xf1, 0x79, 0xa3, 0xcf, 0x40, 0x07, 0x3f, + 0xcd, 0x0f, 0xa4, 0x68, 0xbd, 0x1f, 0x60, 0xb8, 0xd4, 0x75, 0x74, 0x85, + 0xe9, 0x20, 0xe9, 0x3f, 0x85, 0xb3, 0x19, 0xf4, 0x30, 0x3e, 0x7d, 0x83, + 0x2f, 0xa8, 0xc8, 0xe7, 0xaa, 0xce, 0xbe, 0x89, 0xe3, 0x14, 0xeb, 0x70, + 0x0f, 0xfc, 0x1f, 0x74, 0x10, 0x76, 0x5c, 0x5c, 0xe4, 0x3b, 0x85, 0x61, + 0xbe, 0x87, 0x3a, 0x53, 0x82, 0x6c, 0x97, 0xf8, 0xbb, 0x60, 0x5a, 0xe5, + 0x82, 0xaa, 0x76, 0xb2, 0xd8, 0x17, 0x32, 0xaf, 0xa5, 0x9f, 0x2c, 0xc9, + 0xef, 0x80, 0x29, 0xac, 0x09, 0xf0, 0x6c, 0xff, 0x9b, 0x88, 0x9f, 0x14, + 0xd4, 0xdf, 0x44, 0x84, 0xdf, 0x64, 0x1b, 0x2a, 0x07, 0x78, 0xb8, 0x69, + 0xd0, 0x54, 0x33, 0xfa, 0x1b, 0x09, 0x96, 0x83, 0x83, 0x3a, 0x3e, 0x8a, + 0xfb, 0x81, 0x8c, 0x2f, 0xd5, 0x75, 0xb2, 0xfc, 0x66, 0x98, 0xcf, 0x70, + 0xfe, 0xce, 0x3c, 0xc4, 0x78, 0x59, 0xc9, 0x6f, 0x49, 0xec, 0x84, 0xfc, + 0xc0, 0x73, 0xdf, 0x80, 0x2d, 0x65, 0xc2, 0x98, 0x6c, 0x72, 0x7d, 0x18, + 0xd6, 0xac, 0xdb, 0xa9, 0x3a, 0xc9, 0xef, 0x13, 0xf4, 0xfa, 0xfc, 0xa0, + 0x7c, 0x5f, 0xa6, 0x44, 0xf8, 0x9e, 0xc7, 0x29, 0x2a, 0xcb, 0xf7, 0xf7, + 0x86, 0xf8, 0x50, 0x63, 0xdd, 0x1b, 0x8d, 0x33, 0x90, 0xa3, 0x82, 0x9b, + 0x46, 0x2c, 0x7b, 0x0c, 0x71, 0x6c, 0x1a, 0x7c, 0x2f, 0x4e, 0x54, 0x68, + 0x87, 0xc3, 0x3a, 0x0e, 0x99, 0xa5, 0x58, 0xc7, 0x58, 0xbf, 0x18, 0xa6, + 0x17, 0x79, 0x26, 0xce, 0x3b, 0x4a, 0x53, 0x7a, 0xfe, 0xfd, 0x83, 0xe5, + 0x9a, 0x6d, 0x16, 0xe8, 0xa3, 0xc0, 0x33, 0x78, 0xbc, 0x7a, 0xf0, 0x61, + 0x75, 0x4f, 0x2f, 0x44, 0xfe, 0xd2, 0xc1, 0xb2, 0xea, 0xe3, 0xcc, 0xef, + 0x87, 0x7d, 0x86, 0xd3, 0xe5, 0xf7, 0xd3, 0x7f, 0xbf, 0xd5, 0xa0, 0x8b, + 0xb7, 0x06, 0xc1, 0xfd, 0xfc, 0x0d, 0x27, 0xac, 0x41, 0xd5, 0x77, 0x71, + 0x8e, 0x13, 0xa8, 0x37, 0x46, 0x2d, 0xad, 0x04, 0xdb, 0x3d, 0xe5, 0xa3, + 0x5e, 0x11, 0xf6, 0xd8, 0xaa, 0x30, 0x11, 0x7f, 0xb9, 0x96, 0xff, 0xcd, + 0x7e, 0xfe, 0x26, 0x3c, 0xe7, 0xf2, 0x9a, 0x6d, 0xea, 0xae, 0xea, 0xe6, + 0xdb, 0xa4, 0xcf, 0x25, 0x0a, 0xe3, 0xd0, 0xcd, 0xed, 0xf6, 0xd1, 0x9e, + 0x23, 0xb2, 0x5d, 0xd0, 0x94, 0x01, 0x7a, 0xaa, 0xb5, 0x28, 0xdf, 0xe2, + 0xef, 0xfd, 0xab, 0x07, 0xbf, 0xdb, 0xbc, 0x74, 0x70, 0x16, 0xf2, 0xe1, + 0x33, 0xcd, 0x36, 0x23, 0xfd, 0x8b, 0x72, 0x7e, 0xee, 0x23, 0xfe, 0xfb, + 0x88, 0xff, 0x3e, 0xe2, 0xbf, 0x8f, 0xf8, 0xef, 0x23, 0xfe, 0xfb, 0x88, + 0xff, 0xe0, 0xe1, 0x0f, 0xa0, 0x2f, 0xe7, 0xfd, 0x89, 0x30, 0xdf, 0x7a, + 0x7c, 0x2d, 0xdf, 0x3a, 0xd7, 0xe2, 0x6f, 0x3f, 0x92, 0x96, 0x4a, 0x85, + 0x54, 0xbe, 0x4a, 0x82, 0xf3, 0x9b, 0x28, 0x5f, 0xbd, 0xfe, 0x37, 0x0c, + 0x05, 0xc7, 0xb9, 0x1a, 0xc3, 0x55, 0x34, 0xe1, 0x30, 0x9c, 0xca, 0xd7, + 0xb8, 0x46, 0x5a, 0x0f, 0xc3, 0xdf, 0xc9, 0xd8, 0xb7, 0xa9, 0x6f, 0x34, + 0xea, 0x7b, 0xd0, 0xe3, 0x5f, 0xf7, 0x10, 0x8b, 0xcb, 0x4d, 0x19, 0x8f, + 0x31, 0x7e, 0x06, 0x63, 0x83, 0xf5, 0x8f, 0xdf, 0xdd, 0xc3, 0x75, 0x41, + 0xb9, 0x89, 0xbc, 0x68, 0x39, 0xca, 0x85, 0x00, 0xe7, 0xbf, 0xa9, 0x95, + 0xea, 0x2c, 0x67, 0x41, 0xb3, 0x69, 0x30, 0xc5, 0x69, 0xaf, 0x75, 0x5e, + 0x96, 0xb5, 0x8e, 0xfa, 0x9b, 0x9e, 0x11, 0xd0, 0x16, 0xdd, 0xfd, 0x12, + 0xe9, 0xf3, 0x69, 0xf9, 0x77, 0x00, 0x29, 0x67, 0x58, 0xfe, 0x3d, 0x42, + 0x1f, 0xf6, 0x11, 0xf3, 0x3b, 0xdb, 0xee, 0x56, 0xa9, 0xa0, 0x7c, 0x76, + 0xa7, 0xfa, 0x3b, 0x08, 0x91, 0x86, 0xed, 0xde, 0xb6, 0x0d, 0x67, 0x83, + 0x5c, 0x5f, 0xdd, 0x2a, 0xf3, 0x67, 0xf8, 0xd1, 0x93, 0xc3, 0x7d, 0x03, + 0xd4, 0xb3, 0x9d, 0x4e, 0x0d, 0x73, 0xad, 0xb5, 0x19, 0xf8, 0x78, 0xad, + 0x9d, 0x2d, 0x88, 0xed, 0x74, 0x7a, 0x11, 0x7e, 0x76, 0xd1, 0x76, 0x59, + 0x97, 0x97, 0x86, 0xd3, 0xf0, 0xcf, 0x63, 0x03, 0x1c, 0x9f, 0x97, 0x5b, + 0xac, 0x2b, 0x7d, 0x80, 0x1f, 0x84, 0x5e, 0x6e, 0x82, 0x3d, 0x09, 0xec, + 0x1f, 0xe1, 0xfe, 0xb9, 0xc4, 0xdd, 0xe7, 0xec, 0xd9, 0x26, 0x75, 0x43, + 0xd8, 0xa6, 0x25, 0x40, 0xfb, 0x27, 0x6a, 0x44, 0x97, 0xf8, 0x6c, 0xb3, + 0x7e, 0xfb, 0xb7, 0xba, 0x37, 0xb5, 0x72, 0x9d, 0xff, 0x0e, 0x61, 0x98, + 0xf6, 0x41, 0xbf, 0x4c, 0xe7, 0x4d, 0xed, 0x81, 0xc6, 0xff, 0x14, 0x6e, + 0x75, 0xb1, 0x71, 0x5c, 0x55, 0xf8, 0xdc, 0x59, 0xaf, 0xed, 0x38, 0x6b, + 0x67, 0xe2, 0x6c, 0xec, 0xb5, 0x15, 0xc4, 0xce, 0x7a, 0x12, 0x4f, 0xb5, + 0x8e, 0x3a, 0xb6, 0x12, 0xb4, 0x42, 0x96, 0x58, 0xed, 0x7a, 0x5d, 0x87, + 0x92, 0xb2, 0x85, 0x50, 0x05, 0x09, 0x55, 0x96, 0x9d, 0xd2, 0x54, 0x80, + 0x90, 0xfa, 0x80, 0x78, 0xcb, 0x6a, 0x6d, 0x87, 0xa4, 0xec, 0x76, 0x6d, + 0x62, 0xd7, 0x2f, 0x3c, 0x2c, 0xeb, 0x75, 0x6a, 0xbb, 0x9b, 0xac, 0x42, + 0xfb, 0x50, 0x9e, 0x62, 0x99, 0x92, 0xc2, 0x4b, 0x85, 0xc4, 0x03, 0x02, + 0x54, 0xa9, 0x4a, 0xda, 0x34, 0x0f, 0x25, 0x11, 0xbc, 0x50, 0x0a, 0xd2, + 0xf0, 0x7d, 0x77, 0x66, 0x1d, 0x27, 0x50, 0x61, 0x69, 0x35, 0x77, 0xee, + 0xdc, 0x3b, 0x73, 0x7f, 0xce, 0xf9, 0xce, 0x77, 0xce, 0x3d, 0x66, 0x1b, + 0x1b, 0x65, 0xfa, 0xd3, 0xab, 0x6a, 0xa6, 0xda, 0x2b, 0x0b, 0x90, 0xe3, + 0xe2, 0x48, 0x38, 0x88, 0x97, 0x76, 0x05, 0xfa, 0x0c, 0xc7, 0xdf, 0xb7, + 0x57, 0x9a, 0x57, 0x16, 0xcd, 0x4e, 0xcd, 0xab, 0x1e, 0x7d, 0x76, 0x0a, + 0x63, 0x8a, 0x61, 0x1d, 0xba, 0xfb, 0x34, 0x36, 0x19, 0xbc, 0xef, 0x7f, + 0xec, 0xbe, 0xef, 0xb1, 0xfb, 0xc3, 0xff, 0xa3, 0x3d, 0xcb, 0x8f, 0xcb, + 0x03, 0xc7, 0x69, 0xa5, 0xf8, 0x95, 0x62, 0xc9, 0x36, 0x66, 0x4b, 0x56, + 0x9a, 0xbc, 0x20, 0x2b, 0x9e, 0xca, 0xba, 0xed, 0xc0, 0xbb, 0x76, 0x99, + 0x5f, 0x86, 0xcc, 0x63, 0x1e, 0x1d, 0x36, 0xcf, 0xb4, 0x13, 0x7d, 0xd4, + 0x99, 0x4e, 0x6c, 0x83, 0x61, 0x0f, 0xc5, 0xd0, 0xce, 0x7b, 0xc9, 0x4d, + 0x9a, 0xe7, 0x74, 0x1c, 0x86, 0x7c, 0xc6, 0x53, 0x45, 0x9d, 0x9f, 0xc1, + 0x36, 0x6d, 0x72, 0xc7, 0xce, 0xf4, 0x06, 0xf9, 0x3e, 0xf0, 0x5b, 0xc7, + 0xfa, 0xc8, 0x35, 0x5e, 0x74, 0x77, 0xeb, 0xcc, 0xdb, 0xc2, 0x3c, 0x2a, + 0x08, 0xcd, 0xb3, 0x22, 0xd5, 0xba, 0xc8, 0xeb, 0xf8, 0xfd, 0xae, 0x1e, + 0xf8, 0x0a, 0x8a, 0x3e, 0xf3, 0xb8, 0x6c, 0x55, 0xbe, 0x2c, 0x0d, 0xd8, + 0x9f, 0x4d, 0xd7, 0xf3, 0xee, 0xb9, 0x71, 0xbd, 0xe6, 0x3f, 0x29, 0x29, + 0x49, 0x8c, 0xd2, 0xbe, 0xb5, 0xcb, 0x4f, 0x97, 0xdb, 0x64, 0xdb, 0xb4, + 0xcc, 0x7b, 0xc2, 0x5c, 0xb6, 0x98, 0x4c, 0x45, 0x43, 0x9a, 0xa3, 0xca, + 0xb7, 0xc0, 0xa0, 0xf1, 0xec, 0xee, 0xf2, 0x33, 0x7d, 0x8c, 0x9d, 0x7c, + 0xb4, 0xcc, 0x7b, 0x03, 0x57, 0x43, 0x76, 0xec, 0x10, 0xb8, 0x2c, 0x40, + 0xc8, 0xe4, 0xba, 0x73, 0xbe, 0xcf, 0x71, 0x6c, 0xa8, 0xa3, 0x2f, 0xda, + 0x2e, 0xc5, 0xa3, 0xc0, 0x44, 0x35, 0xa4, 0x73, 0x8a, 0x76, 0xa2, 0x1a, + 0xa3, 0x43, 0x35, 0xe6, 0xc8, 0x99, 0xfb, 0x35, 0x5e, 0x67, 0xae, 0x7d, + 0x5f, 0xcf, 0x05, 0xe5, 0x42, 0xcd, 0xa5, 0xac, 0x9a, 0xb2, 0x09, 0x5d, + 0xdb, 0x68, 0x2e, 0xf5, 0x73, 0xaf, 0xb6, 0x9a, 0x3f, 0xe8, 0xf3, 0x7d, + 0x2d, 0xd6, 0xfd, 0xb0, 0xcf, 0xaf, 0x8b, 0x07, 0xbe, 0x13, 0x7d, 0xac, + 0x2a, 0xe6, 0xf6, 0xb2, 0x34, 0x57, 0x7f, 0x2c, 0x6f, 0x57, 0x7e, 0x24, + 0xbf, 0x5a, 0x3d, 0x0b, 0xfe, 0x61, 0x55, 0x0b, 0xb0, 0x27, 0x37, 0x9a, + 0x9e, 0x77, 0xc3, 0x3d, 0x03, 0x5f, 0xc1, 0xf3, 0xfe, 0xe0, 0x6e, 0x4b, + 0x62, 0xec, 0x3b, 0x98, 0x73, 0x1e, 0x3a, 0x44, 0x2c, 0x9c, 0x82, 0xbc, + 0x25, 0xfb, 0xa5, 0x2b, 0xa2, 0xe5, 0x64, 0x68, 0x2c, 0x8c, 0x39, 0x18, + 0x01, 0x27, 0xe7, 0x5c, 0x46, 0xfa, 0x29, 0x33, 0x46, 0xf3, 0x15, 0x7c, + 0x3f, 0x0c, 0xbd, 0xd8, 0x8f, 0x9f, 0x92, 0x7b, 0xa3, 0x18, 0xeb, 0x28, + 0x65, 0x2f, 0x2c, 0x89, 0x27, 0x31, 0x8f, 0x7c, 0x9b, 0xdc, 0x2f, 0x5d, + 0xe9, 0x63, 0x5c, 0xee, 0x7e, 0x89, 0x65, 0xe3, 0x4b, 0x3d, 0xe2, 0x49, + 0x1b, 0x6c, 0xf9, 0xfc, 0x09, 0x9f, 0x37, 0xfd, 0x5a, 0x0d, 0xa3, 0xbd, + 0x5d, 0x78, 0x47, 0x91, 0xe7, 0x15, 0xbc, 0x30, 0x78, 0x79, 0x0e, 0x7c, + 0x28, 0xd3, 0xbc, 0x20, 0x3b, 0xa3, 0x11, 0xb4, 0x21, 0x5f, 0xd1, 0x58, + 0x22, 0xd9, 0x12, 0x73, 0xb0, 0x98, 0x0f, 0x85, 0x31, 0x9e, 0x21, 0x6e, + 0x70, 0x8c, 0xed, 0x3c, 0xb7, 0x0b, 0xea, 0x6c, 0xc8, 0x08, 0xeb, 0x28, + 0xdf, 0x69, 0xcd, 0xa9, 0x60, 0x43, 0xf1, 0xbe, 0x11, 0xc9, 0xe8, 0x72, + 0x0f, 0xde, 0x77, 0x41, 0xe7, 0x25, 0xfa, 0xef, 0x4c, 0xa1, 0x0d, 0x71, + 0x26, 0x05, 0x2e, 0xf1, 0xa1, 0x9a, 0x00, 0xbd, 0x99, 0x29, 0xf5, 0xc9, + 0x84, 0xb9, 0x6f, 0xcf, 0x1c, 0x0b, 0xda, 0x57, 0x30, 0x8c, 0x91, 0x60, + 0x4c, 0x3d, 0x7b, 0xc6, 0xc4, 0xfe, 0xf8, 0xc1, 0xc7, 0xcd, 0x2c, 0x2f, + 0x02, 0xa7, 0x16, 0x7f, 0x9b, 0x71, 0x9f, 0x97, 0x6c, 0xb4, 0x5d, 0xfb, + 0x36, 0x35, 0xec, 0x4b, 0xb6, 0xc4, 0x78, 0xd4, 0xb7, 0x81, 0x43, 0xfb, + 0x82, 0x3a, 0xb6, 0x15, 0x23, 0x83, 0xb5, 0x4f, 0x6b, 0x3d, 0x64, 0xdd, + 0x17, 0x25, 0xb3, 0x98, 0x97, 0x49, 0xdd, 0x8f, 0x6b, 0x38, 0xa8, 0x79, + 0x08, 0x75, 0x35, 0x71, 0x08, 0x6b, 0x99, 0x0c, 0x07, 0x6d, 0xf7, 0x91, + 0xc9, 0xe3, 0xef, 0xd3, 0x40, 0x67, 0xf1, 0xec, 0x10, 0xf7, 0xa8, 0x5d, + 0x12, 0xdf, 0x84, 0xbd, 0x2c, 0xb5, 0xea, 0x23, 0xf2, 0x49, 0xe9, 0xb3, + 0x3e, 0x9e, 0x93, 0xfc, 0xb5, 0x64, 0xca, 0x47, 0x25, 0x7d, 0x7e, 0x3a, + 0x1d, 0x12, 0xeb, 0xbc, 0xef, 0x67, 0x1f, 0x9d, 0x9e, 0x57, 0x7c, 0x7e, + 0xf4, 0xfc, 0xba, 0xea, 0x44, 0xdb, 0x08, 0xda, 0x71, 0x1c, 0xa6, 0xe4, + 0x4a, 0x7f, 0xf7, 0x66, 0x8e, 0x79, 0xde, 0xa4, 0xce, 0xe1, 0x4a, 0x9a, + 0xf3, 0xaa, 0xc5, 0xcf, 0x1d, 0x29, 0x45, 0x3b, 0xf0, 0xad, 0xa4, 0xb9, + 0xae, 0x8e, 0x62, 0x3c, 0x2c, 0x1f, 0xa2, 0x4e, 0xc4, 0xb6, 0x85, 0xef, + 0xb7, 0xa6, 0xd6, 0x54, 0x32, 0x3e, 0xa4, 0xac, 0x74, 0x11, 0xbf, 0x36, + 0xa5, 0xcf, 0x1e, 0x63, 0x71, 0x05, 0xdd, 0xc5, 0x9c, 0xec, 0xe3, 0x9e, + 0x37, 0x65, 0xb3, 0x3e, 0x69, 0x46, 0x14, 0xe3, 0x26, 0x5d, 0xfa, 0x8c, + 0xf2, 0xd2, 0xe1, 0xa4, 0x79, 0x5c, 0x1d, 0x0c, 0xee, 0x53, 0xc0, 0xcc, + 0xdd, 0xf7, 0x9d, 0x5d, 0x53, 0xa6, 0x5c, 0x2e, 0x25, 0xe3, 0xb3, 0xca, + 0xca, 0xe3, 0x9d, 0xf9, 0x09, 0x45, 0xdc, 0x48, 0x9a, 0x5d, 0x8a, 0xb1, + 0xcd, 0x0e, 0x3d, 0xef, 0x29, 0xf4, 0x4f, 0xaa, 0xb6, 0x60, 0x3c, 0xdc, + 0xaf, 0xcb, 0xfd, 0xbe, 0xce, 0x10, 0x73, 0x06, 0x8c, 0x99, 0x45, 0xe6, + 0x83, 0xe9, 0x3c, 0x84, 0x74, 0x62, 0x8c, 0xf7, 0x86, 0x3c, 0x38, 0xf9, + 0x0f, 0xd4, 0xa1, 0x5c, 0x65, 0x9d, 0x13, 0xe8, 0xdb, 0x31, 0xcd, 0x9f, + 0x1f, 0x9c, 0x2c, 0xe8, 0xfc, 0xc4, 0x1d, 0x95, 0x08, 0xe6, 0xbd, 0xbb, + 0x67, 0xf1, 0x8c, 0xfb, 0x05, 0xbe, 0x67, 0x31, 0x34, 0xde, 0x21, 0xcc, + 0x07, 0xcd, 0x55, 0x5a, 0xb2, 0xc1, 0xd8, 0x00, 0xcf, 0xf7, 0x5b, 0x67, + 0xe5, 0x17, 0xc4, 0x18, 0xeb, 0xdc, 0x23, 0x27, 0xe0, 0x9d, 0xe0, 0xab, + 0x75, 0xbc, 0xa7, 0xb8, 0x2c, 0x05, 0xbf, 0xbf, 0x74, 0x32, 0xff, 0xb4, + 0x58, 0xff, 0xbc, 0x77, 0xf8, 0x36, 0x30, 0x87, 0xfb, 0x07, 0x27, 0x29, + 0x9f, 0x5c, 0x9b, 0xb8, 0x9a, 0xbc, 0xc2, 0xf1, 0x0c, 0x4a, 0x6e, 0x19, + 0xdc, 0x08, 0xbf, 0xf9, 0x65, 0x7f, 0xdf, 0xd6, 0xc1, 0xb3, 0x73, 0x25, + 0x53, 0xeb, 0xeb, 0xac, 0xcb, 0xb3, 0x0f, 0xe8, 0x8a, 0xce, 0x7b, 0x62, + 0x5f, 0xe6, 0x0a, 0x1e, 0xa1, 0x7d, 0x74, 0x6a, 0x12, 0x45, 0x5b, 0x72, + 0x56, 0xd6, 0x83, 0xbf, 0xc3, 0x66, 0x16, 0x5f, 0x8d, 0x08, 0x30, 0x39, + 0x15, 0x0f, 0x1d, 0x90, 0x79, 0xd7, 0x95, 0x46, 0xf3, 0x84, 0x5c, 0x6b, + 0x3a, 0xfa, 0x19, 0xed, 0xd9, 0xc2, 0x6b, 0xfa, 0x5c, 0x3a, 0xfe, 0xa1, + 0xb2, 0x9c, 0xab, 0xf0, 0x6b, 0xbe, 0x7b, 0x8c, 0x79, 0xc2, 0xe1, 0x81, + 0x87, 0x79, 0x70, 0xc0, 0x0e, 0x70, 0x8e, 0xb7, 0xc0, 0x39, 0xde, 0x04, + 0xe7, 0xf8, 0x25, 0x38, 0xf6, 0x8d, 0xca, 0x54, 0x80, 0xff, 0xd3, 0xc0, + 0x21, 0xda, 0x6a, 0xeb, 0x2c, 0xf6, 0x74, 0xba, 0x00, 0x19, 0xfc, 0x00, + 0xfe, 0xc7, 0x56, 0x25, 0x23, 0x1b, 0xab, 0x93, 0xb2, 0xb9, 0xea, 0xe7, + 0x1c, 0xbf, 0xcb, 0x3c, 0xad, 0x51, 0xee, 0x93, 0x03, 0x1c, 0xda, 0x27, + 0x89, 0xe3, 0xc4, 0x8f, 0x4e, 0x59, 0x2b, 0xaf, 0x69, 0x1c, 0x5a, 0x2b, + 0xb3, 0x1c, 0x12, 0x9d, 0xf3, 0x75, 0x66, 0x5b, 0x6a, 0xee, 0x16, 0xea, + 0xbb, 0x99, 0xdb, 0x15, 0xc4, 0xd6, 0x89, 0x97, 0x7f, 0x0e, 0xf6, 0x5e, + 0xe9, 0x5c, 0xb8, 0x19, 0xf3, 0x00, 0xda, 0xb5, 0xb0, 0x6b, 0xc8, 0x3f, + 0x27, 0x57, 0x7f, 0x41, 0x1b, 0x7c, 0x03, 0x9c, 0xf1, 0x2a, 0x6c, 0xc8, + 0x8e, 0x73, 0x40, 0x73, 0xbf, 0x1d, 0xe7, 0x88, 0xce, 0xad, 0xe5, 0x7b, + 0x8a, 0x65, 0x5b, 0xe6, 0xca, 0x56, 0xbc, 0x00, 0xf9, 0xbb, 0x06, 0xbf, + 0x6d, 0x03, 0x7b, 0xb0, 0x89, 0xb5, 0xd8, 0x6a, 0xd2, 0xce, 0xbf, 0xaf, + 0xb1, 0x77, 0xad, 0xf9, 0x27, 0xbc, 0xc7, 0x3a, 0x9b, 0x96, 0x3f, 0xf6, + 0x13, 0x03, 0x99, 0x8f, 0x97, 0xd5, 0xfd, 0xfd, 0x7e, 0x1b, 0x68, 0xbb, + 0xd9, 0x24, 0x1e, 0x8b, 0x5c, 0x2c, 0xd9, 0xb0, 0x25, 0x17, 0x63, 0xe4, + 0x00, 0x55, 0xd5, 0xea, 0xe7, 0x05, 0x63, 0xf6, 0xbc, 0xfd, 0x36, 0xc7, + 0xe5, 0x04, 0xb8, 0x4d, 0xdb, 0xbf, 0xad, 0xb9, 0x4d, 0xa9, 0xf2, 0xbc, + 0x5c, 0x5f, 0x4d, 0x05, 0x1c, 0x27, 0x2f, 0x6f, 0x80, 0xe3, 0x35, 0x2b, + 0xad, 0x1c, 0xed, 0x71, 0xac, 0x53, 0x45, 0xcd, 0x2d, 0x75, 0xc9, 0xa5, + 0x95, 0xa2, 0xba, 0xbc, 0x52, 0x52, 0xaf, 0x2c, 0x95, 0x55, 0x71, 0xc9, + 0xf3, 0xfe, 0xe9, 0xce, 0xc8, 0xdb, 0xab, 0x9e, 0x9c, 0x76, 0x8d, 0x81, + 0x90, 0xb4, 0xf2, 0xdf, 0x3c, 0xaf, 0x13, 0xd8, 0xbc, 0x75, 0xd8, 0xf3, + 0x9e, 0x18, 0x1d, 0x15, 0xe7, 0x30, 0x39, 0xca, 0x70, 0x8c, 0x39, 0xac, + 0xc4, 0x9c, 0x8c, 0x6d, 0x9f, 0xaf, 0x29, 0x05, 0x7c, 0x3b, 0xe0, 0xf3, + 0x97, 0x27, 0xbb, 0x83, 0x33, 0x8f, 0xb3, 0x2f, 0x31, 0x26, 0x1c, 0xfb, + 0xaf, 0x98, 0xb0, 0x29, 0xe7, 0xca, 0x58, 0x88, 0xae, 0xa8, 0x7c, 0xaf, + 0x1c, 0x79, 0xac, 0x6c, 0xe2, 0xea, 0x18, 0xc5, 0xf2, 0x7d, 0x6f, 0x48, + 0xc7, 0xfe, 0xc1, 0x49, 0x4c, 0xcf, 0x9b, 0x75, 0xf9, 0xbd, 0x03, 0x8c, + 0xc9, 0x98, 0xdd, 0xb0, 0xff, 0xa7, 0xb5, 0x7d, 0xae, 0xaa, 0x8c, 0x4d, + 0xfd, 0x8e, 0xca, 0x44, 0x19, 0x36, 0x5e, 0x31, 0x2f, 0x94, 0x5c, 0xc1, + 0x8a, 0xcd, 0x02, 0x3b, 0x66, 0x80, 0x37, 0x4f, 0xeb, 0xb3, 0xd1, 0x43, + 0x1a, 0x7b, 0xe6, 0x58, 0xce, 0x4b, 0xba, 0xe6, 0xf6, 0xea, 0xf5, 0xbb, + 0x7d, 0xad, 0x18, 0xf3, 0xf7, 0x1c, 0x7a, 0x9c, 0xe7, 0xf9, 0x40, 0xaf, + 0x64, 0xd7, 0xcf, 0x40, 0x27, 0x62, 0x58, 0xdb, 0xb0, 0xd6, 0x87, 0x1d, + 0xd8, 0xef, 0x1d, 0x27, 0x1c, 0x60, 0x6a, 0x27, 0xee, 0xd9, 0x6e, 0x12, + 0xfd, 0x3a, 0x24, 0xb3, 0xd4, 0xae, 0x71, 0xf5, 0xd1, 0xba, 0x34, 0x78, + 0x48, 0x0e, 0xe5, 0x10, 0xea, 0xe2, 0x41, 0x99, 0xdc, 0x6b, 0x1a, 0xe5, + 0x36, 0x5c, 0xd9, 0xe6, 0x28, 0x78, 0x05, 0xae, 0xbf, 0xc0, 0xfb, 0x46, + 0x31, 0xe6, 0xbc, 0x29, 0xef, 0x9d, 0xa4, 0x2d, 0x71, 0x0c, 0xe6, 0x1a, + 0xcf, 0xda, 0xb8, 0x36, 0xca, 0x2a, 0xbb, 0xc8, 0x32, 0xae, 0x55, 0xff, + 0xf9, 0x23, 0x98, 0x84, 0x3e, 0x99, 0x15, 0x1f, 0x93, 0xde, 0xdb, 0xc5, + 0x24, 0xd6, 0x75, 0xc8, 0xc4, 0x52, 0x5c, 0x9d, 0xba, 0x62, 0x42, 0xde, + 0xba, 0x24, 0xbb, 0x12, 0xd5, 0x7c, 0xb4, 0x06, 0x59, 0x5c, 0x87, 0x5c, + 0xad, 0x41, 0xa6, 0x32, 0x65, 0x2b, 0x35, 0xad, 0xe2, 0x3a, 0x2e, 0x30, + 0x05, 0x79, 0x0d, 0xbf, 0x4a, 0x2e, 0x4a, 0xfd, 0x75, 0xd0, 0x46, 0x68, + 0x47, 0xd3, 0x61, 0x65, 0x43, 0x0e, 0x21, 0x97, 0x65, 0x5f, 0x7f, 0xdf, + 0x51, 0x1a, 0x57, 0x53, 0x77, 0x24, 0xe9, 0xdc, 0x11, 0xcb, 0xdd, 0xc1, + 0xef, 0x37, 0xe2, 0xca, 0x55, 0xe8, 0xfb, 0xeb, 0xf8, 0x4e, 0xf8, 0x35, + 0x43, 0x8e, 0x0d, 0x6b, 0x9d, 0x4e, 0x49, 0xc8, 0x72, 0x36, 0xc5, 0xd7, + 0xf1, 0x75, 0xad, 0xe3, 0x90, 0x37, 0x60, 0x90, 0xaf, 0xd3, 0xe9, 0x40, + 0x46, 0xbf, 0x01, 0xfd, 0xb5, 0xe0, 0x95, 0xc5, 0x65, 0x1e, 0xfa, 0x7f, + 0x15, 0xcf, 0x6f, 0x36, 0x3f, 0x56, 0x73, 0x8b, 0x2a, 0xc8, 0x3f, 0x79, + 0x0e, 0x3c, 0xf9, 0xf7, 0x58, 0xbb, 0x1e, 0xcd, 0xdd, 0x13, 0xa3, 0x3c, + 0x07, 0xfb, 0xb7, 0xba, 0x64, 0x1f, 0x97, 0xdb, 0x23, 0x27, 0x50, 0xee, + 0xc6, 0xd5, 0xc0, 0x3a, 0x44, 0xf4, 0xf9, 0xf5, 0x5a, 0x69, 0xc4, 0x28, + 0xea, 0x33, 0xe6, 0x31, 0xf4, 0x25, 0x96, 0x1d, 0xc6, 0x73, 0xc6, 0x65, + 0x38, 0x37, 0x70, 0x26, 0x15, 0xd3, 0x39, 0xa1, 0x35, 0x70, 0x89, 0x75, + 0xbc, 0xef, 0x16, 0xe3, 0x7a, 0x0d, 0xe8, 0xf0, 0xc8, 0x67, 0x5e, 0x3a, + 0xca, 0xbc, 0xf3, 0xf7, 0x63, 0xbe, 0xfd, 0xfb, 0xc4, 0xbb, 0x6d, 0xcf, + 0xa5, 0x0c, 0xdc, 0x7c, 0x60, 0x02, 0xef, 0xc8, 0xdb, 0x61, 0x8b, 0xaa, + 0x5a, 0x7e, 0xd9, 0xce, 0xef, 0x5b, 0x6c, 0x24, 0xcd, 0x77, 0xc5, 0xef, + 0x3b, 0x6f, 0xd3, 0xee, 0x74, 0x00, 0x5f, 0xe2, 0x9a, 0x57, 0xde, 0xb2, + 0x0b, 0x40, 0x05, 0x2b, 0x3e, 0x05, 0x19, 0x6d, 0x17, 0xcb, 0xc9, 0xc9, + 0xc3, 0xef, 0xce, 0xea, 0xbe, 0x6c, 0xdb, 0xea, 0xdb, 0xfa, 0x2e, 0xc7, + 0xcf, 0xb9, 0x70, 0x0e, 0xf0, 0x6d, 0x4c, 0x53, 0xcb, 0xe8, 0x4e, 0xc3, + 0x18, 0xf0, 0x65, 0xb4, 0x35, 0x8f, 0xe8, 0xff, 0x99, 0x07, 0xe5, 0x64, + 0xc4, 0xf0, 0xcf, 0xdb, 0x71, 0x6d, 0x70, 0x3d, 0x3f, 0x06, 0xbf, 0xdf, + 0x2b, 0x3f, 0xad, 0x38, 0xa3, 0x2f, 0x3f, 0x4f, 0xec, 0xca, 0x0f, 0x7d, + 0xd4, 0x2e, 0xc9, 0xad, 0xd8, 0x32, 0x59, 0xd6, 0xfb, 0x0d, 0xae, 0xc9, + 0xf8, 0xd1, 0x09, 0xc8, 0x0d, 0x65, 0x9d, 0xba, 0x65, 0x4a, 0x15, 0x72, + 0x54, 0x05, 0x3e, 0x55, 0x21, 0x53, 0xe4, 0x40, 0x55, 0xe0, 0x5b, 0xb5, + 0x69, 0x39, 0x75, 0xcc, 0x99, 0x36, 0x7b, 0x1d, 0x72, 0x74, 0xb5, 0xc9, + 0xfd, 0xd7, 0x63, 0x36, 0x69, 0x07, 0x6f, 0xee, 0xee, 0xfd, 0xa7, 0xd8, + 0xfb, 0x23, 0x72, 0x0d, 0x7e, 0xcb, 0xf5, 0xca, 0x08, 0x30, 0x49, 0x80, + 0x51, 0x2e, 0x64, 0x23, 0x25, 0x1b, 0x95, 0x71, 0xd9, 0x84, 0x7d, 0xda, + 0x5a, 0x4d, 0x80, 0x4f, 0x03, 0x47, 0xaf, 0x1c, 0x93, 0x37, 0x56, 0x95, + 0xcc, 0xd8, 0xb0, 0x33, 0x6b, 0x8c, 0xc1, 0x43, 0x9e, 0xab, 0x5d, 0xfa, + 0xbc, 0x7d, 0xa2, 0xee, 0xc7, 0xe2, 0x73, 0xf5, 0x1e, 0x99, 0xac, 0x9b, + 0xf2, 0x54, 0xbd, 0x57, 0xbe, 0x5a, 0x8f, 0xca, 0xe9, 0x46, 0x4c, 0xbe, + 0x56, 0x1f, 0x94, 0xa7, 0xeb, 0x47, 0xe4, 0x99, 0x46, 0x5c, 0xbe, 0x0e, + 0xbf, 0x30, 0xdf, 0x70, 0x64, 0xaa, 0x31, 0x22, 0xa7, 0x1a, 0x8c, 0xb1, + 0xe3, 0x7b, 0xf8, 0x65, 0x77, 0x63, 0x17, 0x1c, 0x57, 0x27, 0xc6, 0xe5, + 0xa8, 0x9c, 0x3e, 0x6f, 0x94, 0xbc, 0x1f, 0xff, 0x10, 0x79, 0x01, 0x7d, + 0x17, 0xae, 0x28, 0xa9, 0xe9, 0xef, 0xb7, 0xfe, 0x47, 0x24, 0xa2, 0x7d, + 0xa3, 0x17, 0xaa, 0x83, 0x68, 0x63, 0xd3, 0x27, 0x09, 0xe2, 0x20, 0xad, + 0xf8, 0x7f, 0xcb, 0xf7, 0x32, 0x74, 0x0c, 0xfb, 0x26, 0x7d, 0x2f, 0xbd, + 0xf6, 0xc4, 0x0f, 0xfa, 0x39, 0xf4, 0xb5, 0xf6, 0x9e, 0x51, 0xb4, 0xbe, + 0xbb, 0x90, 0x7f, 0xf4, 0x7f, 0x51, 0xfc, 0xb3, 0xa6, 0x73, 0x8d, 0x41, + 0xfe, 0x4f, 0x0a, 0xc6, 0xf2, 0xf9, 0xf9, 0xdd, 0x93, 0x95, 0x09, 0xf5, + 0x54, 0x85, 0x8c, 0xc6, 0x93, 0x85, 0xdd, 0x3c, 0xba, 0xaf, 0xc8, 0x9a, + 0x1b, 0xd1, 0x63, 0xf0, 0xe3, 0xf6, 0x69, 0x9d, 0x53, 0x37, 0x31, 0x4c, + 0xf9, 0xe3, 0x19, 0x5a, 0x4f, 0x70, 0xb6, 0x00, 0x6e, 0xeb, 0x9a, 0x72, + 0xb1, 0xee, 0xc7, 0xaf, 0xe6, 0xb4, 0xbc, 0x5c, 0x87, 0xcc, 0xf1, 0xfc, + 0xc1, 0xbf, 0x16, 0xaa, 0x7e, 0xdf, 0xec, 0xb0, 0x43, 0x7f, 0x1c, 0xf3, + 0x35, 0x7a, 0xf9, 0x2d, 0xfe, 0x4f, 0x0e, 0xca, 0xc1, 0x78, 0x99, 0x0f, + 0x6c, 0x6b, 0x59, 0xf4, 0xcf, 0x67, 0x1d, 0x79, 0x11, 0x7b, 0x51, 0x33, + 0x39, 0xfe, 0x4e, 0xa9, 0x39, 0xf4, 0x6d, 0x89, 0xdf, 0xc3, 0x52, 0xc5, + 0x77, 0x6a, 0x4e, 0x2b, 0x36, 0xe6, 0xe3, 0x6c, 0xcd, 0x7c, 0xf8, 0xdd, + 0xe9, 0xea, 0x41, 0xdc, 0xa3, 0xce, 0x01, 0x67, 0x3a, 0xc3, 0xfb, 0x05, + 0x94, 0x19, 0x1b, 0x99, 0xc3, 0x35, 0x16, 0xd4, 0xfd, 0x7c, 0x40, 0x73, + 0xf5, 0xf1, 0x87, 0xfd, 0x66, 0xaa, 0x56, 0x21, 0x13, 0xba, 0xab, 0x8c, + 0x9f, 0xad, 0x0f, 0x10, 0x73, 0x0f, 0xda, 0xfc, 0x45, 0xe4, 0x6f, 0xa6, + 0x8e, 0x29, 0x04, 0xcf, 0xf6, 0xc9, 0xb3, 0x26, 0x73, 0xcd, 0xd3, 0x6a, + 0xa2, 0xf2, 0x72, 0x90, 0x57, 0x7b, 0x57, 0x1d, 0xac, 0x35, 0x07, 0xfc, + 0xbc, 0x74, 0xbe, 0x7b, 0x6f, 0x2e, 0xfa, 0x5e, 0x39, 0x61, 0x4e, 0x7a, + 0x07, 0x78, 0xab, 0x36, 0x62, 0xd0, 0x41, 0xe0, 0x9d, 0xdd, 0xa6, 0xf5, + 0xb1, 0xd8, 0xf8, 0x97, 0xb7, 0xad, 0xf5, 0xb9, 0x15, 0x63, 0xb8, 0x35, + 0x40, 0xdf, 0x96, 0xb8, 0x71, 0xd1, 0x8f, 0x1b, 0x69, 0x1f, 0x1a, 0x58, + 0x81, 0x3a, 0xea, 0x2a, 0xf4, 0x64, 0xb7, 0x2d, 0xff, 0xfe, 0x03, 0x7d, + 0xe7, 0x95, 0xf0, 0x2c, 0x67, 0x00, 0x00, 0x00 }; static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x0 }; -static u32 bnx2_RXP_b06FwRodata[(0x28/4) + 1] = { - 0x0800468c, 0x0800458c, 0x08004630, 0x08004648, 0x08004660, 0x08004680, - 0x0800468c, 0x0800468c, 0x08004594, 0x00000000, 0x00000000 }; -static u32 bnx2_RXP_b06FwBss[(0x13a4/4) + 1] = { 0x0 }; -static u32 bnx2_RXP_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwRodata[(0x278/4) + 1] = { + 0x08003fdc, 0x08003edc, 0x08003f80, 0x08003f98, 0x08003fb0, 0x08003fd0, + 0x08003fdc, 0x08003fdc, 0x08003ee4, 0x00000000, 0x08004a04, 0x08004a3c, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004a74, 0x08004c38, + 0x08004b80, 0x08004bb8, 0x08004c38, 0x08004b08, 0x08004c38, 0x08004c38, + 0x08004bb8, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004bf8, + 0x08004c38, 0x08004bf8, 0x08004b80, 0x08004c38, 0x08004c38, 0x08004bf8, + 0x08004bf8, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, 0x08004c38, + 0x08004ae4, 0x00000000, 0x08006018, 0x08006030, 0x08006030, 0x08006030, + 0x08006018, 0x08006030, 0x08006030, 0x08006030, 0x08006018, 0x08006030, + 0x08006030, 0x08006030, 0x08006018, 0x08006030, 0x08006030, 0x08006030, + 0x08006024, 0x00000000, 0x00000000 }; + +static u32 bnx2_RXP_b06FwBss[(0x13dc/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b06FwSbss[(0x2c/4) + 1] = { 0x0 }; static u8 bnx2_rv2p_proc1[] = { 0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, -- cgit v1.2.3 From 80be44348e30b68d2d8c5b6d1b7e53f2c5659134 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:07:28 -0800 Subject: [BNX2]: Improve SerDes handling. 1. Add support for 2.5Gbps forced speed setting. 2. Remove a long udelay() loop and change to msleep(). 3. Other misc. SerDes fixes. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 60 +++++++++++++++++++++++++++++++++++------------------- drivers/net/bnx2.h | 2 ++ 2 files changed, 41 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b60e45d1ce3d..9b391cf80a32 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -860,7 +860,7 @@ bnx2_set_link(struct bnx2 *bp) u32 bmsr; u8 link_up; - if (bp->loopback == MAC_LOOPBACK) { + if (bp->loopback == MAC_LOOPBACK || bp->loopback == PHY_LOOPBACK) { bp->link_up = 1; return 0; } @@ -902,6 +902,7 @@ bnx2_set_link(struct bnx2 *bp) u32 bmcr; bnx2_read_phy(bp, MII_BMCR, &bmcr); + bmcr &= ~BCM5708S_BMCR_FORCE_2500; if (!(bmcr & BMCR_ANENABLE)) { bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANENABLE); @@ -988,7 +989,21 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) u32 new_bmcr; int force_link_down = 0; - if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + new_bmcr = bmcr & ~(BMCR_ANENABLE | BCM5708S_BMCR_FORCE_2500); + new_bmcr |= BMCR_SPEED1000; + if (bp->req_line_speed == SPEED_2500) { + new_bmcr |= BCM5708S_BMCR_FORCE_2500; + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + if (!(up1 & BCM5708S_UP1_2G5)) { + up1 |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + force_link_down = 1; + } + } else if (CHIP_NUM(bp) == CHIP_NUM_5708) { bnx2_read_phy(bp, BCM5708S_UP1, &up1); if (up1 & BCM5708S_UP1_2G5) { up1 &= ~BCM5708S_UP1_2G5; @@ -997,12 +1012,6 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) } } - bnx2_read_phy(bp, MII_ADVERTISE, &adv); - adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); - - bnx2_read_phy(bp, MII_BMCR, &bmcr); - new_bmcr = bmcr & ~BMCR_ANENABLE; - new_bmcr |= BMCR_SPEED1000; if (bp->req_duplex == DUPLEX_FULL) { adv |= ADVERTISE_1000XFULL; new_bmcr |= BMCR_FULLDPLX; @@ -1023,6 +1032,7 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) bp->link_up = 0; netif_carrier_off(bp->dev); bnx2_write_phy(bp, MII_BMCR, new_bmcr); + bnx2_report_link(bp); } bnx2_write_phy(bp, MII_ADVERTISE, adv); bnx2_write_phy(bp, MII_BMCR, new_bmcr); @@ -1048,12 +1058,10 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) { /* Force a link down visible on the other side */ if (bp->link_up) { - int i; - bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); - for (i = 0; i < 110; i++) { - udelay(100); - } + spin_unlock_bh(&bp->phy_lock); + msleep(20); + spin_lock_bh(&bp->phy_lock); } bnx2_write_phy(bp, MII_ADVERTISE, new_adv); @@ -1397,7 +1405,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp) for (i = 0; i < 10; i++) { if (bnx2_test_link(bp) == 0) break; - udelay(10); + msleep(100); } mac_mode = REG_RD(bp, BNX2_EMAC_MODE); @@ -3713,7 +3721,9 @@ bnx2_init_nic(struct bnx2 *bp) if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0) return rc; + spin_lock_bh(&bp->phy_lock); bnx2_init_phy(bp); + spin_unlock_bh(&bp->phy_lock); bnx2_set_link(bp); return 0; } @@ -3953,7 +3963,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) bnx2_set_mac_loopback(bp); } else if (loopback_mode == BNX2_PHY_LOOPBACK) { - bp->loopback = 0; + bp->loopback = PHY_LOOPBACK; bnx2_set_phy_loopback(bp); } else @@ -4744,10 +4754,14 @@ bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) } else { if (bp->phy_flags & PHY_SERDES_FLAG) { - if ((cmd->speed != SPEED_1000) || - (cmd->duplex != DUPLEX_FULL)) { + if ((cmd->speed != SPEED_1000 && + cmd->speed != SPEED_2500) || + (cmd->duplex != DUPLEX_FULL)) + return -EINVAL; + + if (cmd->speed == SPEED_2500 && + !(bp->phy_flags & PHY_2_5G_CAPABLE_FLAG)) return -EINVAL; - } } else if (cmd->speed == SPEED_1000) { return -EINVAL; @@ -5289,6 +5303,8 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS); if (etest->flags & ETH_TEST_FL_OFFLINE) { + int i; + bnx2_netif_stop(bp); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); bnx2_free_skbs(bp); @@ -5313,9 +5329,11 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) } /* wait for link up */ - msleep_interruptible(3000); - if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG)) - msleep_interruptible(4000); + for (i = 0; i < 7; i++) { + if (bp->link_up) + break; + msleep_interruptible(1000); + } } if (bnx2_test_nvram(bp) != 0) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index ca31904893ea..78ff09d70de4 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3696,6 +3696,8 @@ struct l2_fhdr { /* 5708 Serdes PHY registers */ +#define BCM5708S_BMCR_FORCE_2500 0x20 + #define BCM5708S_UP1 0xb #define BCM5708S_UP1_2G5 0x1 -- cgit v1.2.3 From 48b01e2d7c83d37321722f1cdd46193d4ca73b41 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:08:00 -0800 Subject: [BNX2]: Add bnx2_5706_serdes_timer(). Separate the 5706S SerDes handling code in bnx2_timer() and put it in a new function. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 111 ++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 9b391cf80a32..78974810e307 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -4173,81 +4173,80 @@ bnx2_test_intr(struct bnx2 *bp) } static void -bnx2_timer(unsigned long data) +bnx2_5706_serdes_timer(struct bnx2 *bp) { - struct bnx2 *bp = (struct bnx2 *) data; - u32 msg; + spin_lock(&bp->phy_lock); + if (bp->serdes_an_pending) + bp->serdes_an_pending--; + else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { + u32 bmcr; - if (!netif_running(bp->dev)) - return; + bp->current_interval = bp->timer_interval; - if (atomic_read(&bp->intr_sem) != 0) - goto bnx2_restart_timer; + bnx2_read_phy(bp, MII_BMCR, &bmcr); - msg = (u32) ++bp->fw_drv_pulse_wr_seq; - REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); + if (bmcr & BMCR_ANENABLE) { + u32 phy1, phy2; - bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); + bnx2_write_phy(bp, 0x1c, 0x7c00); + bnx2_read_phy(bp, 0x1c, &phy1); - if ((bp->phy_flags & PHY_SERDES_FLAG) && - (CHIP_NUM(bp) == CHIP_NUM_5706)) { + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); - spin_lock(&bp->phy_lock); - if (bp->serdes_an_pending) { - bp->serdes_an_pending--; + if ((phy1 & 0x10) && /* SIGNAL DETECT */ + !(phy2 & 0x20)) { /* no CONFIG */ + + bmcr &= ~BMCR_ANENABLE; + bmcr |= BMCR_SPEED1000 | BMCR_FULLDPLX; + bnx2_write_phy(bp, MII_BMCR, bmcr); + bp->phy_flags |= PHY_PARALLEL_DETECT_FLAG; + } } - else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { - u32 bmcr; + } + else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) && + (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) { + u32 phy2; - bp->current_interval = bp->timer_interval; + bnx2_write_phy(bp, 0x17, 0x0f01); + bnx2_read_phy(bp, 0x15, &phy2); + if (phy2 & 0x20) { + u32 bmcr; bnx2_read_phy(bp, MII_BMCR, &bmcr); + bmcr |= BMCR_ANENABLE; + bnx2_write_phy(bp, MII_BMCR, bmcr); - if (bmcr & BMCR_ANENABLE) { - u32 phy1, phy2; - - bnx2_write_phy(bp, 0x1c, 0x7c00); - bnx2_read_phy(bp, 0x1c, &phy1); - - bnx2_write_phy(bp, 0x17, 0x0f01); - bnx2_read_phy(bp, 0x15, &phy2); - bnx2_write_phy(bp, 0x17, 0x0f01); - bnx2_read_phy(bp, 0x15, &phy2); + bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; + } + } else + bp->current_interval = bp->timer_interval; - if ((phy1 & 0x10) && /* SIGNAL DETECT */ - !(phy2 & 0x20)) { /* no CONFIG */ + spin_unlock(&bp->phy_lock); +} - bmcr &= ~BMCR_ANENABLE; - bmcr |= BMCR_SPEED1000 | - BMCR_FULLDPLX; - bnx2_write_phy(bp, MII_BMCR, bmcr); - bp->phy_flags |= - PHY_PARALLEL_DETECT_FLAG; - } - } - } - else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) && - (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) { - u32 phy2; +static void +bnx2_timer(unsigned long data) +{ + struct bnx2 *bp = (struct bnx2 *) data; + u32 msg; - bnx2_write_phy(bp, 0x17, 0x0f01); - bnx2_read_phy(bp, 0x15, &phy2); - if (phy2 & 0x20) { - u32 bmcr; + if (!netif_running(bp->dev)) + return; - bnx2_read_phy(bp, MII_BMCR, &bmcr); - bmcr |= BMCR_ANENABLE; - bnx2_write_phy(bp, MII_BMCR, bmcr); + if (atomic_read(&bp->intr_sem) != 0) + goto bnx2_restart_timer; - bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; + msg = (u32) ++bp->fw_drv_pulse_wr_seq; + REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB, msg); - } - } - else - bp->current_interval = bp->timer_interval; + bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); - spin_unlock(&bp->phy_lock); - } + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5706)) + bnx2_5706_serdes_timer(bp); bnx2_restart_timer: mod_timer(&bp->timer, jiffies + bp->current_interval); -- cgit v1.2.3 From f8dd064ee1bd62ef2cdb398cb9cdc8a8f112cb28 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:08:29 -0800 Subject: [BNX2]: Add 5708S parallel detection. Add code to parallel detect 1Gbps and 2.5Gbps link speeds. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 77 +++++++++++++++++++++++++++++++++++++++--------------- drivers/net/bnx2.h | 1 + 2 files changed, 57 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 78974810e307..ea5daf6efa09 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1067,19 +1067,17 @@ bnx2_setup_serdes_phy(struct bnx2 *bp) bnx2_write_phy(bp, MII_ADVERTISE, new_adv); bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); - if (CHIP_NUM(bp) == CHIP_NUM_5706) { - /* Speed up link-up time when the link partner - * does not autonegotiate which is very common - * in blade servers. Some blade servers use - * IPMI for kerboard input and it's important - * to minimize link disruptions. Autoneg. involves - * exchanging base pages plus 3 next pages and - * normally completes in about 120 msec. - */ - bp->current_interval = SERDES_AN_TIMEOUT; - bp->serdes_an_pending = 1; - mod_timer(&bp->timer, jiffies + bp->current_interval); - } + /* Speed up link-up time when the link partner + * does not autonegotiate which is very common + * in blade servers. Some blade servers use + * IPMI for kerboard input and it's important + * to minimize link disruptions. Autoneg. involves + * exchanging base pages plus 3 next pages and + * normally completes in about 120 msec. + */ + bp->current_interval = SERDES_AN_TIMEOUT; + bp->serdes_an_pending = 1; + mod_timer(&bp->timer, jiffies + bp->current_interval); } return 0; @@ -4227,6 +4225,41 @@ bnx2_5706_serdes_timer(struct bnx2 *bp) spin_unlock(&bp->phy_lock); } +static void +bnx2_5708_serdes_timer(struct bnx2 *bp) +{ + if ((bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) == 0) { + bp->serdes_an_pending = 0; + return; + } + + spin_lock(&bp->phy_lock); + if (bp->serdes_an_pending) + bp->serdes_an_pending--; + else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) { + u32 bmcr; + + bnx2_read_phy(bp, MII_BMCR, &bmcr); + + if (bmcr & BMCR_ANENABLE) { + bmcr &= ~BMCR_ANENABLE; + bmcr |= BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500; + bnx2_write_phy(bp, MII_BMCR, bmcr); + bp->current_interval = SERDES_FORCED_TIMEOUT; + } else { + bmcr &= ~(BMCR_FULLDPLX | BCM5708S_BMCR_FORCE_2500); + bmcr |= BMCR_ANENABLE; + bnx2_write_phy(bp, MII_BMCR, bmcr); + bp->serdes_an_pending = 2; + bp->current_interval = bp->timer_interval; + } + + } else + bp->current_interval = bp->timer_interval; + + spin_unlock(&bp->phy_lock); +} + static void bnx2_timer(unsigned long data) { @@ -4244,9 +4277,12 @@ bnx2_timer(unsigned long data) bp->stats_blk->stat_FwRxDrop = REG_RD_IND(bp, BNX2_FW_RX_DROP_COUNT); - if ((bp->phy_flags & PHY_SERDES_FLAG) && - (CHIP_NUM(bp) == CHIP_NUM_5706)) - bnx2_5706_serdes_timer(bp); + if (bp->phy_flags & PHY_SERDES_FLAG) { + if (CHIP_NUM(bp) == CHIP_NUM_5706) + bnx2_5706_serdes_timer(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + bnx2_5708_serdes_timer(bp); + } bnx2_restart_timer: mod_timer(&bp->timer, jiffies + bp->current_interval); @@ -4917,11 +4953,10 @@ bnx2_nway_reset(struct net_device *dev) msleep(20); spin_lock_bh(&bp->phy_lock); - if (CHIP_NUM(bp) == CHIP_NUM_5706) { - bp->current_interval = SERDES_AN_TIMEOUT; - bp->serdes_an_pending = 1; - mod_timer(&bp->timer, jiffies + bp->current_interval); - } + + bp->current_interval = SERDES_AN_TIMEOUT; + bp->serdes_an_pending = 1; + mod_timer(&bp->timer, jiffies + bp->current_interval); } bnx2_read_phy(bp, MII_BMCR, &bmcr); diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 78ff09d70de4..7fa7008f402a 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -4040,6 +4040,7 @@ struct bnx2 { u8 serdes_an_pending; #define SERDES_AN_TIMEOUT (HZ / 3) +#define SERDES_FORCED_TIMEOUT (HZ / 10) u8 mac_addr[8]; -- cgit v1.2.3 From a16dda0e67cea666fb7eb708ab1199892c4a1a13 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:08:56 -0800 Subject: [BNX2]: Remove udelay() in copper PHY code. Change a long udelay() in bnx2_setup_copper_phy() to msleep(). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index ea5daf6efa09..0a46b45f21dd 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -1159,7 +1159,6 @@ bnx2_setup_copper_phy(struct bnx2 *bp) } if (new_bmcr != bmcr) { u32 bmsr; - int i = 0; bnx2_read_phy(bp, MII_BMSR, &bmsr); bnx2_read_phy(bp, MII_BMSR, &bmsr); @@ -1167,12 +1166,12 @@ bnx2_setup_copper_phy(struct bnx2 *bp) if (bmsr & BMSR_LSTATUS) { /* Force link down */ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK); - do { - udelay(100); - bnx2_read_phy(bp, MII_BMSR, &bmsr); - bnx2_read_phy(bp, MII_BMSR, &bmsr); - i++; - } while ((bmsr & BMSR_LSTATUS) && (i < 620)); + spin_unlock_bh(&bp->phy_lock); + msleep(50); + spin_lock_bh(&bp->phy_lock); + + bnx2_read_phy(bp, MII_BMSR, &bmsr); + bnx2_read_phy(bp, MII_BMSR, &bmsr); } bnx2_write_phy(bp, MII_BMCR, new_bmcr); -- cgit v1.2.3 From af3ee519c5d6bebbda9bf0ca3b81bc50b4dd2163 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:09:25 -0800 Subject: [BNX2]: Re-organize firmware structures. Re-organize the firmware handling code and declarations a bit to make the code more compact. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 164 +++++++----------------------------------- drivers/net/bnx2.h | 48 +++++++------ drivers/net/bnx2_fw.h | 193 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 187 insertions(+), 218 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0a46b45f21dd..2633579b8c43 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -2214,11 +2214,12 @@ load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, } } -static void +static int load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) { u32 offset; u32 val; + int rc; /* Halt the CPU. */ val = REG_RD_IND(bp, cpu_reg->mode); @@ -2228,7 +2229,18 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) /* Load the Text area. */ offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base); - if (fw->text) { + if (fw->gz_text) { + u32 text_len; + void *text; + + rc = bnx2_gunzip(bp, fw->gz_text, fw->gz_text_len, &text, + &text_len); + if (rc) + return rc; + + fw->text = text; + } + if (fw->gz_text) { int j; for (j = 0; j < (fw->text_len / 4); j++, offset += 4) { @@ -2286,13 +2298,15 @@ load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw) val &= ~cpu_reg->mode_value_halt; REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear); REG_WR_IND(bp, cpu_reg->mode, val); + + return 0; } static int bnx2_init_cpus(struct bnx2 *bp) { struct cpu_reg cpu_reg; - struct fw_info fw; + struct fw_info *fw; int rc = 0; void *text; u32 text_len; @@ -2329,44 +2343,12 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_RXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw.ver_major = bnx2_RXP_b06FwReleaseMajor; - fw.ver_minor = bnx2_RXP_b06FwReleaseMinor; - fw.ver_fix = bnx2_RXP_b06FwReleaseFix; - fw.start_addr = bnx2_RXP_b06FwStartAddr; + fw = &bnx2_rxp_fw_06; - fw.text_addr = bnx2_RXP_b06FwTextAddr; - fw.text_len = bnx2_RXP_b06FwTextLen; - fw.text_index = 0; - - rc = bnx2_gunzip(bp, bnx2_RXP_b06FwText, sizeof(bnx2_RXP_b06FwText), - &text, &text_len); + rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) goto init_cpu_err; - fw.text = text; - - fw.data_addr = bnx2_RXP_b06FwDataAddr; - fw.data_len = bnx2_RXP_b06FwDataLen; - fw.data_index = 0; - fw.data = bnx2_RXP_b06FwData; - - fw.sbss_addr = bnx2_RXP_b06FwSbssAddr; - fw.sbss_len = bnx2_RXP_b06FwSbssLen; - fw.sbss_index = 0; - fw.sbss = bnx2_RXP_b06FwSbss; - - fw.bss_addr = bnx2_RXP_b06FwBssAddr; - fw.bss_len = bnx2_RXP_b06FwBssLen; - fw.bss_index = 0; - fw.bss = bnx2_RXP_b06FwBss; - - fw.rodata_addr = bnx2_RXP_b06FwRodataAddr; - fw.rodata_len = bnx2_RXP_b06FwRodataLen; - fw.rodata_index = 0; - fw.rodata = bnx2_RXP_b06FwRodata; - - load_cpu_fw(bp, &cpu_reg, &fw); - /* Initialize the TX Processor. */ cpu_reg.mode = BNX2_TXP_CPU_MODE; cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT; @@ -2381,44 +2363,12 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_TXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw.ver_major = bnx2_TXP_b06FwReleaseMajor; - fw.ver_minor = bnx2_TXP_b06FwReleaseMinor; - fw.ver_fix = bnx2_TXP_b06FwReleaseFix; - fw.start_addr = bnx2_TXP_b06FwStartAddr; + fw = &bnx2_txp_fw_06; - fw.text_addr = bnx2_TXP_b06FwTextAddr; - fw.text_len = bnx2_TXP_b06FwTextLen; - fw.text_index = 0; - - rc = bnx2_gunzip(bp, bnx2_TXP_b06FwText, sizeof(bnx2_TXP_b06FwText), - &text, &text_len); + rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) goto init_cpu_err; - fw.text = text; - - fw.data_addr = bnx2_TXP_b06FwDataAddr; - fw.data_len = bnx2_TXP_b06FwDataLen; - fw.data_index = 0; - fw.data = bnx2_TXP_b06FwData; - - fw.sbss_addr = bnx2_TXP_b06FwSbssAddr; - fw.sbss_len = bnx2_TXP_b06FwSbssLen; - fw.sbss_index = 0; - fw.sbss = bnx2_TXP_b06FwSbss; - - fw.bss_addr = bnx2_TXP_b06FwBssAddr; - fw.bss_len = bnx2_TXP_b06FwBssLen; - fw.bss_index = 0; - fw.bss = bnx2_TXP_b06FwBss; - - fw.rodata_addr = bnx2_TXP_b06FwRodataAddr; - fw.rodata_len = bnx2_TXP_b06FwRodataLen; - fw.rodata_index = 0; - fw.rodata = bnx2_TXP_b06FwRodata; - - load_cpu_fw(bp, &cpu_reg, &fw); - /* Initialize the TX Patch-up Processor. */ cpu_reg.mode = BNX2_TPAT_CPU_MODE; cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT; @@ -2433,44 +2383,12 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_TPAT_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw.ver_major = bnx2_TPAT_b06FwReleaseMajor; - fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor; - fw.ver_fix = bnx2_TPAT_b06FwReleaseFix; - fw.start_addr = bnx2_TPAT_b06FwStartAddr; + fw = &bnx2_tpat_fw_06; - fw.text_addr = bnx2_TPAT_b06FwTextAddr; - fw.text_len = bnx2_TPAT_b06FwTextLen; - fw.text_index = 0; - - rc = bnx2_gunzip(bp, bnx2_TPAT_b06FwText, sizeof(bnx2_TPAT_b06FwText), - &text, &text_len); + rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) goto init_cpu_err; - fw.text = text; - - fw.data_addr = bnx2_TPAT_b06FwDataAddr; - fw.data_len = bnx2_TPAT_b06FwDataLen; - fw.data_index = 0; - fw.data = bnx2_TPAT_b06FwData; - - fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr; - fw.sbss_len = bnx2_TPAT_b06FwSbssLen; - fw.sbss_index = 0; - fw.sbss = bnx2_TPAT_b06FwSbss; - - fw.bss_addr = bnx2_TPAT_b06FwBssAddr; - fw.bss_len = bnx2_TPAT_b06FwBssLen; - fw.bss_index = 0; - fw.bss = bnx2_TPAT_b06FwBss; - - fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr; - fw.rodata_len = bnx2_TPAT_b06FwRodataLen; - fw.rodata_index = 0; - fw.rodata = bnx2_TPAT_b06FwRodata; - - load_cpu_fw(bp, &cpu_reg, &fw); - /* Initialize the Completion Processor. */ cpu_reg.mode = BNX2_COM_CPU_MODE; cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT; @@ -2485,44 +2403,12 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_COM_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw.ver_major = bnx2_COM_b06FwReleaseMajor; - fw.ver_minor = bnx2_COM_b06FwReleaseMinor; - fw.ver_fix = bnx2_COM_b06FwReleaseFix; - fw.start_addr = bnx2_COM_b06FwStartAddr; - - fw.text_addr = bnx2_COM_b06FwTextAddr; - fw.text_len = bnx2_COM_b06FwTextLen; - fw.text_index = 0; + fw = &bnx2_com_fw_06; - rc = bnx2_gunzip(bp, bnx2_COM_b06FwText, sizeof(bnx2_COM_b06FwText), - &text, &text_len); + rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) goto init_cpu_err; - fw.text = text; - - fw.data_addr = bnx2_COM_b06FwDataAddr; - fw.data_len = bnx2_COM_b06FwDataLen; - fw.data_index = 0; - fw.data = bnx2_COM_b06FwData; - - fw.sbss_addr = bnx2_COM_b06FwSbssAddr; - fw.sbss_len = bnx2_COM_b06FwSbssLen; - fw.sbss_index = 0; - fw.sbss = bnx2_COM_b06FwSbss; - - fw.bss_addr = bnx2_COM_b06FwBssAddr; - fw.bss_len = bnx2_COM_b06FwBssLen; - fw.bss_index = 0; - fw.bss = bnx2_COM_b06FwBss; - - fw.rodata_addr = bnx2_COM_b06FwRodataAddr; - fw.rodata_len = bnx2_COM_b06FwRodataLen; - fw.rodata_index = 0; - fw.rodata = bnx2_COM_b06FwRodata; - - load_cpu_fw(bp, &cpu_reg, &fw); - init_cpu_err: bnx2_gunzip_end(bp); return rc; diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 7fa7008f402a..11e9c55d1dd0 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -4107,41 +4107,43 @@ struct cpu_reg { }; struct fw_info { - u32 ver_major; - u32 ver_minor; - u32 ver_fix; + const u32 ver_major; + const u32 ver_minor; + const u32 ver_fix; - u32 start_addr; + const u32 start_addr; /* Text section. */ - u32 text_addr; - u32 text_len; - u32 text_index; + const u32 text_addr; + const u32 text_len; + const u32 text_index; u32 *text; + u8 *gz_text; + const u32 gz_text_len; /* Data section. */ - u32 data_addr; - u32 data_len; - u32 data_index; - u32 *data; + const u32 data_addr; + const u32 data_len; + const u32 data_index; + const u32 *data; /* SBSS section. */ - u32 sbss_addr; - u32 sbss_len; - u32 sbss_index; - u32 *sbss; + const u32 sbss_addr; + const u32 sbss_len; + const u32 sbss_index; + const u32 *sbss; /* BSS section. */ - u32 bss_addr; - u32 bss_len; - u32 bss_index; - u32 *bss; + const u32 bss_addr; + const u32 bss_len; + const u32 bss_index; + const u32 *bss; /* Read-only section. */ - u32 rodata_addr; - u32 rodata_len; - u32 rodata_index; - u32 *rodata; + const u32 rodata_addr; + const u32 rodata_len; + const u32 rodata_index; + const u32 *rodata; }; #define RV2P_PROC1 0 diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h index 4adc8de30631..21d368ff424d 100644 --- a/drivers/net/bnx2_fw.h +++ b/drivers/net/bnx2_fw.h @@ -14,20 +14,6 @@ * accompanying it. */ -static const int bnx2_COM_b06FwReleaseMajor = 0x1; -static const int bnx2_COM_b06FwReleaseMinor = 0x0; -static const int bnx2_COM_b06FwReleaseFix = 0x0; -static const u32 bnx2_COM_b06FwStartAddr = 0x080008b4; -static const u32 bnx2_COM_b06FwTextAddr = 0x08000000; -static const int bnx2_COM_b06FwTextLen = 0x57bc; -static const u32 bnx2_COM_b06FwDataAddr = 0x08005840; -static const int bnx2_COM_b06FwDataLen = 0x0; -static const u32 bnx2_COM_b06FwRodataAddr = 0x080057c0; -static const int bnx2_COM_b06FwRodataLen = 0x58; -static const u32 bnx2_COM_b06FwBssAddr = 0x08005860; -static const int bnx2_COM_b06FwBssLen = 0x88; -static const u32 bnx2_COM_b06FwSbssAddr = 0x08005840; -static const int bnx2_COM_b06FwSbssLen = 0x1c; static u8 bnx2_COM_b06FwText[] = { 0x1f, 0x8b, 0x08, 0x08, 0x09, 0x83, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5b, 0x7d, 0x6c, @@ -673,20 +659,40 @@ static u32 bnx2_COM_b06FwRodata[(0x58/4) + 1] = { static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x0 }; static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x0 }; -static const int bnx2_RXP_b06FwReleaseMajor = 0x2; -static const int bnx2_RXP_b06FwReleaseMinor = 0x8; -static const int bnx2_RXP_b06FwReleaseFix = 0x17; -static const u32 bnx2_RXP_b06FwStartAddr = 0x08003184; -static const u32 bnx2_RXP_b06FwTextAddr = 0x08000000; -static const int bnx2_RXP_b06FwTextLen = 0x6728; -static const u32 bnx2_RXP_b06FwDataAddr = 0x080069c0; -static const int bnx2_RXP_b06FwDataLen = 0x0; -static const u32 bnx2_RXP_b06FwRodataAddr = 0x08006728; -static const int bnx2_RXP_b06FwRodataLen = 0x278; -static const u32 bnx2_RXP_b06FwBssAddr = 0x080069f0; -static const int bnx2_RXP_b06FwBssLen = 0x13dc; -static const u32 bnx2_RXP_b06FwSbssAddr = 0x080069c0; -static const int bnx2_RXP_b06FwSbssLen = 0x2c; +static struct fw_info bnx2_com_fw_06 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x080008b4, + + .text_addr = 0x08000000, + .text_len = 0x57bc, + .text_index = 0x0, + .gz_text = bnx2_COM_b06FwText, + .gz_text_len = sizeof(bnx2_COM_b06FwText), + + .data_addr = 0x08005840, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_COM_b06FwData, + + .sbss_addr = 0x08005840, + .sbss_len = 0x1c, + .sbss_index = 0x0, + .sbss = bnx2_COM_b06FwSbss, + + .bss_addr = 0x08005860, + .bss_len = 0x88, + .bss_index = 0x0, + .bss = bnx2_COM_b06FwBss, + + .rodata_addr = 0x080057c0, + .rodata_len = 0x58, + .rodata_index = 0x0, + .rodata = bnx2_COM_b06FwRodata, +}; + static u8 bnx2_RXP_b06FwText[] = { 0x1f, 0x8b, 0x08, 0x08, 0xcb, 0xa3, 0x46, 0x45, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6f, 0x6c, @@ -1366,6 +1372,40 @@ static u32 bnx2_RXP_b06FwRodata[(0x278/4) + 1] = { static u32 bnx2_RXP_b06FwBss[(0x13dc/4) + 1] = { 0x0 }; static u32 bnx2_RXP_b06FwSbss[(0x2c/4) + 1] = { 0x0 }; +static struct fw_info bnx2_rxp_fw_06 = { + .ver_major = 0x2, + .ver_minor = 0x8, + .ver_fix = 0x17, + + .start_addr = 0x08003184, + + .text_addr = 0x08000000, + .text_len = 0x6728, + .text_index = 0x0, + .gz_text = bnx2_RXP_b06FwText, + .gz_text_len = sizeof(bnx2_RXP_b06FwText), + + .data_addr = 0x080069c0, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_RXP_b06FwData, + + .sbss_addr = 0x080069c0, + .sbss_len = 0x2c, + .sbss_index = 0x0, + .sbss = bnx2_RXP_b06FwSbss, + + .bss_addr = 0x080069f0, + .bss_len = 0x13dc, + .bss_index = 0x0, + .bss = bnx2_RXP_b06FwBss, + + .rodata_addr = 0x08006728, + .rodata_len = 0x278, + .rodata_index = 0x0, + .rodata = bnx2_RXP_b06FwRodata, +}; + static u8 bnx2_rv2p_proc1[] = { 0x1f, 0x8b, 0x08, 0x08, 0x5e, 0xd0, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x56, 0xcf, 0x6b, @@ -1625,20 +1665,6 @@ static u8 bnx2_rv2p_proc2[] = { 0x63, 0xd6, 0x11, 0x8f, 0x47, 0xd5, 0x5f, 0x3f, 0x97, 0x8f, 0x31, 0xd8, 0x17, 0x00, 0x00, 0x00 }; -static const int bnx2_TPAT_b06FwReleaseMajor = 0x1; -static const int bnx2_TPAT_b06FwReleaseMinor = 0x0; -static const int bnx2_TPAT_b06FwReleaseFix = 0x0; -static const u32 bnx2_TPAT_b06FwStartAddr = 0x08000860; -static const u32 bnx2_TPAT_b06FwTextAddr = 0x08000800; -static const int bnx2_TPAT_b06FwTextLen = 0x122c; -static const u32 bnx2_TPAT_b06FwDataAddr = 0x08001a60; -static const int bnx2_TPAT_b06FwDataLen = 0x0; -static const u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000; -static const int bnx2_TPAT_b06FwRodataLen = 0x0; -static const u32 bnx2_TPAT_b06FwBssAddr = 0x08001aa0; -static const int bnx2_TPAT_b06FwBssLen = 0x250; -static const u32 bnx2_TPAT_b06FwSbssAddr = 0x08001a60; -static const int bnx2_TPAT_b06FwSbssLen = 0x34; static u8 bnx2_TPAT_b06FwText[] = { 0x1f, 0x8b, 0x08, 0x08, 0x47, 0xd2, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x57, 0x4d, 0x68, @@ -1838,20 +1864,40 @@ static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TPAT_b06FwBss[(0x250/4) + 1] = { 0x0 }; static u32 bnx2_TPAT_b06FwSbss[(0x34/4) + 1] = { 0x0 }; -static const int bnx2_TXP_b06FwReleaseMajor = 0x1; -static const int bnx2_TXP_b06FwReleaseMinor = 0x0; -static const int bnx2_TXP_b06FwReleaseFix = 0x0; -static const u32 bnx2_TXP_b06FwStartAddr = 0x080034b0; -static const u32 bnx2_TXP_b06FwTextAddr = 0x08000000; -static const int bnx2_TXP_b06FwTextLen = 0x5748; -static const u32 bnx2_TXP_b06FwDataAddr = 0x08005760; -static const int bnx2_TXP_b06FwDataLen = 0x0; -static const u32 bnx2_TXP_b06FwRodataAddr = 0x00000000; -static const int bnx2_TXP_b06FwRodataLen = 0x0; -static const u32 bnx2_TXP_b06FwBssAddr = 0x080057a0; -static const int bnx2_TXP_b06FwBssLen = 0x1c4; -static const u32 bnx2_TXP_b06FwSbssAddr = 0x08005760; -static const int bnx2_TXP_b06FwSbssLen = 0x38; +static struct fw_info bnx2_tpat_fw_06 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x08000860, + + .text_addr = 0x08000800, + .text_len = 0x122c, + .text_index = 0x0, + .gz_text = bnx2_TPAT_b06FwText, + .gz_text_len = sizeof(bnx2_TPAT_b06FwText), + + .data_addr = 0x08001a60, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_TPAT_b06FwData, + + .sbss_addr = 0x08001a60, + .sbss_len = 0x34, + .sbss_index = 0x0, + .sbss = bnx2_TPAT_b06FwSbss, + + .bss_addr = 0x08001aa0, + .bss_len = 0x250, + .bss_index = 0x0, + .bss = bnx2_TPAT_b06FwBss, + + .rodata_addr = 0x00000000, + .rodata_len = 0x0, + .rodata_index = 0x0, + .rodata = bnx2_TPAT_b06FwRodata, +}; + static u8 bnx2_TXP_b06FwText[] = { 0x1f, 0x8b, 0x08, 0x08, 0x21, 0xd3, 0x41, 0x44, 0x00, 0x03, 0x74, 0x65, 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xed, 0x5c, 0x6d, 0x6c, @@ -2273,3 +2319,38 @@ static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x0 }; static u32 bnx2_TXP_b06FwBss[(0x1c4/4) + 1] = { 0x0 }; static u32 bnx2_TXP_b06FwSbss[(0x38/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_txp_fw_06 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x080034b0, + + .text_addr = 0x08000000, + .text_len = 0x5748, + .text_index = 0x0, + .gz_text = bnx2_TXP_b06FwText, + .gz_text_len = sizeof(bnx2_TXP_b06FwText), + + .data_addr = 0x08005760, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_TXP_b06FwData, + + .sbss_addr = 0x08005760, + .sbss_len = 0x38, + .sbss_index = 0x0, + .sbss = bnx2_TXP_b06FwSbss, + + .bss_addr = 0x080057a0, + .bss_len = 0x1c4, + .bss_index = 0x0, + .bss = bnx2_TXP_b06FwBss, + + .rodata_addr = 0x00000000, + .rodata_len = 0x0, + .rodata_index = 0x0, + .rodata = bnx2_TXP_b06FwRodata, +}; + -- cgit v1.2.3 From 19cdeb794b7ef9e1f0e408777445bd76fe90e694 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:09:48 -0800 Subject: [BNX2]: Add new 5709 registers (part 1). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.h | 1457 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 1311 insertions(+), 146 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 11e9c55d1dd0..73c785585fc3 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -56,6 +56,7 @@ struct rx_bd { }; +#define BNX2_RX_ALIGN 16 /* * status_block definition @@ -90,6 +91,7 @@ struct status_block { #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25) #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26) #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27) + #define STATUS_ATTN_BITS_EPB_ERROR (1L<<30) #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31) u32 status_attn_bits_ack; @@ -117,7 +119,8 @@ struct status_block { u16 status_completion_producer_index; u16 status_cmd_consumer_index; u16 status_idx; - u16 status_unused; + u8 status_unused; + u8 status_blk_num; #elif defined(__LITTLE_ENDIAN) u16 status_tx_quick_consumer_index1; u16 status_tx_quick_consumer_index0; @@ -141,7 +144,8 @@ struct status_block { u16 status_rx_quick_consumer_index14; u16 status_cmd_consumer_index; u16 status_completion_producer_index; - u16 status_unused; + u8 status_blk_num; + u8 status_unused; u16 status_idx; #endif }; @@ -301,6 +305,10 @@ struct l2_fhdr { #define BNX2_L2CTX_TXP_BIDX 0x000000a8 #define BNX2_L2CTX_TXP_BSEQ 0x000000ac +#define BNX2_L2CTX_TYPE_XI 0x00000080 +#define BNX2_L2CTX_CMD_TYPE_XI 0x00000240 +#define BNX2_L2CTX_TBDR_BHADDR_HI_XI 0x00000258 +#define BNX2_L2CTX_TBDR_BHADDR_LO_XI 0x0000025c /* * l2_bd_chain_context definition @@ -328,11 +336,15 @@ struct l2_fhdr { #define BNX2_PCICFG_MISC_CONFIG 0x00000068 #define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2) #define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3) +#define BNX2_PCICFG_MISC_CONFIG_RESERVED1 (1L<<4) #define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5) #define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6) #define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7) #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8) #define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9) +#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN1_SWAP_EN (1L<<10) +#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN2_SWAP_EN (1L<<11) +#define BNX2_PCICFG_MISC_CONFIG_GRC_WIN3_SWAP_EN (1L<<12) #define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16) #define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24) #define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28) @@ -347,6 +359,7 @@ struct l2_fhdr { #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4) #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4) #define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4) +#define BNX2_PCICFG_MISC_STATUS_BAD_MEM_WRITE_BE (1L<<8) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070 #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) @@ -366,7 +379,7 @@ struct l2_fhdr { #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) -#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) @@ -374,18 +387,21 @@ struct l2_fhdr { #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) -#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_17 (1L<<17) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18) -#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19) +#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_19 (1L<<19) #define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20) #define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078 +#define BNX2_PCICFG_REG_WINDOW_ADDRESS_VAL (0xfffffL<<2) + #define BNX2_PCICFG_REG_WINDOW 0x00000080 #define BNX2_PCICFG_INT_ACK_CMD 0x00000084 #define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0) #define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16) #define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17) #define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18) +#define BNX2_PCICFG_INT_ACK_CMD_INTERRUPT_NUM (0xfL<<24) #define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088 #define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c @@ -398,9 +414,11 @@ struct l2_fhdr { * offset: 0x400 */ #define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400 -#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8) +#define BNX2_PCI_GRC_WINDOW_ADDR_VALUE (0x1ffL<<13) +#define BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN (1L<<31) #define BNX2_PCI_CONFIG_1 0x00000404 +#define BNX2_PCI_CONFIG_1_RESERVED0 (0xffL<<0) #define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8) #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8) #define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8) @@ -419,6 +437,7 @@ struct l2_fhdr { #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11) #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11) #define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11) +#define BNX2_PCI_CONFIG_1_RESERVED1 (0x3ffffL<<14) #define BNX2_PCI_CONFIG_2 0x00000408 #define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0) @@ -468,9 +487,13 @@ struct l2_fhdr { #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23) #define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24) #define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25) +#define BNX2_PCI_CONFIG_2_RESERVED0 (0x3fL<<26) +#define BNX2_PCI_CONFIG_2_BAR_PREFETCH_XI (1L<<16) +#define BNX2_PCI_CONFIG_2_RESERVED0_XI (0x7fffL<<17) #define BNX2_PCI_CONFIG_3 0x0000040c #define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0) +#define BNX2_PCI_CONFIG_3_REG_STICKY_BYTE (0xffL<<8) #define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24) #define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25) #define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26) @@ -501,8 +524,10 @@ struct l2_fhdr { #define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0) #define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c -#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2) -#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15) +#define BNX2_PCI_VPD_ADDR_FLAG_MSK 0x0000ffff +#define BNX2_PCI_VPD_ADDR_FLAG_SL 0L +#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fffL<<2) +#define BNX2_PCI_VPD_ADDR_FLAG_WR (1L<<15) #define BNX2_PCI_VPD_DATA 0x00000430 #define BNX2_PCI_ID_VAL1 0x00000434 @@ -535,19 +560,26 @@ struct l2_fhdr { #define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0) #define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0) #define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0) +#define BNX2_PCI_ID_VAL4_RESERVED0 (0x3L<<4) #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6) #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6) #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6) #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6) #define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6) +#define BNX2_PCI_ID_VAL4_MSI_PV_MASK_CAP (1L<<8) #define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9) -#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12) +#define BNX2_PCI_ID_VAL4_MULTI_MSG_CAP (0x7L<<12) #define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15) #define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16) #define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17) -#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21) -#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23) -#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26) +#define BNX2_PCI_ID_VAL4_RESERVED2 (0x7L<<18) +#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B21 (0x3L<<21) +#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B21 (0x3L<<23) +#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE_B0 (1L<<25) +#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE_B10 (0x3L<<26) +#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE_B0 (1L<<28) +#define BNX2_PCI_ID_VAL4_RESERVED3 (0x7L<<29) +#define BNX2_PCI_ID_VAL4_RESERVED3_XI (0xffffL<<16) #define BNX2_PCI_ID_VAL5 0x00000444 #define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0) @@ -556,6 +588,10 @@ struct l2_fhdr { #define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3) #define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4) #define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5) +#define BNX2_PCI_ID_VAL5_RESERVED0_TE (0x3ffffffL<<6) +#define BNX2_PCI_ID_VAL5_PM_VERSION_XI (0x7L<<6) +#define BNX2_PCI_ID_VAL5_NO_SOFT_RESET_XI (1L<<9) +#define BNX2_PCI_ID_VAL5_RESERVED0_XI (0x3fffffL<<10) #define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448 #define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8) @@ -567,12 +603,91 @@ struct l2_fhdr { #define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0) #define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8) #define BNX2_PCI_ID_VAL6_BIST (0xffL<<16) +#define BNX2_PCI_ID_VAL6_RESERVED0 (0xffL<<24) #define BNX2_PCI_MSI_DATA 0x00000450 -#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0) +#define BNX2_PCI_MSI_DATA_MSI_DATA (0xffffL<<0) #define BNX2_PCI_MSI_ADDR_H 0x00000454 #define BNX2_PCI_MSI_ADDR_L 0x00000458 +#define BNX2_PCI_MSI_ADDR_L_VAL (0x3fffffffL<<2) + +#define BNX2_PCI_CFG_ACCESS_CMD 0x0000045c +#define BNX2_PCI_CFG_ACCESS_CMD_ADR (0x3fL<<2) +#define BNX2_PCI_CFG_ACCESS_CMD_RD_REQ (1L<<27) +#define BNX2_PCI_CFG_ACCESS_CMD_WR_REQ (0xfL<<28) + +#define BNX2_PCI_CFG_ACCESS_DATA 0x00000460 +#define BNX2_PCI_MSI_MASK 0x00000464 +#define BNX2_PCI_MSI_MASK_MSI_MASK (0xffffffffL<<0) + +#define BNX2_PCI_MSI_PEND 0x00000468 +#define BNX2_PCI_MSI_PEND_MSI_PEND (0xffffffffL<<0) + +#define BNX2_PCI_PM_DATA_C 0x0000046c +#define BNX2_PCI_PM_DATA_C_PM_DATA_8_PRG (0xffL<<0) +#define BNX2_PCI_PM_DATA_C_RESERVED0 (0xffffffL<<8) + +#define BNX2_PCI_MSIX_CONTROL 0x000004c0 +#define BNX2_PCI_MSIX_CONTROL_MSIX_TBL_SIZ (0x7ffL<<0) +#define BNX2_PCI_MSIX_CONTROL_RESERVED0 (0x1fffffL<<11) + +#define BNX2_PCI_MSIX_TBL_OFF_BIR 0x000004c4 +#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_BIR (0x7L<<0) +#define BNX2_PCI_MSIX_TBL_OFF_BIR_MSIX_TBL_OFF (0x1fffffffL<<3) + +#define BNX2_PCI_MSIX_PBA_OFF_BIT 0x000004c8 +#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_BIR (0x7L<<0) +#define BNX2_PCI_MSIX_PBA_OFF_BIT_MSIX_PBA_OFF (0x1fffffffL<<3) + +#define BNX2_PCI_PCIE_CAPABILITY 0x000004d0 +#define BNX2_PCI_PCIE_CAPABILITY_INTERRUPT_MSG_NUM (0x1fL<<0) +#define BNX2_PCI_PCIE_CAPABILITY_COMPLY_PCIE_1_1 (1L<<5) + +#define BNX2_PCI_DEVICE_CAPABILITY 0x000004d4 +#define BNX2_PCI_DEVICE_CAPABILITY_MAX_PL_SIZ_SUPPORTED (0x7L<<0) +#define BNX2_PCI_DEVICE_CAPABILITY_EXTENDED_TAG_SUPPORT (1L<<5) +#define BNX2_PCI_DEVICE_CAPABILITY_L0S_ACCEPTABLE_LATENCY (0x7L<<6) +#define BNX2_PCI_DEVICE_CAPABILITY_L1_ACCEPTABLE_LATENCY (0x7L<<9) +#define BNX2_PCI_DEVICE_CAPABILITY_ROLE_BASED_ERR_RPT (1L<<15) + +#define BNX2_PCI_LINK_CAPABILITY 0x000004dc +#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED (0xfL<<0) +#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0001 (1L<<0) +#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_SPEED_0010 (1L<<0) +#define BNX2_PCI_LINK_CAPABILITY_MAX_LINK_WIDTH (0x1fL<<4) +#define BNX2_PCI_LINK_CAPABILITY_CLK_POWER_MGMT (1L<<9) +#define BNX2_PCI_LINK_CAPABILITY_ASPM_SUPPORT (0x3L<<10) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT (0x7L<<12) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_101 (5L<<12) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_LAT_110 (6L<<12) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT (0x7L<<15) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_001 (1L<<15) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_LAT_010 (2L<<15) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT (0x7L<<18) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_101 (5L<<18) +#define BNX2_PCI_LINK_CAPABILITY_L0S_EXIT_COMM_LAT_110 (6L<<18) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT (0x7L<<21) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_001 (1L<<21) +#define BNX2_PCI_LINK_CAPABILITY_L1_EXIT_COMM_LAT_010 (2L<<21) +#define BNX2_PCI_LINK_CAPABILITY_PORT_NUM (0xffL<<24) + +#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2 0x000004e4 +#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_RANGE_SUPP (0xfL<<0) +#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_CMPL_TO_DISABL_SUPP (1L<<4) +#define BNX2_PCI_PCIE_DEVICE_CAPABILITY_2_RESERVED (0x7ffffffL<<5) + +#define BNX2_PCI_PCIE_LINK_CAPABILITY_2 0x000004e8 +#define BNX2_PCI_PCIE_LINK_CAPABILITY_2_RESERVED (0xffffffffL<<0) + +#define BNX2_PCI_GRC_WINDOW1_ADDR 0x00000610 +#define BNX2_PCI_GRC_WINDOW1_ADDR_VALUE (0x1ffL<<13) + +#define BNX2_PCI_GRC_WINDOW2_ADDR 0x00000614 +#define BNX2_PCI_GRC_WINDOW2_ADDR_VALUE (0x1ffL<<13) + +#define BNX2_PCI_GRC_WINDOW3_ADDR 0x00000618 +#define BNX2_PCI_GRC_WINDOW3_ADDR_VALUE (0x1ffL<<13) /* @@ -582,13 +697,23 @@ struct l2_fhdr { #define BNX2_MISC_COMMAND 0x00000800 #define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0) #define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1) -#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4) -#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5) +#define BNX2_MISC_COMMAND_SW_RESET (1L<<4) +#define BNX2_MISC_COMMAND_POR_RESET (1L<<5) +#define BNX2_MISC_COMMAND_HD_RESET (1L<<6) +#define BNX2_MISC_COMMAND_CMN_SW_RESET (1L<<7) #define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8) +#define BNX2_MISC_COMMAND_CS16_ERR (1L<<9) +#define BNX2_MISC_COMMAND_CS16_ERR_LOC (0xfL<<12) #define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16) +#define BNX2_MISC_COMMAND_POWERDOWN_EVENT (1L<<23) +#define BNX2_MISC_COMMAND_SW_SHUTDOWN (1L<<24) +#define BNX2_MISC_COMMAND_SHUTDOWN_EN (1L<<25) +#define BNX2_MISC_COMMAND_DINTEG_ATTN_EN (1L<<26) +#define BNX2_MISC_COMMAND_PCIE_LINK_IN_L23 (1L<<27) +#define BNX2_MISC_COMMAND_PCIE_DIS (1L<<28) #define BNX2_MISC_CFG 0x00000804 -#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0) +#define BNX2_MISC_CFG_GRC_TMOUT (1L<<0) #define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1) #define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1) #define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1) @@ -596,16 +721,45 @@ struct l2_fhdr { #define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1) #define BNX2_MISC_CFG_BIST_EN (1L<<3) #define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4) -#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5) -#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6) +#define BNX2_MISC_CFG_RESERVED5_TE (1L<<5) +#define BNX2_MISC_CFG_RESERVED6_TE (1L<<6) #define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7) -#define BNX2_MISC_CFG_LEDMODE (0x3L<<8) +#define BNX2_MISC_CFG_LEDMODE (0x7L<<8) #define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8) -#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8) -#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY1_TE (1L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY2_TE (2L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY3_TE (3L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY4_TE (4L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY5_TE (5L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY6_TE (6L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY7_TE (7L<<8) +#define BNX2_MISC_CFG_MCP_GRC_TMOUT_TE (1L<<11) +#define BNX2_MISC_CFG_DBU_GRC_TMOUT_TE (1L<<12) +#define BNX2_MISC_CFG_LEDMODE_XI (0xfL<<8) +#define BNX2_MISC_CFG_LEDMODE_MAC_XI (0L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY1_XI (1L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY2_XI (2L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY3_XI (3L<<8) +#define BNX2_MISC_CFG_LEDMODE_MAC2_XI (4L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY4_XI (5L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY5_XI (6L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY6_XI (7L<<8) +#define BNX2_MISC_CFG_LEDMODE_MAC3_XI (8L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY7_XI (9L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY8_XI (10L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY9_XI (11L<<8) +#define BNX2_MISC_CFG_LEDMODE_MAC4_XI (12L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY10_XI (13L<<8) +#define BNX2_MISC_CFG_LEDMODE_PHY11_XI (14L<<8) +#define BNX2_MISC_CFG_LEDMODE_UNUSED_XI (15L<<8) +#define BNX2_MISC_CFG_PORT_SELECT_XI (1L<<13) +#define BNX2_MISC_CFG_PARITY_MODE_XI (1L<<14) #define BNX2_MISC_ID 0x00000808 #define BNX2_MISC_ID_BOND_ID (0xfL<<0) +#define BNX2_MISC_ID_BOND_ID_X (0L<<0) +#define BNX2_MISC_ID_BOND_ID_C (3L<<0) +#define BNX2_MISC_ID_BOND_ID_S (12L<<0) #define BNX2_MISC_ID_CHIP_METAL (0xffL<<4) #define BNX2_MISC_ID_CHIP_REV (0xfL<<12) #define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16) @@ -639,6 +793,8 @@ struct l2_fhdr { #define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25) #define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26) #define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27) +#define BNX2_MISC_ENABLE_STATUS_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) +#define BNX2_MISC_ENABLE_STATUS_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) #define BNX2_MISC_ENABLE_SET_BITS 0x00000810 #define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0) @@ -669,6 +825,8 @@ struct l2_fhdr { #define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25) #define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26) #define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27) +#define BNX2_MISC_ENABLE_SET_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) +#define BNX2_MISC_ENABLE_SET_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) #define BNX2_MISC_ENABLE_CLR_BITS 0x00000814 #define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0) @@ -699,6 +857,8 @@ struct l2_fhdr { #define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25) #define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26) #define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27) +#define BNX2_MISC_ENABLE_CLR_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) +#define BNX2_MISC_ENABLE_CLR_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) #define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818 #define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0) @@ -718,30 +878,41 @@ struct l2_fhdr { #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8) -#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED0_XI (0x7L<<8) +#define BNX2_MISC_CLOCK_CONTROL_BITS_MIN_POWER (1L<<11) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED1_XI (0xfL<<12) #define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16) -#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17) -#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18) -#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19) -#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20) - -#define BNX2_MISC_GPIO 0x0000081c -#define BNX2_MISC_GPIO_VALUE (0xffL<<0) -#define BNX2_MISC_GPIO_SET (0xffL<<8) -#define BNX2_MISC_GPIO_CLR (0xffL<<16) -#define BNX2_MISC_GPIO_FLOAT (0xffL<<24) - -#define BNX2_MISC_GPIO_INT 0x00000820 -#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0) -#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8) -#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16) -#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_17_TE (1L<<17) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18_TE (1L<<18) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_19_TE (1L<<19) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_TE (0xfffL<<20) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_MGMT_XI (1L<<17) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED2_XI (0x3fL<<18) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_VCO_XI (0x7L<<24) +#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED3_XI (1L<<27) +#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_XI (0xfL<<28) + +#define BNX2_MISC_SPIO 0x0000081c +#define BNX2_MISC_SPIO_VALUE (0xffL<<0) +#define BNX2_MISC_SPIO_SET (0xffL<<8) +#define BNX2_MISC_SPIO_CLR (0xffL<<16) +#define BNX2_MISC_SPIO_FLOAT (0xffL<<24) + +#define BNX2_MISC_SPIO_INT 0x00000820 +#define BNX2_MISC_SPIO_INT_INT_STATE_TE (0xfL<<0) +#define BNX2_MISC_SPIO_INT_OLD_VALUE_TE (0xfL<<8) +#define BNX2_MISC_SPIO_INT_OLD_SET_TE (0xfL<<16) +#define BNX2_MISC_SPIO_INT_OLD_CLR_TE (0xfL<<24) +#define BNX2_MISC_SPIO_INT_INT_STATE_XI (0xffL<<0) +#define BNX2_MISC_SPIO_INT_OLD_VALUE_XI (0xffL<<8) +#define BNX2_MISC_SPIO_INT_OLD_SET_XI (0xffL<<16) +#define BNX2_MISC_SPIO_INT_OLD_CLR_XI (0xffL<<24) #define BNX2_MISC_CONFIG_LFSR 0x00000824 #define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0) @@ -775,6 +946,8 @@ struct l2_fhdr { #define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25) #define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26) #define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27) +#define BNX2_MISC_LFSR_MASK_BITS_RV2P_CMD_SCHEDULER_ENABLE (1L<<28) +#define BNX2_MISC_LFSR_MASK_BITS_RSVD_FUTURE_ENABLE (0x7L<<29) #define BNX2_MISC_ARB_REQ0 0x0000082c #define BNX2_MISC_ARB_REQ1 0x00000830 @@ -831,22 +1004,12 @@ struct l2_fhdr { #define BNX2_MISC_ARB_GNT3_30 (0x7L<<24) #define BNX2_MISC_ARB_GNT3_31 (0x7L<<28) -#define BNX2_MISC_PRBS_CONTROL 0x00000878 -#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0) -#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1) -#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2) -#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3) -#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4) -#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4) -#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4) -#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4) -#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4) - -#define BNX2_MISC_PRBS_STATUS 0x0000087c -#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0) -#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1) -#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2) -#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16) +#define BNX2_MISC_RESERVED1 0x00000878 +#define BNX2_MISC_RESERVED1_MISC_RESERVED1_VALUE (0x3fL<<0) + +#define BNX2_MISC_RESERVED2 0x0000087c +#define BNX2_MISC_RESERVED2_PCIE_DIS (1L<<0) +#define BNX2_MISC_RESERVED2_LINK_IN_L23 (1L<<1) #define BNX2_MISC_SM_ASF_CONTROL 0x00000880 #define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0) @@ -857,13 +1020,15 @@ struct l2_fhdr { #define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5) #define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6) #define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7) -#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8) +#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_EN (1L<<8) +#define BNX2_MISC_SM_ASF_CONTROL_STRETCH_PULSE (1L<<9) +#define BNX2_MISC_SM_ASF_CONTROL_RES (0x3L<<10) #define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12) #define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13) #define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14) #define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15) -#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16) -#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24) +#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x7fL<<16) +#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x7fL<<23) #define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30) #define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31) @@ -891,13 +1056,13 @@ struct l2_fhdr { #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20) -#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (6L<<20) +#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20) -#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20) #define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24) #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25) #define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26) @@ -955,6 +1120,38 @@ struct l2_fhdr { #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29) #define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30) #define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31) +#define BNX2_MISC_PERR_ENA0_COM_DMAE_PERR_EN_XI (1L<<0) +#define BNX2_MISC_PERR_ENA0_CP_DMAE_PERR_EN_XI (1L<<1) +#define BNX2_MISC_PERR_ENA0_RPM_ACPIBEMEM_PERR_EN_XI (1L<<2) +#define BNX2_MISC_PERR_ENA0_CTX_USAGE_CNT_PERR_EN_XI (1L<<3) +#define BNX2_MISC_PERR_ENA0_CTX_PGTBL_PERR_EN_XI (1L<<4) +#define BNX2_MISC_PERR_ENA0_CTX_CACHE_PERR_EN_XI (1L<<5) +#define BNX2_MISC_PERR_ENA0_CTX_MIRROR_PERR_EN_XI (1L<<6) +#define BNX2_MISC_PERR_ENA0_COM_CTXC_PERR_EN_XI (1L<<7) +#define BNX2_MISC_PERR_ENA0_COM_SCPAD_PERR_EN_XI (1L<<8) +#define BNX2_MISC_PERR_ENA0_CP_CTXC_PERR_EN_XI (1L<<9) +#define BNX2_MISC_PERR_ENA0_CP_SCPAD_PERR_EN_XI (1L<<10) +#define BNX2_MISC_PERR_ENA0_RXP_RBUFC_PERR_EN_XI (1L<<11) +#define BNX2_MISC_PERR_ENA0_RXP_CTXC_PERR_EN_XI (1L<<12) +#define BNX2_MISC_PERR_ENA0_RXP_SCPAD_PERR_EN_XI (1L<<13) +#define BNX2_MISC_PERR_ENA0_TPAT_SCPAD_PERR_EN_XI (1L<<14) +#define BNX2_MISC_PERR_ENA0_TXP_CTXC_PERR_EN_XI (1L<<15) +#define BNX2_MISC_PERR_ENA0_TXP_SCPAD_PERR_EN_XI (1L<<16) +#define BNX2_MISC_PERR_ENA0_CS_TMEM_PERR_EN_XI (1L<<17) +#define BNX2_MISC_PERR_ENA0_MQ_CTX_PERR_EN_XI (1L<<18) +#define BNX2_MISC_PERR_ENA0_RPM_DFIFOMEM_PERR_EN_XI (1L<<19) +#define BNX2_MISC_PERR_ENA0_RPC_DFIFOMEM_PERR_EN_XI (1L<<20) +#define BNX2_MISC_PERR_ENA0_RBUF_PTRMEM_PERR_EN_XI (1L<<21) +#define BNX2_MISC_PERR_ENA0_RBUF_DATAMEM_PERR_EN_XI (1L<<22) +#define BNX2_MISC_PERR_ENA0_RV2P_P2IRAM_PERR_EN_XI (1L<<23) +#define BNX2_MISC_PERR_ENA0_RV2P_P1IRAM_PERR_EN_XI (1L<<24) +#define BNX2_MISC_PERR_ENA0_RV2P_CB1REGS_PERR_EN_XI (1L<<25) +#define BNX2_MISC_PERR_ENA0_RV2P_CB0REGS_PERR_EN_XI (1L<<26) +#define BNX2_MISC_PERR_ENA0_TPBUF_PERR_EN_XI (1L<<27) +#define BNX2_MISC_PERR_ENA0_THBUF_PERR_EN_XI (1L<<28) +#define BNX2_MISC_PERR_ENA0_TDMA_PERR_EN_XI (1L<<29) +#define BNX2_MISC_PERR_ENA0_TBDC_PERR_EN_XI (1L<<30) +#define BNX2_MISC_PERR_ENA0_TSCH_LR_PERR_EN_XI (1L<<31) #define BNX2_MISC_PERR_ENA1 0x000008a8 #define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0) @@ -989,6 +1186,35 @@ struct l2_fhdr { #define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29) #define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30) #define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31) +#define BNX2_MISC_PERR_ENA1_RBDC_PERR_EN_XI (1L<<0) +#define BNX2_MISC_PERR_ENA1_RDMA_DFIFO_PERR_EN_XI (1L<<2) +#define BNX2_MISC_PERR_ENA1_HC_STATS_PERR_EN_XI (1L<<3) +#define BNX2_MISC_PERR_ENA1_HC_MSIX_PERR_EN_XI (1L<<4) +#define BNX2_MISC_PERR_ENA1_HC_PRODUCSTB_PERR_EN_XI (1L<<5) +#define BNX2_MISC_PERR_ENA1_HC_CONSUMSTB_PERR_EN_XI (1L<<6) +#define BNX2_MISC_PERR_ENA1_TPATQ_PERR_EN_XI (1L<<7) +#define BNX2_MISC_PERR_ENA1_MCPQ_PERR_EN_XI (1L<<8) +#define BNX2_MISC_PERR_ENA1_TDMAQ_PERR_EN_XI (1L<<9) +#define BNX2_MISC_PERR_ENA1_TXPQ_PERR_EN_XI (1L<<10) +#define BNX2_MISC_PERR_ENA1_COMTQ_PERR_EN_XI (1L<<11) +#define BNX2_MISC_PERR_ENA1_COMQ_PERR_EN_XI (1L<<12) +#define BNX2_MISC_PERR_ENA1_RLUPQ_PERR_EN_XI (1L<<13) +#define BNX2_MISC_PERR_ENA1_RXPQ_PERR_EN_XI (1L<<14) +#define BNX2_MISC_PERR_ENA1_RV2PPQ_PERR_EN_XI (1L<<15) +#define BNX2_MISC_PERR_ENA1_RDMAQ_PERR_EN_XI (1L<<16) +#define BNX2_MISC_PERR_ENA1_TASQ_PERR_EN_XI (1L<<17) +#define BNX2_MISC_PERR_ENA1_TBDRQ_PERR_EN_XI (1L<<18) +#define BNX2_MISC_PERR_ENA1_TSCHQ_PERR_EN_XI (1L<<19) +#define BNX2_MISC_PERR_ENA1_COMXQ_PERR_EN_XI (1L<<20) +#define BNX2_MISC_PERR_ENA1_RXPCQ_PERR_EN_XI (1L<<21) +#define BNX2_MISC_PERR_ENA1_RV2PTQ_PERR_EN_XI (1L<<22) +#define BNX2_MISC_PERR_ENA1_RV2PMQ_PERR_EN_XI (1L<<23) +#define BNX2_MISC_PERR_ENA1_CPQ_PERR_EN_XI (1L<<24) +#define BNX2_MISC_PERR_ENA1_CSQ_PERR_EN_XI (1L<<25) +#define BNX2_MISC_PERR_ENA1_RLUP_CID_PERR_EN_XI (1L<<26) +#define BNX2_MISC_PERR_ENA1_RV2PCS_TMEM_PERR_EN_XI (1L<<27) +#define BNX2_MISC_PERR_ENA1_RV2PCSQ_PERR_EN_XI (1L<<28) +#define BNX2_MISC_PERR_ENA1_MQ_IDX_PERR_EN_XI (1L<<29) #define BNX2_MISC_PERR_ENA2 0x000008ac #define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0) @@ -1000,19 +1226,498 @@ struct l2_fhdr { #define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6) #define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7) #define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8) +#define BNX2_MISC_PERR_ENA2_TGT_FIFO_PERR_EN_XI (1L<<0) +#define BNX2_MISC_PERR_ENA2_UMP_TX_PERR_EN_XI (1L<<1) +#define BNX2_MISC_PERR_ENA2_UMP_RX_PERR_EN_XI (1L<<2) +#define BNX2_MISC_PERR_ENA2_MCP_ROM_PERR_EN_XI (1L<<3) +#define BNX2_MISC_PERR_ENA2_MCP_SCPAD_PERR_EN_XI (1L<<4) +#define BNX2_MISC_PERR_ENA2_HB_MEM_PERR_EN_XI (1L<<5) +#define BNX2_MISC_PERR_ENA2_PCIE_REPLAY_PERR_EN_XI (1L<<6) #define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0 #define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0) #define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12) +#define BNX2_MISC_DEBUG_VECTOR_SEL_1_XI (0xfffL<<15) #define BNX2_MISC_VREG_CONTROL 0x000008b4 #define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_XI (0xfL<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS14_XI (0L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS12_XI (1L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS10_XI (2L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS8_XI (3L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS6_XI (4L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS4_XI (5L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_PLUS2_XI (6L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_NOM_XI (7L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS2_XI (8L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS4_XI (9L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS6_XI (10L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS8_XI (11L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS10_XI (12L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS12_XI (13L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS14_XI (14L<<0) +#define BNX2_MISC_VREG_CONTROL_1_0_MAIN_MINUS16_XI (15L<<0) #define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS14 (0L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS12 (1L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS10 (2L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS8 (3L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS6 (4L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS4 (5L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_PLUS2 (6L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_NOM (7L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS2 (8L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS4 (9L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS6 (10L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS8 (11L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS10 (12L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS12 (13L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS14 (14L<<4) +#define BNX2_MISC_VREG_CONTROL_2_5_MINUS16 (15L<<4) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT (0xfL<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS14 (0L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS12 (1L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS10 (2L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS8 (3L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS6 (4L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS4 (5L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_PLUS2 (6L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_NOM (7L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS2 (8L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS4 (9L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS6 (10L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS8 (11L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS10 (12L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS12 (13L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS14 (14L<<8) +#define BNX2_MISC_VREG_CONTROL_1_0_MGMT_MINUS16 (15L<<8) #define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8 #define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6) -#define BNX2_MISC_UNUSED0 0x000008bc +#define BNX2_MISC_GP_HW_CTL0 0x000008bc +#define BNX2_MISC_GP_HW_CTL0_TX_DRIVE (1L<<0) +#define BNX2_MISC_GP_HW_CTL0_RMII_MODE (1L<<1) +#define BNX2_MISC_GP_HW_CTL0_RMII_CRSDV_SEL (1L<<2) +#define BNX2_MISC_GP_HW_CTL0_RVMII_MODE (1L<<3) +#define BNX2_MISC_GP_HW_CTL0_FLASH_SAMP_SCLK_NEGEDGE_TE (1L<<4) +#define BNX2_MISC_GP_HW_CTL0_HIDDEN_REVISION_ID_TE (1L<<5) +#define BNX2_MISC_GP_HW_CTL0_HC_CNTL_TMOUT_CTR_RST_TE (1L<<6) +#define BNX2_MISC_GP_HW_CTL0_RESERVED1_XI (0x7L<<4) +#define BNX2_MISC_GP_HW_CTL0_ENA_CORE_RST_ON_MAIN_PWR_GOING_AWAY (1L<<7) +#define BNX2_MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE (1L<<8) +#define BNX2_MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE (1L<<9) +#define BNX2_MISC_GP_HW_CTL0_LED_ACT_SEL_TE (1L<<10) +#define BNX2_MISC_GP_HW_CTL0_RESERVED2_XI (0x7L<<8) +#define BNX2_MISC_GP_HW_CTL0_UP1_DEF0 (1L<<11) +#define BNX2_MISC_GP_HW_CTL0_FIBER_MODE_DIS_DEF (1L<<12) +#define BNX2_MISC_GP_HW_CTL0_FORCE2500_DEF (1L<<13) +#define BNX2_MISC_GP_HW_CTL0_AUTODETECT_DIS_DEF (1L<<14) +#define BNX2_MISC_GP_HW_CTL0_PARALLEL_DETECT_DEF (1L<<15) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI (0xfL<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_3MA (0L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P5MA (1L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_2P0MA (3L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P5MA (5L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_1P0MA (7L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_DAI_PWRDN (15L<<16) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE2DIS (1L<<20) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PRE1DIS (1L<<21) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT (0x3L<<22) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M6P (0L<<22) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_M0P (1L<<22) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P0P (2L<<22) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_CTAT_P6P (3L<<22) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT (0x3L<<24) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M6P (0L<<24) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_M0P (1L<<24) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P0P (2L<<24) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_PTAT_P6P (3L<<24) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ (0x3L<<26) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_240UA (0L<<26) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_160UA (1L<<26) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_400UA (2L<<26) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_IAMP_ADJ_320UA (3L<<26) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ (0x3L<<28) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_240UA (0L<<28) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_160UA (1L<<28) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_400UA (2L<<28) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_ICBUF_ADJ_320UA (3L<<28) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ (0x3L<<30) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P57 (0L<<30) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P45 (1L<<30) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P62 (2L<<30) +#define BNX2_MISC_GP_HW_CTL0_OSCCTRL_XTAL_ADJ_1P66 (3L<<30) + +#define BNX2_MISC_GP_HW_CTL1 0x000008c0 +#define BNX2_MISC_GP_HW_CTL1_1_ATTN_BTN_PRSNT_TE (1L<<0) +#define BNX2_MISC_GP_HW_CTL1_1_ATTN_IND_PRSNT_TE (1L<<1) +#define BNX2_MISC_GP_HW_CTL1_1_PWR_IND_PRSNT_TE (1L<<2) +#define BNX2_MISC_GP_HW_CTL1_0_PCIE_LOOPBACK_TE (1L<<3) +#define BNX2_MISC_GP_HW_CTL1_RESERVED_SOFT_XI (0xffffL<<0) +#define BNX2_MISC_GP_HW_CTL1_RESERVED_HARD_XI (0xffffL<<16) + +#define BNX2_MISC_NEW_HW_CTL 0x000008c4 +#define BNX2_MISC_NEW_HW_CTL_MAIN_POR_BYPASS (1L<<0) +#define BNX2_MISC_NEW_HW_CTL_RINGOSC_ENABLE (1L<<1) +#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL0 (1L<<2) +#define BNX2_MISC_NEW_HW_CTL_RINGOSC_SEL1 (1L<<3) +#define BNX2_MISC_NEW_HW_CTL_RESERVED_SHARED (0xfffL<<4) +#define BNX2_MISC_NEW_HW_CTL_RESERVED_SPLIT (0xffffL<<16) + +#define BNX2_MISC_NEW_CORE_CTL 0x000008c8 +#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_SUCCESS (1L<<0) +#define BNX2_MISC_NEW_CORE_CTL_LINK_HOLDOFF_REQ (1L<<1) +#define BNX2_MISC_NEW_CORE_CTL_RESERVED_CMN (0x3fffL<<2) +#define BNX2_MISC_NEW_CORE_CTL_RESERVED_TC (0xffffL<<16) + +#define BNX2_MISC_ECO_HW_CTL 0x000008cc +#define BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN (1L<<0) +#define BNX2_MISC_ECO_HW_CTL_RESERVED_SOFT (0x7fffL<<1) +#define BNX2_MISC_ECO_HW_CTL_RESERVED_HARD (0xffffL<<16) + +#define BNX2_MISC_ECO_CORE_CTL 0x000008d0 +#define BNX2_MISC_ECO_CORE_CTL_RESERVED_SOFT (0xffffL<<0) +#define BNX2_MISC_ECO_CORE_CTL_RESERVED_HARD (0xffffL<<16) + +#define BNX2_MISC_PPIO 0x000008d4 +#define BNX2_MISC_PPIO_VALUE (0xfL<<0) +#define BNX2_MISC_PPIO_SET (0xfL<<8) +#define BNX2_MISC_PPIO_CLR (0xfL<<16) +#define BNX2_MISC_PPIO_FLOAT (0xfL<<24) + +#define BNX2_MISC_PPIO_INT 0x000008d8 +#define BNX2_MISC_PPIO_INT_INT_STATE (0xfL<<0) +#define BNX2_MISC_PPIO_INT_OLD_VALUE (0xfL<<8) +#define BNX2_MISC_PPIO_INT_OLD_SET (0xfL<<16) +#define BNX2_MISC_PPIO_INT_OLD_CLR (0xfL<<24) + +#define BNX2_MISC_RESET_NUMS 0x000008dc +#define BNX2_MISC_RESET_NUMS_NUM_HARD_RESETS (0x7L<<0) +#define BNX2_MISC_RESET_NUMS_NUM_PCIE_RESETS (0x7L<<4) +#define BNX2_MISC_RESET_NUMS_NUM_PERSTB_RESETS (0x7L<<8) +#define BNX2_MISC_RESET_NUMS_NUM_CMN_RESETS (0x7L<<12) +#define BNX2_MISC_RESET_NUMS_NUM_PORT_RESETS (0x7L<<16) + +#define BNX2_MISC_CS16_ERR 0x000008e0 +#define BNX2_MISC_CS16_ERR_ENA_PCI (1L<<0) +#define BNX2_MISC_CS16_ERR_ENA_RDMA (1L<<1) +#define BNX2_MISC_CS16_ERR_ENA_TDMA (1L<<2) +#define BNX2_MISC_CS16_ERR_ENA_EMAC (1L<<3) +#define BNX2_MISC_CS16_ERR_ENA_CTX (1L<<4) +#define BNX2_MISC_CS16_ERR_ENA_TBDR (1L<<5) +#define BNX2_MISC_CS16_ERR_ENA_RBDC (1L<<6) +#define BNX2_MISC_CS16_ERR_ENA_COM (1L<<7) +#define BNX2_MISC_CS16_ERR_ENA_CP (1L<<8) +#define BNX2_MISC_CS16_ERR_STA_PCI (1L<<16) +#define BNX2_MISC_CS16_ERR_STA_RDMA (1L<<17) +#define BNX2_MISC_CS16_ERR_STA_TDMA (1L<<18) +#define BNX2_MISC_CS16_ERR_STA_EMAC (1L<<19) +#define BNX2_MISC_CS16_ERR_STA_CTX (1L<<20) +#define BNX2_MISC_CS16_ERR_STA_TBDR (1L<<21) +#define BNX2_MISC_CS16_ERR_STA_RBDC (1L<<22) +#define BNX2_MISC_CS16_ERR_STA_COM (1L<<23) +#define BNX2_MISC_CS16_ERR_STA_CP (1L<<24) + +#define BNX2_MISC_SPIO_EVENT 0x000008e4 +#define BNX2_MISC_SPIO_EVENT_ENABLE (0xffL<<0) + +#define BNX2_MISC_PPIO_EVENT 0x000008e8 +#define BNX2_MISC_PPIO_EVENT_ENABLE (0xfL<<0) + +#define BNX2_MISC_DUAL_MEDIA_CTRL 0x000008ec +#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID (0xffL<<0) +#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_X (0L<<0) +#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C (3L<<0) +#define BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_S (12L<<0) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP (0x7L<<8) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN (1L<<11) +#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_SIGDET (1L<<12) +#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_SIGDET (1L<<13) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_SIGDET (1L<<14) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_SIGDET (1L<<15) +#define BNX2_MISC_DUAL_MEDIA_CTRL_LCPLL_RST (1L<<16) +#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES1_RST (1L<<17) +#define BNX2_MISC_DUAL_MEDIA_CTRL_SERDES0_RST (1L<<18) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY1_RST (1L<<19) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY0_RST (1L<<20) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_CTRL (0x7L<<21) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PORT_SWAP (1L<<24) +#define BNX2_MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE (1L<<25) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ (0xfL<<26) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER1_IDDQ (1L<<26) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_SER0_IDDQ (2L<<26) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY1_IDDQ (4L<<26) +#define BNX2_MISC_DUAL_MEDIA_CTRL_PHY_SERDES_IDDQ_PHY0_IDDQ (8L<<26) + +#define BNX2_MISC_OTP_CMD1 0x000008f0 +#define BNX2_MISC_OTP_CMD1_FMODE (0x7L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_IDLE (0L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_WRITE (1L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_INIT (2L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_SET (3L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_RST (4L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_VERIFY (5L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED0 (6L<<0) +#define BNX2_MISC_OTP_CMD1_FMODE_RESERVED1 (7L<<0) +#define BNX2_MISC_OTP_CMD1_USEPINS (1L<<8) +#define BNX2_MISC_OTP_CMD1_PROGSEL (1L<<9) +#define BNX2_MISC_OTP_CMD1_PROGSTART (1L<<10) +#define BNX2_MISC_OTP_CMD1_PCOUNT (0x7L<<16) +#define BNX2_MISC_OTP_CMD1_PBYP (1L<<19) +#define BNX2_MISC_OTP_CMD1_VSEL (0xfL<<20) +#define BNX2_MISC_OTP_CMD1_TM (0x7L<<27) +#define BNX2_MISC_OTP_CMD1_SADBYP (1L<<30) +#define BNX2_MISC_OTP_CMD1_DEBUG (1L<<31) + +#define BNX2_MISC_OTP_CMD2 0x000008f4 +#define BNX2_MISC_OTP_CMD2_OTP_ROM_ADDR (0x3ffL<<0) +#define BNX2_MISC_OTP_CMD2_DOSEL (0x7fL<<16) +#define BNX2_MISC_OTP_CMD2_DOSEL_0 (0L<<16) +#define BNX2_MISC_OTP_CMD2_DOSEL_1 (1L<<16) +#define BNX2_MISC_OTP_CMD2_DOSEL_127 (127L<<16) + +#define BNX2_MISC_OTP_STATUS 0x000008f8 +#define BNX2_MISC_OTP_STATUS_DATA (0xffL<<0) +#define BNX2_MISC_OTP_STATUS_VALID (1L<<8) +#define BNX2_MISC_OTP_STATUS_BUSY (1L<<9) +#define BNX2_MISC_OTP_STATUS_BUSYSM (1L<<10) +#define BNX2_MISC_OTP_STATUS_DONE (1L<<11) + +#define BNX2_MISC_OTP_SHIFT1_CMD 0x000008fc +#define BNX2_MISC_OTP_SHIFT1_CMD_RESET_MODE_N (1L<<0) +#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_DONE (1L<<1) +#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_START (1L<<2) +#define BNX2_MISC_OTP_SHIFT1_CMD_LOAD_DATA (1L<<3) +#define BNX2_MISC_OTP_SHIFT1_CMD_SHIFT_SELECT (0x1fL<<8) + +#define BNX2_MISC_OTP_SHIFT1_DATA 0x00000900 +#define BNX2_MISC_OTP_SHIFT2_CMD 0x00000904 +#define BNX2_MISC_OTP_SHIFT2_CMD_RESET_MODE_N (1L<<0) +#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_DONE (1L<<1) +#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_START (1L<<2) +#define BNX2_MISC_OTP_SHIFT2_CMD_LOAD_DATA (1L<<3) +#define BNX2_MISC_OTP_SHIFT2_CMD_SHIFT_SELECT (0x1fL<<8) + +#define BNX2_MISC_OTP_SHIFT2_DATA 0x00000908 +#define BNX2_MISC_BIST_CS0 0x0000090c +#define BNX2_MISC_BIST_CS0_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS0_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS0_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS0_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS0_MBIST_GO (1L<<9) +#define BNX2_MISC_BIST_CS0_BIST_OVERRIDE (1L<<31) + +#define BNX2_MISC_BIST_MEMSTATUS0 0x00000910 +#define BNX2_MISC_BIST_CS1 0x00000914 +#define BNX2_MISC_BIST_CS1_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS1_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS1_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS1_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS1_MBIST_GO (1L<<9) + +#define BNX2_MISC_BIST_MEMSTATUS1 0x00000918 +#define BNX2_MISC_BIST_CS2 0x0000091c +#define BNX2_MISC_BIST_CS2_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS2_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS2_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS2_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS2_MBIST_GO (1L<<9) + +#define BNX2_MISC_BIST_MEMSTATUS2 0x00000920 +#define BNX2_MISC_BIST_CS3 0x00000924 +#define BNX2_MISC_BIST_CS3_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS3_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS3_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS3_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS3_MBIST_GO (1L<<9) + +#define BNX2_MISC_BIST_MEMSTATUS3 0x00000928 +#define BNX2_MISC_BIST_CS4 0x0000092c +#define BNX2_MISC_BIST_CS4_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS4_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS4_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS4_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS4_MBIST_GO (1L<<9) + +#define BNX2_MISC_BIST_MEMSTATUS4 0x00000930 +#define BNX2_MISC_BIST_CS5 0x00000934 +#define BNX2_MISC_BIST_CS5_MBIST_EN (1L<<0) +#define BNX2_MISC_BIST_CS5_BIST_SETUP (0x3L<<1) +#define BNX2_MISC_BIST_CS5_MBIST_ASYNC_RESET (1L<<3) +#define BNX2_MISC_BIST_CS5_MBIST_DONE (1L<<8) +#define BNX2_MISC_BIST_CS5_MBIST_GO (1L<<9) + +#define BNX2_MISC_BIST_MEMSTATUS5 0x00000938 +#define BNX2_MISC_MEM_TM0 0x0000093c +#define BNX2_MISC_MEM_TM0_PCIE_REPLAY_TM (0xfL<<0) +#define BNX2_MISC_MEM_TM0_MCP_SCPAD (0xfL<<8) +#define BNX2_MISC_MEM_TM0_UMP_TM (0xffL<<16) +#define BNX2_MISC_MEM_TM0_HB_MEM_TM (0xfL<<24) + +#define BNX2_MISC_USPLL_CTRL 0x00000940 +#define BNX2_MISC_USPLL_CTRL_PH_DET_DIS (1L<<0) +#define BNX2_MISC_USPLL_CTRL_FREQ_DET_DIS (1L<<1) +#define BNX2_MISC_USPLL_CTRL_LCPX (0x3fL<<2) +#define BNX2_MISC_USPLL_CTRL_RX (0x3L<<8) +#define BNX2_MISC_USPLL_CTRL_VC_EN (1L<<10) +#define BNX2_MISC_USPLL_CTRL_VCO_MG (0x3L<<11) +#define BNX2_MISC_USPLL_CTRL_KVCO_XF (0x7L<<13) +#define BNX2_MISC_USPLL_CTRL_KVCO_XS (0x7L<<16) +#define BNX2_MISC_USPLL_CTRL_TESTD_EN (1L<<19) +#define BNX2_MISC_USPLL_CTRL_TESTD_SEL (0x7L<<20) +#define BNX2_MISC_USPLL_CTRL_TESTA_EN (1L<<23) +#define BNX2_MISC_USPLL_CTRL_TESTA_SEL (0x3L<<24) +#define BNX2_MISC_USPLL_CTRL_ATTEN_FREF (1L<<26) +#define BNX2_MISC_USPLL_CTRL_DIGITAL_RST (1L<<27) +#define BNX2_MISC_USPLL_CTRL_ANALOG_RST (1L<<28) +#define BNX2_MISC_USPLL_CTRL_LOCK (1L<<29) + +#define BNX2_MISC_PERR_STATUS0 0x00000944 +#define BNX2_MISC_PERR_STATUS0_COM_DMAE_PERR (1L<<0) +#define BNX2_MISC_PERR_STATUS0_CP_DMAE_PERR (1L<<1) +#define BNX2_MISC_PERR_STATUS0_RPM_ACPIBEMEM_PERR (1L<<2) +#define BNX2_MISC_PERR_STATUS0_CTX_USAGE_CNT_PERR (1L<<3) +#define BNX2_MISC_PERR_STATUS0_CTX_PGTBL_PERR (1L<<4) +#define BNX2_MISC_PERR_STATUS0_CTX_CACHE_PERR (1L<<5) +#define BNX2_MISC_PERR_STATUS0_CTX_MIRROR_PERR (1L<<6) +#define BNX2_MISC_PERR_STATUS0_COM_CTXC_PERR (1L<<7) +#define BNX2_MISC_PERR_STATUS0_COM_SCPAD_PERR (1L<<8) +#define BNX2_MISC_PERR_STATUS0_CP_CTXC_PERR (1L<<9) +#define BNX2_MISC_PERR_STATUS0_CP_SCPAD_PERR (1L<<10) +#define BNX2_MISC_PERR_STATUS0_RXP_RBUFC_PERR (1L<<11) +#define BNX2_MISC_PERR_STATUS0_RXP_CTXC_PERR (1L<<12) +#define BNX2_MISC_PERR_STATUS0_RXP_SCPAD_PERR (1L<<13) +#define BNX2_MISC_PERR_STATUS0_TPAT_SCPAD_PERR (1L<<14) +#define BNX2_MISC_PERR_STATUS0_TXP_CTXC_PERR (1L<<15) +#define BNX2_MISC_PERR_STATUS0_TXP_SCPAD_PERR (1L<<16) +#define BNX2_MISC_PERR_STATUS0_CS_TMEM_PERR (1L<<17) +#define BNX2_MISC_PERR_STATUS0_MQ_CTX_PERR (1L<<18) +#define BNX2_MISC_PERR_STATUS0_RPM_DFIFOMEM_PERR (1L<<19) +#define BNX2_MISC_PERR_STATUS0_RPC_DFIFOMEM_PERR (1L<<20) +#define BNX2_MISC_PERR_STATUS0_RBUF_PTRMEM_PERR (1L<<21) +#define BNX2_MISC_PERR_STATUS0_RBUF_DATAMEM_PERR (1L<<22) +#define BNX2_MISC_PERR_STATUS0_RV2P_P2IRAM_PERR (1L<<23) +#define BNX2_MISC_PERR_STATUS0_RV2P_P1IRAM_PERR (1L<<24) +#define BNX2_MISC_PERR_STATUS0_RV2P_CB1REGS_PERR (1L<<25) +#define BNX2_MISC_PERR_STATUS0_RV2P_CB0REGS_PERR (1L<<26) +#define BNX2_MISC_PERR_STATUS0_TPBUF_PERR (1L<<27) +#define BNX2_MISC_PERR_STATUS0_THBUF_PERR (1L<<28) +#define BNX2_MISC_PERR_STATUS0_TDMA_PERR (1L<<29) +#define BNX2_MISC_PERR_STATUS0_TBDC_PERR (1L<<30) +#define BNX2_MISC_PERR_STATUS0_TSCH_LR_PERR (1L<<31) + +#define BNX2_MISC_PERR_STATUS1 0x00000948 +#define BNX2_MISC_PERR_STATUS1_RBDC_PERR (1L<<0) +#define BNX2_MISC_PERR_STATUS1_RDMA_DFIFO_PERR (1L<<2) +#define BNX2_MISC_PERR_STATUS1_HC_STATS_PERR (1L<<3) +#define BNX2_MISC_PERR_STATUS1_HC_MSIX_PERR (1L<<4) +#define BNX2_MISC_PERR_STATUS1_HC_PRODUCSTB_PERR (1L<<5) +#define BNX2_MISC_PERR_STATUS1_HC_CONSUMSTB_PERR (1L<<6) +#define BNX2_MISC_PERR_STATUS1_TPATQ_PERR (1L<<7) +#define BNX2_MISC_PERR_STATUS1_MCPQ_PERR (1L<<8) +#define BNX2_MISC_PERR_STATUS1_TDMAQ_PERR (1L<<9) +#define BNX2_MISC_PERR_STATUS1_TXPQ_PERR (1L<<10) +#define BNX2_MISC_PERR_STATUS1_COMTQ_PERR (1L<<11) +#define BNX2_MISC_PERR_STATUS1_COMQ_PERR (1L<<12) +#define BNX2_MISC_PERR_STATUS1_RLUPQ_PERR (1L<<13) +#define BNX2_MISC_PERR_STATUS1_RXPQ_PERR (1L<<14) +#define BNX2_MISC_PERR_STATUS1_RV2PPQ_PERR (1L<<15) +#define BNX2_MISC_PERR_STATUS1_RDMAQ_PERR (1L<<16) +#define BNX2_MISC_PERR_STATUS1_TASQ_PERR (1L<<17) +#define BNX2_MISC_PERR_STATUS1_TBDRQ_PERR (1L<<18) +#define BNX2_MISC_PERR_STATUS1_TSCHQ_PERR (1L<<19) +#define BNX2_MISC_PERR_STATUS1_COMXQ_PERR (1L<<20) +#define BNX2_MISC_PERR_STATUS1_RXPCQ_PERR (1L<<21) +#define BNX2_MISC_PERR_STATUS1_RV2PTQ_PERR (1L<<22) +#define BNX2_MISC_PERR_STATUS1_RV2PMQ_PERR (1L<<23) +#define BNX2_MISC_PERR_STATUS1_CPQ_PERR (1L<<24) +#define BNX2_MISC_PERR_STATUS1_CSQ_PERR (1L<<25) +#define BNX2_MISC_PERR_STATUS1_RLUP_CID_PERR (1L<<26) +#define BNX2_MISC_PERR_STATUS1_RV2PCS_TMEM_PERR (1L<<27) +#define BNX2_MISC_PERR_STATUS1_RV2PCSQ_PERR (1L<<28) +#define BNX2_MISC_PERR_STATUS1_MQ_IDX_PERR (1L<<29) + +#define BNX2_MISC_PERR_STATUS2 0x0000094c +#define BNX2_MISC_PERR_STATUS2_TGT_FIFO_PERR (1L<<0) +#define BNX2_MISC_PERR_STATUS2_UMP_TX_PERR (1L<<1) +#define BNX2_MISC_PERR_STATUS2_UMP_RX_PERR (1L<<2) +#define BNX2_MISC_PERR_STATUS2_MCP_ROM_PERR (1L<<3) +#define BNX2_MISC_PERR_STATUS2_MCP_SCPAD_PERR (1L<<4) +#define BNX2_MISC_PERR_STATUS2_HB_MEM_PERR (1L<<5) +#define BNX2_MISC_PERR_STATUS2_PCIE_REPLAY_PERR (1L<<6) + +#define BNX2_MISC_LCPLL_CTRL0 0x00000950 +#define BNX2_MISC_LCPLL_CTRL0_OAC (0x7L<<0) +#define BNX2_MISC_LCPLL_CTRL0_OAC_NEGTWENTY (0L<<0) +#define BNX2_MISC_LCPLL_CTRL0_OAC_ZERO (1L<<0) +#define BNX2_MISC_LCPLL_CTRL0_OAC_TWENTY (3L<<0) +#define BNX2_MISC_LCPLL_CTRL0_OAC_FORTY (7L<<0) +#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL (0x7L<<3) +#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_360 (0L<<3) +#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_480 (1L<<3) +#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_600 (3L<<3) +#define BNX2_MISC_LCPLL_CTRL0_ICP_CTRL_720 (7L<<3) +#define BNX2_MISC_LCPLL_CTRL0_BIAS_CTRL (0x3L<<6) +#define BNX2_MISC_LCPLL_CTRL0_PLL_OBSERVE (0x7L<<8) +#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL (0x3L<<11) +#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_0 (0L<<11) +#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_1 (1L<<11) +#define BNX2_MISC_LCPLL_CTRL0_VTH_CTRL_2 (2L<<11) +#define BNX2_MISC_LCPLL_CTRL0_PLLSEQSTART (1L<<13) +#define BNX2_MISC_LCPLL_CTRL0_RESERVED (1L<<14) +#define BNX2_MISC_LCPLL_CTRL0_CAPRETRY_EN (1L<<15) +#define BNX2_MISC_LCPLL_CTRL0_FREQMONITOR_EN (1L<<16) +#define BNX2_MISC_LCPLL_CTRL0_FREQDETRESTART_EN (1L<<17) +#define BNX2_MISC_LCPLL_CTRL0_FREQDETRETRY_EN (1L<<18) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE_EN (1L<<19) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFDONE (1L<<20) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCEFPASS (1L<<21) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE_EN (1L<<22) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPDONE (1L<<23) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS_EN (1L<<24) +#define BNX2_MISC_LCPLL_CTRL0_PLLFORCECAPPASS (1L<<25) +#define BNX2_MISC_LCPLL_CTRL0_CAPRESTART (1L<<26) +#define BNX2_MISC_LCPLL_CTRL0_CAPSELECTM_EN (1L<<27) + +#define BNX2_MISC_LCPLL_CTRL1 0x00000954 +#define BNX2_MISC_LCPLL_CTRL1_CAPSELECTM (0x1fL<<0) +#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN_EN (1L<<5) +#define BNX2_MISC_LCPLL_CTRL1_CAPFORCESLOWDOWN (1L<<6) +#define BNX2_MISC_LCPLL_CTRL1_SLOWDN_XOR (1L<<7) + +#define BNX2_MISC_LCPLL_STATUS 0x00000958 +#define BNX2_MISC_LCPLL_STATUS_FREQDONE_SM (1L<<0) +#define BNX2_MISC_LCPLL_STATUS_FREQPASS_SM (1L<<1) +#define BNX2_MISC_LCPLL_STATUS_PLLSEQDONE (1L<<2) +#define BNX2_MISC_LCPLL_STATUS_PLLSEQPASS (1L<<3) +#define BNX2_MISC_LCPLL_STATUS_PLLSTATE (0x7L<<4) +#define BNX2_MISC_LCPLL_STATUS_CAPSTATE (0x7L<<7) +#define BNX2_MISC_LCPLL_STATUS_CAPSELECT (0x1fL<<10) +#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR (1L<<15) +#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_0 (0L<<15) +#define BNX2_MISC_LCPLL_STATUS_SLOWDN_INDICATOR_1 (1L<<15) + +#define BNX2_MISC_OSCFUNDS_CTRL 0x0000095c +#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON (1L<<5) +#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_OFF (0L<<5) +#define BNX2_MISC_OSCFUNDS_CTRL_FREQ_MON_ON (1L<<5) +#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM (0x3L<<6) +#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_0 (0L<<6) +#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_1 (1L<<6) +#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_2 (2L<<6) +#define BNX2_MISC_OSCFUNDS_CTRL_XTAL_ADJCM_3 (3L<<6) +#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ (0x3L<<8) +#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_0 (0L<<8) +#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_1 (1L<<8) +#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_2 (2L<<8) +#define BNX2_MISC_OSCFUNDS_CTRL_ICBUF_ADJ_3 (3L<<8) +#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ (0x3L<<10) +#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_0 (0L<<10) +#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_1 (1L<<10) +#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_2 (2L<<10) +#define BNX2_MISC_OSCFUNDS_CTRL_IAMP_ADJ_3 (3L<<10) /* @@ -1031,11 +1736,35 @@ struct l2_fhdr { #define BNX2_NVM_COMMAND_WRDI (1L<<17) #define BNX2_NVM_COMMAND_EWSR (1L<<18) #define BNX2_NVM_COMMAND_WRSR (1L<<19) +#define BNX2_NVM_COMMAND_RD_ID (1L<<20) +#define BNX2_NVM_COMMAND_RD_STATUS (1L<<21) +#define BNX2_NVM_COMMAND_MODE_256 (1L<<22) #define BNX2_NVM_STATUS 0x00006404 #define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0) #define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4) #define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_XI (0x1fL<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_IDLE_XI (0L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD0_XI (1L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD1_XI (2L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH0_XI (3L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CMD_FINISH1_XI (4L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ADDR0_XI (5L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA0_XI (6L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA1_XI (7L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WRITE_DATA2_XI (8L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA0_XI (9L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA1_XI (10L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_DATA2_XI (11L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID0_XI (12L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID1_XI (13L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID2_XI (14L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID3_XI (15L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_READ_STATUS_RDID4_XI (16L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_CHECK_BUSY0_XI (17L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_ST_WREN_XI (18L<<0) +#define BNX2_NVM_STATUS_SPI_FSM_STATE_SPI_WAIT_XI (19L<<0) #define BNX2_NVM_WRITE 0x00006408 #define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0) @@ -1046,6 +1775,10 @@ struct l2_fhdr { #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0) #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0) #define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI_XI (1L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO_XI (2L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B_XI (4L<<0) +#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK_XI (8L<<0) #define BNX2_NVM_ADDR 0x0000640c #define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0) @@ -1056,6 +1789,10 @@ struct l2_fhdr { #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0) #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0) #define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI_XI (1L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO_XI (2L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B_XI (4L<<0) +#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK_XI (8L<<0) #define BNX2_NVM_READ 0x00006410 #define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0) @@ -1066,6 +1803,10 @@ struct l2_fhdr { #define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0) #define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0) #define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SI_XI (1L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SO_XI (2L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B_XI (4L<<0) +#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK_XI (8L<<0) #define BNX2_NVM_CFG1 0x00006414 #define BNX2_NVM_CFG1_FLASH_MODE (1L<<0) @@ -1077,14 +1818,21 @@ struct l2_fhdr { #define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4) #define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7) #define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11) +#define BNX2_NVM_CFG1_STRAP_CONTROL_0 (1L<<23) #define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24) #define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25) +#define BNX2_NVM_CFG1_FW_USTRAP_1 (1L<<26) +#define BNX2_NVM_CFG1_FW_USTRAP_0 (1L<<27) +#define BNX2_NVM_CFG1_FW_USTRAP_2 (1L<<28) +#define BNX2_NVM_CFG1_FW_USTRAP_3 (1L<<29) +#define BNX2_NVM_CFG1_FW_FLASH_TYPE_EN (1L<<30) #define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31) #define BNX2_NVM_CFG2 0x00006418 #define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0) #define BNX2_NVM_CFG2_DUMMY (0xffL<<8) #define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16) +#define BNX2_NVM_CFG2_READ_ID (0xffL<<24) #define BNX2_NVM_CFG3 0x0000641c #define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0) @@ -1119,6 +1867,35 @@ struct l2_fhdr { #define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8) #define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16) +#define BNX2_NVM_CFG4 0x0000642c +#define BNX2_NVM_CFG4_FLASH_SIZE (0x7L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_1MBIT (0L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_2MBIT (1L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_4MBIT (2L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_8MBIT (3L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_16MBIT (4L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_32MBIT (5L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_64MBIT (6L<<0) +#define BNX2_NVM_CFG4_FLASH_SIZE_128MBIT (7L<<0) +#define BNX2_NVM_CFG4_FLASH_VENDOR (1L<<3) +#define BNX2_NVM_CFG4_FLASH_VENDOR_ST (0L<<3) +#define BNX2_NVM_CFG4_FLASH_VENDOR_ATMEL (1L<<3) +#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC (0x3L<<4) +#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT8 (0L<<4) +#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT9 (1L<<4) +#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT10 (2L<<4) +#define BNX2_NVM_CFG4_MODE_256_EMPTY_BIT_LOC_BIT11 (3L<<4) +#define BNX2_NVM_CFG4_STATUS_BIT_POLARITY (1L<<6) +#define BNX2_NVM_CFG4_RESERVED (0x1ffffffL<<7) + +#define BNX2_NVM_RECONFIG 0x00006430 +#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE (0xfL<<0) +#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ST (0L<<0) +#define BNX2_NVM_RECONFIG_ORIG_STRAP_VALUE_ATMEL (1L<<0) +#define BNX2_NVM_RECONFIG_RECONFIG_STRAP_VALUE (0xfL<<4) +#define BNX2_NVM_RECONFIG_RESERVED (0x7fffffL<<8) +#define BNX2_NVM_RECONFIG_RECONFIG_DONE (1L<<31) + /* @@ -1140,6 +1917,8 @@ struct l2_fhdr { #define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23) #define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24) #define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25) +#define BNX2_DMA_STATUS_GLOBAL_ERR_XI (1L<<0) +#define BNX2_DMA_STATUS_BME_XI (1L<<4) #define BNX2_DMA_CONFIG 0x00000c08 #define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0) @@ -1161,85 +1940,315 @@ struct l2_fhdr { #define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24) #define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24) #define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24) +#define BNX2_DMA_CONFIG_DAT_WBSWAP_MODE_XI (0x3L<<0) +#define BNX2_DMA_CONFIG_CTL_WBSWAP_MODE_XI (0x3L<<4) +#define BNX2_DMA_CONFIG_MAX_PL_XI (0x7L<<12) +#define BNX2_DMA_CONFIG_MAX_PL_128B_XI (0L<<12) +#define BNX2_DMA_CONFIG_MAX_PL_256B_XI (1L<<12) +#define BNX2_DMA_CONFIG_MAX_PL_512B_XI (2L<<12) +#define BNX2_DMA_CONFIG_MAX_PL_EN_XI (1L<<15) +#define BNX2_DMA_CONFIG_MAX_RRS_XI (0x7L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_128B_XI (0L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_256B_XI (1L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_512B_XI (2L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_1024B_XI (3L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_2048B_XI (4L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_4096B_XI (5L<<16) +#define BNX2_DMA_CONFIG_MAX_RRS_EN_XI (1L<<19) +#define BNX2_DMA_CONFIG_NO_64SWAP_EN_XI (1L<<31) #define BNX2_DMA_BLACKOUT 0x00000c0c #define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0) #define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8) #define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16) -#define BNX2_DMA_RCHAN_STAT 0x00000c30 -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27) -#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28) -#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31) - -#define BNX2_DMA_WCHAN_STAT 0x00000c34 -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27) -#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28) -#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31) - -#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38 -#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0) -#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4) -#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8) -#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12) -#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16) -#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20) -#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24) -#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28) - -#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c -#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0) -#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4) -#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8) -#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12) -#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16) -#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20) -#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24) -#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28) - -#define BNX2_DMA_RCHAN_STAT_00 0x00000c40 -#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0) - -#define BNX2_DMA_RCHAN_STAT_01 0x00000c44 -#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0) - -#define BNX2_DMA_RCHAN_STAT_02 0x00000c48 -#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0) -#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16) -#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17) -#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18) - -#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c -#define BNX2_DMA_RCHAN_STAT_11 0x00000c50 -#define BNX2_DMA_RCHAN_STAT_12 0x00000c54 -#define BNX2_DMA_RCHAN_STAT_20 0x00000c58 -#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c +#define BNX2_DMA_READ_MASTER_SETTING_0 0x00000c10 +#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_NO_SNOOP (1L<<0) +#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_RELAX_ORDER (1L<<1) +#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PRIORITY (1L<<2) +#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_TRAFFIC_CLASS (0x7L<<4) +#define BNX2_DMA_READ_MASTER_SETTING_0_TBDC_PARAM_EN (1L<<7) +#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_NO_SNOOP (1L<<8) +#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_RELAX_ORDER (1L<<9) +#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PRIORITY (1L<<10) +#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_TRAFFIC_CLASS (0x7L<<12) +#define BNX2_DMA_READ_MASTER_SETTING_0_RBDC_PARAM_EN (1L<<15) +#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_NO_SNOOP (1L<<16) +#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_RELAX_ORDER (1L<<17) +#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PRIORITY (1L<<18) +#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_TRAFFIC_CLASS (0x7L<<20) +#define BNX2_DMA_READ_MASTER_SETTING_0_TDMA_PARAM_EN (1L<<23) +#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24) +#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25) +#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PRIORITY (1L<<26) +#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28) +#define BNX2_DMA_READ_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31) + +#define BNX2_DMA_READ_MASTER_SETTING_1 0x00000c14 +#define BNX2_DMA_READ_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0) +#define BNX2_DMA_READ_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1) +#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PRIORITY (1L<<2) +#define BNX2_DMA_READ_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4) +#define BNX2_DMA_READ_MASTER_SETTING_1_COM_PARAM_EN (1L<<7) +#define BNX2_DMA_READ_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8) +#define BNX2_DMA_READ_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9) +#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PRIORITY (1L<<10) +#define BNX2_DMA_READ_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12) +#define BNX2_DMA_READ_MASTER_SETTING_1_CP_PARAM_EN (1L<<15) + +#define BNX2_DMA_WRITE_MASTER_SETTING_0 0x00000c18 +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_NO_SNOOP (1L<<0) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_RELAX_ORDER (1L<<1) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PRIORITY (1L<<2) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_CS_VLD (1L<<3) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_TRAFFIC_CLASS (0x7L<<4) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_HC_PARAM_EN (1L<<7) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_NO_SNOOP (1L<<8) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_RELAX_ORDER (1L<<9) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PRIORITY (1L<<10) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_CS_VLD (1L<<11) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_TRAFFIC_CLASS (0x7L<<12) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_RDMA_PARAM_EN (1L<<15) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_NO_SNOOP (1L<<24) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_RELAX_ORDER (1L<<25) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PRIORITY (1L<<26) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_CS_VLD (1L<<27) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_TRAFFIC_CLASS (0x7L<<28) +#define BNX2_DMA_WRITE_MASTER_SETTING_0_CTX_PARAM_EN (1L<<31) + +#define BNX2_DMA_WRITE_MASTER_SETTING_1 0x00000c1c +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_NO_SNOOP (1L<<0) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_RELAX_ORDER (1L<<1) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PRIORITY (1L<<2) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_CS_VLD (1L<<3) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_TRAFFIC_CLASS (0x7L<<4) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_COM_PARAM_EN (1L<<7) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_NO_SNOOP (1L<<8) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_RELAX_ORDER (1L<<9) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PRIORITY (1L<<10) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_CS_VLD (1L<<11) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_TRAFFIC_CLASS (0x7L<<12) +#define BNX2_DMA_WRITE_MASTER_SETTING_1_CP_PARAM_EN (1L<<15) + +#define BNX2_DMA_ARBITER 0x00000c20 +#define BNX2_DMA_ARBITER_NUM_READS (0x7L<<0) +#define BNX2_DMA_ARBITER_WR_ARB_MODE (1L<<4) +#define BNX2_DMA_ARBITER_WR_ARB_MODE_STRICT (0L<<4) +#define BNX2_DMA_ARBITER_WR_ARB_MODE_RND_RBN (1L<<4) +#define BNX2_DMA_ARBITER_RD_ARB_MODE (0x3L<<5) +#define BNX2_DMA_ARBITER_RD_ARB_MODE_STRICT (0L<<5) +#define BNX2_DMA_ARBITER_RD_ARB_MODE_RND_RBN (1L<<5) +#define BNX2_DMA_ARBITER_RD_ARB_MODE_WGT_RND_RBN (2L<<5) +#define BNX2_DMA_ARBITER_ALT_MODE_EN (1L<<8) +#define BNX2_DMA_ARBITER_RR_MODE (1L<<9) +#define BNX2_DMA_ARBITER_TIMER_MODE (1L<<10) +#define BNX2_DMA_ARBITER_OUSTD_READ_REQ (0xfL<<12) + +#define BNX2_DMA_ARB_TIMERS 0x00000c24 +#define BNX2_DMA_ARB_TIMERS_RD_DRR_WAIT_TIME (0xffL<<0) +#define BNX2_DMA_ARB_TIMERS_TM_MIN_TIMEOUT (0xffL<<12) +#define BNX2_DMA_ARB_TIMERS_TM_MAX_TIMEOUT (0xfffL<<20) + +#define BNX2_DMA_DEBUG_VECT_PEEK 0x00000c2c +#define BNX2_DMA_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0) +#define BNX2_DMA_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11) +#define BNX2_DMA_DEBUG_VECT_PEEK_1_SEL (0xfL<<12) +#define BNX2_DMA_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16) +#define BNX2_DMA_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) +#define BNX2_DMA_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) + +#define BNX2_DMA_TAG_RAM_00 0x00000c30 +#define BNX2_DMA_TAG_RAM_00_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_00_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_00_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_00_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_00_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_00_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_00_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_00_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_00_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_01 0x00000c34 +#define BNX2_DMA_TAG_RAM_01_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_01_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_01_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_01_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_01_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_01_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_01_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_01_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_01_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_02 0x00000c38 +#define BNX2_DMA_TAG_RAM_02_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_02_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_02_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_02_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_02_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_02_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_02_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_02_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_02_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_03 0x00000c3c +#define BNX2_DMA_TAG_RAM_03_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_03_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_03_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_03_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_03_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_03_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_03_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_03_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_03_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_04 0x00000c40 +#define BNX2_DMA_TAG_RAM_04_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_04_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_04_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_04_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_04_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_04_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_04_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_04_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_04_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_05 0x00000c44 +#define BNX2_DMA_TAG_RAM_05_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_05_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_05_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_05_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_05_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_05_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_05_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_05_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_05_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_06 0x00000c48 +#define BNX2_DMA_TAG_RAM_06_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_06_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_06_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_06_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_06_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_06_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_06_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_06_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_06_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_07 0x00000c4c +#define BNX2_DMA_TAG_RAM_07_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_07_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_07_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_07_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_07_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_07_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_07_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_07_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_07_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_08 0x00000c50 +#define BNX2_DMA_TAG_RAM_08_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_08_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_08_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_08_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_08_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_08_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_08_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_08_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_08_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_09 0x00000c54 +#define BNX2_DMA_TAG_RAM_09_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_09_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_09_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_09_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_09_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_09_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_09_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_09_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_09_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_10 0x00000c58 +#define BNX2_DMA_TAG_RAM_10_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_10_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_10_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_10_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_10_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_10_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_10_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_10_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_10_VALID (1L<<10) + +#define BNX2_DMA_TAG_RAM_11 0x00000c5c +#define BNX2_DMA_TAG_RAM_11_CHANNEL (0xfL<<0) +#define BNX2_DMA_TAG_RAM_11_MASTER (0x7L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_CTX (0L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_RBDC (1L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_TBDC (2L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_COM (3L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_CP (4L<<4) +#define BNX2_DMA_TAG_RAM_11_MASTER_TDMA (5L<<4) +#define BNX2_DMA_TAG_RAM_11_SWAP (0x3L<<7) +#define BNX2_DMA_TAG_RAM_11_SWAP_CONFIG (0L<<7) +#define BNX2_DMA_TAG_RAM_11_SWAP_DATA (1L<<7) +#define BNX2_DMA_TAG_RAM_11_SWAP_CONTROL (2L<<7) +#define BNX2_DMA_TAG_RAM_11_FUNCTION (1L<<9) +#define BNX2_DMA_TAG_RAM_11_VALID (1L<<10) + #define BNX2_DMA_RCHAN_STAT_22 0x00000c60 #define BNX2_DMA_RCHAN_STAT_30 0x00000c64 #define BNX2_DMA_RCHAN_STAT_31 0x00000c68 @@ -1336,6 +2345,25 @@ struct l2_fhdr { */ #define BNX2_CTX_COMMAND 0x00001000 #define BNX2_CTX_COMMAND_ENABLED (1L<<0) +#define BNX2_CTX_COMMAND_DISABLE_USAGE_CNT (1L<<1) +#define BNX2_CTX_COMMAND_DISABLE_PLRU (1L<<2) +#define BNX2_CTX_COMMAND_DISABLE_COMBINE_READ (1L<<3) +#define BNX2_CTX_COMMAND_FLUSH_AHEAD (0x1fL<<8) +#define BNX2_CTX_COMMAND_MEM_INIT (1L<<13) +#define BNX2_CTX_COMMAND_PAGE_SIZE (0xfL<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_256 (0L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_512 (1L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_1K (2L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_2K (3L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_4K (4L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_8K (5L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_16K (6L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_32K (7L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_64K (8L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_128K (9L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_256K (10L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_512K (11L<<16) +#define BNX2_CTX_COMMAND_PAGE_SIZE_1M (12L<<16) #define BNX2_CTX_STATUS 0x00001004 #define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0) @@ -1343,6 +2371,13 @@ struct l2_fhdr { #define BNX2_CTX_STATUS_WRITE_STAT (1L<<17) #define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18) #define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19) +#define BNX2_CTX_STATUS_EXT_READ_STAT (1L<<20) +#define BNX2_CTX_STATUS_EXT_WRITE_STAT (1L<<21) +#define BNX2_CTX_STATUS_MISS_STAT (1L<<22) +#define BNX2_CTX_STATUS_HIT_STAT (1L<<23) +#define BNX2_CTX_STATUS_DEAD_LOCK (1L<<24) +#define BNX2_CTX_STATUS_USAGE_CNT_ERR (1L<<25) +#define BNX2_CTX_STATUS_INVALID_PAGE (1L<<26) #define BNX2_CTX_VIRT_ADDR 0x00001008 #define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6) @@ -1357,10 +2392,15 @@ struct l2_fhdr { #define BNX2_CTX_LOCK 0x00001018 #define BNX2_CTX_LOCK_TYPE (0x7L<<0) #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0) -#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0) #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0) #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0) #define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0) +#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0) +#define BNX2_CTX_LOCK_TYPE_VOID_XI (0L<<0) +#define BNX2_CTX_LOCK_TYPE_PROTOCOL_XI (1L<<0) +#define BNX2_CTX_LOCK_TYPE_TX_XI (2L<<0) +#define BNX2_CTX_LOCK_TYPE_TIMER_XI (4L<<0) +#define BNX2_CTX_LOCK_TYPE_COMPLETE_XI (7L<<0) #define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7) #define BNX2_CTX_LOCK_GRANTED (1L<<26) #define BNX2_CTX_LOCK_MODE (0x7L<<27) @@ -1370,21 +2410,89 @@ struct l2_fhdr { #define BNX2_CTX_LOCK_STATUS (1L<<30) #define BNX2_CTX_LOCK_REQ (1L<<31) +#define BNX2_CTX_CTX_CTRL 0x0000101c +#define BNX2_CTX_CTX_CTRL_CTX_ADDR (0x7ffffL<<2) +#define BNX2_CTX_CTX_CTRL_MOD_USAGE_CNT (0x3L<<21) +#define BNX2_CTX_CTX_CTRL_NO_RAM_ACC (1L<<23) +#define BNX2_CTX_CTX_CTRL_PREFETCH_SIZE (0x3L<<24) +#define BNX2_CTX_CTX_CTRL_ATTR (1L<<26) +#define BNX2_CTX_CTX_CTRL_WRITE_REQ (1L<<30) +#define BNX2_CTX_CTX_CTRL_READ_REQ (1L<<31) + +#define BNX2_CTX_CTX_DATA 0x00001020 #define BNX2_CTX_ACCESS_STATUS 0x00001040 #define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0) #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10) #define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12) #define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14) #define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17) +#define BNX2_CTX_ACCESS_STATUS_CAMMASTERENCODED_XI (0x1fL<<0) +#define BNX2_CTX_ACCESS_STATUS_CACHEMASTERENCODED_XI (0x1fL<<5) +#define BNX2_CTX_ACCESS_STATUS_REQUEST_XI (0x3fffffL<<10) #define BNX2_CTX_DBG_LOCK_STATUS 0x00001044 #define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0) #define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22) +#define BNX2_CTX_CACHE_CTRL_STATUS 0x00001048 +#define BNX2_CTX_CACHE_CTRL_STATUS_RFIFO_OVERFLOW (1L<<0) +#define BNX2_CTX_CACHE_CTRL_STATUS_INVALID_READ_COMP (1L<<1) +#define BNX2_CTX_CACHE_CTRL_STATUS_FLUSH_START (1L<<6) +#define BNX2_CTX_CACHE_CTRL_STATUS_FREE_ENTRY_CNT (0x3fL<<7) +#define BNX2_CTX_CACHE_CTRL_STATUS_CACHE_ENTRY_NEEDED (0x3fL<<13) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN0_ACTIVE (1L<<19) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN1_ACTIVE (1L<<20) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN2_ACTIVE (1L<<21) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN3_ACTIVE (1L<<22) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN4_ACTIVE (1L<<23) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN5_ACTIVE (1L<<24) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN6_ACTIVE (1L<<25) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN7_ACTIVE (1L<<26) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN8_ACTIVE (1L<<27) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN9_ACTIVE (1L<<28) +#define BNX2_CTX_CACHE_CTRL_STATUS_RD_CHAN10_ACTIVE (1L<<29) + +#define BNX2_CTX_CACHE_CTRL_SM_STATUS 0x0000104c +#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_DWC (0x7L<<0) +#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_WFIFOC (0x7L<<3) +#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RTAGC (0x7L<<6) +#define BNX2_CTX_CACHE_CTRL_SM_STATUS_CS_RFIFOC (0x7L<<9) +#define BNX2_CTX_CACHE_CTRL_SM_STATUS_INVALID_BLK_ADDR (0x7fffL<<16) + +#define BNX2_CTX_CACHE_STATUS 0x00001050 +#define BNX2_CTX_CACHE_STATUS_HELD_ENTRIES (0x3ffL<<0) +#define BNX2_CTX_CACHE_STATUS_MAX_HELD_ENTRIES (0x3ffL<<16) + +#define BNX2_CTX_DMA_STATUS 0x00001054 +#define BNX2_CTX_DMA_STATUS_RD_CHAN0_STATUS (0x3L<<0) +#define BNX2_CTX_DMA_STATUS_RD_CHAN1_STATUS (0x3L<<2) +#define BNX2_CTX_DMA_STATUS_RD_CHAN2_STATUS (0x3L<<4) +#define BNX2_CTX_DMA_STATUS_RD_CHAN3_STATUS (0x3L<<6) +#define BNX2_CTX_DMA_STATUS_RD_CHAN4_STATUS (0x3L<<8) +#define BNX2_CTX_DMA_STATUS_RD_CHAN5_STATUS (0x3L<<10) +#define BNX2_CTX_DMA_STATUS_RD_CHAN6_STATUS (0x3L<<12) +#define BNX2_CTX_DMA_STATUS_RD_CHAN7_STATUS (0x3L<<14) +#define BNX2_CTX_DMA_STATUS_RD_CHAN8_STATUS (0x3L<<16) +#define BNX2_CTX_DMA_STATUS_RD_CHAN9_STATUS (0x3L<<18) +#define BNX2_CTX_DMA_STATUS_RD_CHAN10_STATUS (0x3L<<20) + +#define BNX2_CTX_REP_STATUS 0x00001058 +#define BNX2_CTX_REP_STATUS_ERROR_ENTRY (0x3ffL<<0) +#define BNX2_CTX_REP_STATUS_ERROR_CLIENT_ID (0x1fL<<10) +#define BNX2_CTX_REP_STATUS_USAGE_CNT_MAX_ERR (1L<<16) +#define BNX2_CTX_REP_STATUS_USAGE_CNT_MIN_ERR (1L<<17) +#define BNX2_CTX_REP_STATUS_USAGE_CNT_MISS_ERR (1L<<18) + +#define BNX2_CTX_CKSUM_ERROR_STATUS 0x0000105c +#define BNX2_CTX_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) +#define BNX2_CTX_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + #define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080 #define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0) #define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14) #define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16) +#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE_XI (1L<<14) +#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE_XI (0x7L<<15) #define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084 #define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088 @@ -1394,6 +2502,26 @@ struct l2_fhdr { #define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098 #define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c #define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0 +#define BNX2_CTX_CHNL_LOCK_STATUS_9 0x000010a4 + +#define BNX2_CTX_CACHE_DATA 0x000010c4 +#define BNX2_CTX_HOST_PAGE_TBL_CTRL 0x000010c8 +#define BNX2_CTX_HOST_PAGE_TBL_CTRL_PAGE_TBL_ADDR (0x1ffL<<0) +#define BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ (1L<<30) +#define BNX2_CTX_HOST_PAGE_TBL_CTRL_READ_REQ (1L<<31) + +#define BNX2_CTX_HOST_PAGE_TBL_DATA0 0x000010cc +#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID (1L<<0) +#define BNX2_CTX_HOST_PAGE_TBL_DATA0_VALUE (0xffffffL<<8) + +#define BNX2_CTX_HOST_PAGE_TBL_DATA1 0x000010d0 +#define BNX2_CTX_CAM_CTRL 0x000010d4 +#define BNX2_CTX_CAM_CTRL_CAM_ADDR (0x3ffL<<0) +#define BNX2_CTX_CAM_CTRL_RESET (1L<<27) +#define BNX2_CTX_CAM_CTRL_INVALIDATE (1L<<28) +#define BNX2_CTX_CAM_CTRL_SEARCH (1L<<29) +#define BNX2_CTX_CAM_CTRL_WRITE_REQ (1L<<30) +#define BNX2_CTX_CAM_CTRL_READ_REQ (1L<<31) /* @@ -1407,14 +2535,16 @@ struct l2_fhdr { #define BNX2_EMAC_MODE_PORT_NONE (0L<<2) #define BNX2_EMAC_MODE_PORT_MII (1L<<2) #define BNX2_EMAC_MODE_PORT_GMII (2L<<2) -#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2) +#define BNX2_EMAC_MODE_PORT_MII_10M (3L<<2) #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) -#define BNX2_EMAC_MODE_25G (1L<<5) +#define BNX2_EMAC_MODE_25G_MODE (1L<<5) #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) #define BNX2_EMAC_MODE_TX_BURST (1L<<8) #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) #define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10) #define BNX2_EMAC_MODE_FORCE_LINK (1L<<11) +#define BNX2_EMAC_MODE_SERDES_MODE (1L<<12) +#define BNX2_EMAC_MODE_BOND_OVRD (1L<<13) #define BNX2_EMAC_MODE_MPKT (1L<<18) #define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19) #define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20) @@ -1422,6 +2552,11 @@ struct l2_fhdr { #define BNX2_EMAC_STATUS 0x00001404 #define BNX2_EMAC_STATUS_LINK (1L<<11) #define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12) +#define BNX2_EMAC_STATUS_SERDES_AUTONEG_COMPLETE (1L<<13) +#define BNX2_EMAC_STATUS_SERDES_AUTONEG_CHANGE (1L<<14) +#define BNX2_EMAC_STATUS_SERDES_NXT_PG_CHANGE (1L<<16) +#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0 (1L<<17) +#define BNX2_EMAC_STATUS_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18) #define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22) #define BNX2_EMAC_STATUS_MI_INT (1L<<23) #define BNX2_EMAC_STATUS_AP_ERROR (1L<<24) @@ -1429,6 +2564,9 @@ struct l2_fhdr { #define BNX2_EMAC_ATTENTION_ENA 0x00001408 #define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11) +#define BNX2_EMAC_ATTENTION_ENA_AUTONEG_CHANGE (1L<<14) +#define BNX2_EMAC_ATTENTION_ENA_NXT_PG_CHANGE (1L<<16) +#define BNX2_EMAC_ATTENTION_ENA_SERDES_RX_CONFIG_IS_0_CHANGE (1L<<18) #define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22) #define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23) #define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24) @@ -1445,6 +2583,13 @@ struct l2_fhdr { #define BNX2_EMAC_LED_100MB (1L<<8) #define BNX2_EMAC_LED_10MB (1L<<9) #define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10) +#define BNX2_EMAC_LED_2500MB (1L<<11) +#define BNX2_EMAC_LED_2500MB_OVERRIDE (1L<<12) +#define BNX2_EMAC_LED_ACTIVITY_SEL (0x3L<<17) +#define BNX2_EMAC_LED_ACTIVITY_SEL_0 (0L<<17) +#define BNX2_EMAC_LED_ACTIVITY_SEL_1 (1L<<17) +#define BNX2_EMAC_LED_ACTIVITY_SEL_2 (2L<<17) +#define BNX2_EMAC_LED_ACTIVITY_SEL_3 (3L<<17) #define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19) #define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31) @@ -1515,9 +2660,15 @@ struct l2_fhdr { #define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21) #define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26) #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_ADDRESS (0L<<26) #define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26) #define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_22_XI (1L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE_45_XI (1L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_22_XI (2L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_INC_45_XI (2L<<26) #define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26) +#define BNX2_EMAC_MDIO_COMM_COMMAND_READ_45 (3L<<26) #define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28) #define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29) #define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30) @@ -1534,13 +2685,17 @@ struct l2_fhdr { #define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10) #define BNX2_EMAC_MDIO_MODE_MDC (1L<<11) #define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12) +#define BNX2_EMAC_MDIO_MODE_EXT_MDINT (1L<<13) #define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16) +#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT_XI (0x3fL<<16) +#define BNX2_EMAC_MDIO_MODE_CLAUSE_45_XI (1L<<31) #define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8 #define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0) #define BNX2_EMAC_TX_MODE 0x000014bc #define BNX2_EMAC_TX_MODE_RESET (1L<<0) +#define BNX2_EMAC_TX_MODE_CS16_TEST (1L<<2) #define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3) #define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4) #define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5) @@ -1553,6 +2708,7 @@ struct l2_fhdr { #define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2) #define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3) #define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4) +#define BNX2_EMAC_TX_STATUS_CS16_ERROR (1L<<5) #define BNX2_EMAC_TX_LENGTHS 0x000014c4 #define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0) @@ -1586,6 +2742,10 @@ struct l2_fhdr { #define BNX2_EMAC_MULTICAST_HASH5 0x000014e4 #define BNX2_EMAC_MULTICAST_HASH6 0x000014e8 #define BNX2_EMAC_MULTICAST_HASH7 0x000014ec +#define BNX2_EMAC_CKSUM_ERROR_STATUS 0x000014f0 +#define BNX2_EMAC_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) +#define BNX2_EMAC_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + #define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500 #define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504 #define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508 @@ -1608,7 +2768,7 @@ struct l2_fhdr { #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550 #define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554 -#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558 +#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001558 #define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c #define BNX2_EMAC_RXMAC_DEBUG1 0x00001560 #define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0) @@ -1661,9 +2821,9 @@ struct l2_fhdr { #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16) -#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16) +#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16) #define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16) @@ -1701,7 +2861,7 @@ struct l2_fhdr { #define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23) #define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24) #define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25) -#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26) +#define BNX2_EMAC_RXMAC_DEBUG4_SFD_FOUND (1L<<26) #define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27) #define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28) @@ -1733,6 +2893,7 @@ struct l2_fhdr { #define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19) #define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20) +#define BNX2_EMAC_RX_STAT_FALSECARRIERERRORS 0x00001574 #define BNX2_EMAC_RX_STAT_AC0 0x00001580 #define BNX2_EMAC_RX_STAT_AC1 0x00001584 #define BNX2_EMAC_RX_STAT_AC2 0x00001588 @@ -1757,6 +2918,7 @@ struct l2_fhdr { #define BNX2_EMAC_RX_STAT_AC21 0x000015d4 #define BNX2_EMAC_RX_STAT_AC22 0x000015d8 #define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc +#define BNX2_EMAC_RX_STAT_AC_28 0x000015f4 #define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600 #define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604 #define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608 @@ -1777,7 +2939,7 @@ struct l2_fhdr { #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644 #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648 #define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c -#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650 +#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTSOVER1522OCTETS 0x00001650 #define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654 #define BNX2_EMAC_TXMAC_DEBUG0 0x00001658 #define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c @@ -1843,16 +3005,16 @@ struct l2_fhdr { #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16) -#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16) -#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16) -#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16) -#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16) -#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16) #define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16) +#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16) #define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20) #define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21) #define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22) @@ -1887,8 +3049,11 @@ struct l2_fhdr { #define BNX2_EMAC_TX_STAT_AC18 0x000016c8 #define BNX2_EMAC_TX_STAT_AC19 0x000016cc #define BNX2_EMAC_TX_STAT_AC20 0x000016d0 -#define BNX2_EMAC_TX_STAT_AC21 0x000016d4 #define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8 +#define BNX2_EMAC_TX_RATE_LIMIT_CTRL 0x000016fc +#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_INC (0x7fL<<0) +#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_TX_THROTTLE_NUM (0x7fL<<16) +#define BNX2_EMAC_TX_RATE_LIMIT_CTRL_RATE_LIMITER_EN (1L<<31) /* -- cgit v1.2.3 From 9052a840fffa2f565ed13e6ecd53fbe2532d51b9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:10:12 -0800 Subject: [BNX2]: Add new 5709 registers (part 2). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.h | 1432 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1410 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 73c785585fc3..13b6f9b11e01 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -3074,8 +3074,15 @@ struct l2_fhdr { #define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2) #define BNX2_RPM_CONFIG_MP_KEEP (1L<<3) #define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4) +#define BNX2_RPM_CONFIG_DISABLE_WOL_ASSERT (1L<<30) #define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31) +#define BNX2_RPM_MGMT_PKT_CTRL 0x0000180c +#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_SORT (0xfL<<0) +#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_RULE (0xfL<<4) +#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_DISCARD_EN (1L<<30) +#define BNX2_RPM_MGMT_PKT_CTRL_MGMT_EN (1L<<31) + #define BNX2_RPM_VLAN_MATCH0 0x00001810 #define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0) @@ -3096,6 +3103,7 @@ struct l2_fhdr { #define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19) #define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20) #define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24) +#define BNX2_RPM_SORT_USER0_VLAN_NOTMATCH (1L<<25) #define BNX2_RPM_SORT_USER0_ENA (1L<<31) #define BNX2_RPM_SORT_USER1 0x00001824 @@ -3133,11 +3141,187 @@ struct l2_fhdr { #define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848 #define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c #define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0 0x00001854 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION0_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1 0x00001858 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION1_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2 0x0000185c +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION2_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3 0x00001860 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION3_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4 0x00001864 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION4_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5 0x00001868 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION5_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6 0x0000186c +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION6_NEXT_HEADER_EN (1L<<31) + +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7 0x00001870 +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN (0xffL<<0) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER (0xffL<<16) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_LEN_TYPE (1L<<30) +#define BNX2_RPM_IPV6_PROGRAMMABLE_EXTENSION7_NEXT_HEADER_EN (1L<<31) + #define BNX2_RPM_STAT_AC0 0x00001880 #define BNX2_RPM_STAT_AC1 0x00001884 #define BNX2_RPM_STAT_AC2 0x00001888 #define BNX2_RPM_STAT_AC3 0x0000188c #define BNX2_RPM_STAT_AC4 0x00001890 +#define BNX2_RPM_RC_CNTL_16 0x000018e0 +#define BNX2_RPM_RC_CNTL_16_OFFSET (0xffL<<0) +#define BNX2_RPM_RC_CNTL_16_CLASS (0x7L<<8) +#define BNX2_RPM_RC_CNTL_16_PRIORITY (1L<<11) +#define BNX2_RPM_RC_CNTL_16_P4 (1L<<12) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE (0x7L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_START (0L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_IP (1L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP (2L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_UDP (3L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_TCP_UDP (5L<<13) +#define BNX2_RPM_RC_CNTL_16_HDR_TYPE_ICMPV6 (6L<<13) +#define BNX2_RPM_RC_CNTL_16_COMP (0x3L<<16) +#define BNX2_RPM_RC_CNTL_16_COMP_EQUAL (0L<<16) +#define BNX2_RPM_RC_CNTL_16_COMP_NEQUAL (1L<<16) +#define BNX2_RPM_RC_CNTL_16_COMP_GREATER (2L<<16) +#define BNX2_RPM_RC_CNTL_16_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_16_MAP (1L<<18) +#define BNX2_RPM_RC_CNTL_16_SBIT (1L<<19) +#define BNX2_RPM_RC_CNTL_16_CMDSEL (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_16_DISCARD (1L<<25) +#define BNX2_RPM_RC_CNTL_16_MASK (1L<<26) +#define BNX2_RPM_RC_CNTL_16_P1 (1L<<27) +#define BNX2_RPM_RC_CNTL_16_P2 (1L<<28) +#define BNX2_RPM_RC_CNTL_16_P3 (1L<<29) +#define BNX2_RPM_RC_CNTL_16_NBIT (1L<<30) + +#define BNX2_RPM_RC_VALUE_MASK_16 0x000018e4 +#define BNX2_RPM_RC_VALUE_MASK_16_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_16_MASK (0xffffL<<16) + +#define BNX2_RPM_RC_CNTL_17 0x000018e8 +#define BNX2_RPM_RC_CNTL_17_OFFSET (0xffL<<0) +#define BNX2_RPM_RC_CNTL_17_CLASS (0x7L<<8) +#define BNX2_RPM_RC_CNTL_17_PRIORITY (1L<<11) +#define BNX2_RPM_RC_CNTL_17_P4 (1L<<12) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE (0x7L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_START (0L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_IP (1L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP (2L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_UDP (3L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_TCP_UDP (5L<<13) +#define BNX2_RPM_RC_CNTL_17_HDR_TYPE_ICMPV6 (6L<<13) +#define BNX2_RPM_RC_CNTL_17_COMP (0x3L<<16) +#define BNX2_RPM_RC_CNTL_17_COMP_EQUAL (0L<<16) +#define BNX2_RPM_RC_CNTL_17_COMP_NEQUAL (1L<<16) +#define BNX2_RPM_RC_CNTL_17_COMP_GREATER (2L<<16) +#define BNX2_RPM_RC_CNTL_17_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_17_MAP (1L<<18) +#define BNX2_RPM_RC_CNTL_17_SBIT (1L<<19) +#define BNX2_RPM_RC_CNTL_17_CMDSEL (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_17_DISCARD (1L<<25) +#define BNX2_RPM_RC_CNTL_17_MASK (1L<<26) +#define BNX2_RPM_RC_CNTL_17_P1 (1L<<27) +#define BNX2_RPM_RC_CNTL_17_P2 (1L<<28) +#define BNX2_RPM_RC_CNTL_17_P3 (1L<<29) +#define BNX2_RPM_RC_CNTL_17_NBIT (1L<<30) + +#define BNX2_RPM_RC_VALUE_MASK_17 0x000018ec +#define BNX2_RPM_RC_VALUE_MASK_17_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_17_MASK (0xffffL<<16) + +#define BNX2_RPM_RC_CNTL_18 0x000018f0 +#define BNX2_RPM_RC_CNTL_18_OFFSET (0xffL<<0) +#define BNX2_RPM_RC_CNTL_18_CLASS (0x7L<<8) +#define BNX2_RPM_RC_CNTL_18_PRIORITY (1L<<11) +#define BNX2_RPM_RC_CNTL_18_P4 (1L<<12) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE (0x7L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_START (0L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_IP (1L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP (2L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_UDP (3L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_TCP_UDP (5L<<13) +#define BNX2_RPM_RC_CNTL_18_HDR_TYPE_ICMPV6 (6L<<13) +#define BNX2_RPM_RC_CNTL_18_COMP (0x3L<<16) +#define BNX2_RPM_RC_CNTL_18_COMP_EQUAL (0L<<16) +#define BNX2_RPM_RC_CNTL_18_COMP_NEQUAL (1L<<16) +#define BNX2_RPM_RC_CNTL_18_COMP_GREATER (2L<<16) +#define BNX2_RPM_RC_CNTL_18_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_18_MAP (1L<<18) +#define BNX2_RPM_RC_CNTL_18_SBIT (1L<<19) +#define BNX2_RPM_RC_CNTL_18_CMDSEL (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_18_DISCARD (1L<<25) +#define BNX2_RPM_RC_CNTL_18_MASK (1L<<26) +#define BNX2_RPM_RC_CNTL_18_P1 (1L<<27) +#define BNX2_RPM_RC_CNTL_18_P2 (1L<<28) +#define BNX2_RPM_RC_CNTL_18_P3 (1L<<29) +#define BNX2_RPM_RC_CNTL_18_NBIT (1L<<30) + +#define BNX2_RPM_RC_VALUE_MASK_18 0x000018f4 +#define BNX2_RPM_RC_VALUE_MASK_18_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_18_MASK (0xffffL<<16) + +#define BNX2_RPM_RC_CNTL_19 0x000018f8 +#define BNX2_RPM_RC_CNTL_19_OFFSET (0xffL<<0) +#define BNX2_RPM_RC_CNTL_19_CLASS (0x7L<<8) +#define BNX2_RPM_RC_CNTL_19_PRIORITY (1L<<11) +#define BNX2_RPM_RC_CNTL_19_P4 (1L<<12) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE (0x7L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_START (0L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_IP (1L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP (2L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_UDP (3L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_TCP_UDP (5L<<13) +#define BNX2_RPM_RC_CNTL_19_HDR_TYPE_ICMPV6 (6L<<13) +#define BNX2_RPM_RC_CNTL_19_COMP (0x3L<<16) +#define BNX2_RPM_RC_CNTL_19_COMP_EQUAL (0L<<16) +#define BNX2_RPM_RC_CNTL_19_COMP_NEQUAL (1L<<16) +#define BNX2_RPM_RC_CNTL_19_COMP_GREATER (2L<<16) +#define BNX2_RPM_RC_CNTL_19_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_19_MAP (1L<<18) +#define BNX2_RPM_RC_CNTL_19_SBIT (1L<<19) +#define BNX2_RPM_RC_CNTL_19_CMDSEL (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_19_DISCARD (1L<<25) +#define BNX2_RPM_RC_CNTL_19_MASK (1L<<26) +#define BNX2_RPM_RC_CNTL_19_P1 (1L<<27) +#define BNX2_RPM_RC_CNTL_19_P2 (1L<<28) +#define BNX2_RPM_RC_CNTL_19_P3 (1L<<29) +#define BNX2_RPM_RC_CNTL_19_NBIT (1L<<30) + +#define BNX2_RPM_RC_VALUE_MASK_19 0x000018fc +#define BNX2_RPM_RC_VALUE_MASK_19_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_19_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_0 0x00001900 #define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0) #define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8) @@ -3149,14 +3333,18 @@ struct l2_fhdr { #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13) #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13) #define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP_UDP (5L<<13) +#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_ICMPV6 (6L<<13) #define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16) #define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16) #define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16) #define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16) #define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16) +#define BNX2_RPM_RC_CNTL_0_MAP_XI (1L<<18) #define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19) #define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20) #define BNX2_RPM_RC_CNTL_0_MAP (1L<<24) +#define BNX2_RPM_RC_CNTL_0_CMDSEL_XI (0x1fL<<20) #define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25) #define BNX2_RPM_RC_CNTL_0_MASK (1L<<26) #define BNX2_RPM_RC_CNTL_0_P1 (1L<<27) @@ -3171,81 +3359,518 @@ struct l2_fhdr { #define BNX2_RPM_RC_CNTL_1 0x00001908 #define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_1_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_1_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_1_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_1_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_1_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_1_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_1_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_1_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_1_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_1_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_1_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_1_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_1_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_1_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_1_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_1_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_1_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_1_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_1_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c +#define BNX2_RPM_RC_VALUE_MASK_1_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_1_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_2 0x00001910 #define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_2_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_2_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_2_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_2_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_2_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_2_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_2_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_2_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_2_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_2_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_2_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_2_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_2_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_2_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_2_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_2_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_2_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_2_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_2_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_2 0x00001914 +#define BNX2_RPM_RC_VALUE_MASK_2_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_2_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_3 0x00001918 #define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_3_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_3_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_3_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_3_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_3_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_3_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_3_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_3_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_3_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_3_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_3_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_3_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_3_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_3_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_3_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_3_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_3_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_3_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_3_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c +#define BNX2_RPM_RC_VALUE_MASK_3_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_3_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_4 0x00001920 #define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_4_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_4_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_4_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_4_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_4_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_4_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_4_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_4_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_4_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_4_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_4_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_4_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_4_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_4_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_4_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_4_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_4_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_4_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_4_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_4 0x00001924 +#define BNX2_RPM_RC_VALUE_MASK_4_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_4_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_5 0x00001928 #define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_5_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_5_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_5_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_5_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_5_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_5_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_5_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_5_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_5_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_5_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_5_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_5_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_5_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_5_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_5_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_5_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_5_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_5_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_5_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c +#define BNX2_RPM_RC_VALUE_MASK_5_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_5_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_6 0x00001930 #define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_6_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_6_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_6_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_6_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_6_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_6_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_6_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_6_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_6_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_6_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_6_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_6_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_6_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_6_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_6_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_6_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_6_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_6_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_6_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_6 0x00001934 +#define BNX2_RPM_RC_VALUE_MASK_6_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_6_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_7 0x00001938 #define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_7_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_7_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_7_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_7_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_7_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_7_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_7_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_7_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_7_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_7_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_7_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_7_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_7_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_7_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_7_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_7_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_7_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_7_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_7_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c +#define BNX2_RPM_RC_VALUE_MASK_7_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_7_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_8 0x00001940 #define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_8_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_8_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_8_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_8_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_8_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_8_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_8_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_8_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_8_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_8_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_8_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_8_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_8_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_8_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_8_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_8_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_8_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_8_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_8_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_8 0x00001944 +#define BNX2_RPM_RC_VALUE_MASK_8_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_8_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_9 0x00001948 #define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_9_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_9_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_9_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_9_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_9_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_9_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_9_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_9_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_9_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_9_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_9_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_9_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_9_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_9_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_9_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_9_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_9_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_9_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_9_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c +#define BNX2_RPM_RC_VALUE_MASK_9_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_9_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_10 0x00001950 #define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_10_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_10_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_10_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_10_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_10_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_10_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_10_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_10_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_10_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_10_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_10_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_10_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_10_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_10_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_10_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_10_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_10_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_10_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_10_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_10 0x00001954 +#define BNX2_RPM_RC_VALUE_MASK_10_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_10_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_11 0x00001958 #define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_11_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_11_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_11_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_11_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_11_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_11_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_11_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_11_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_11_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_11_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_11_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_11_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_11_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_11_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_11_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_11_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_11_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_11_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_11_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c +#define BNX2_RPM_RC_VALUE_MASK_11_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_11_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_12 0x00001960 #define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_12_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_12_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_12_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_12_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_12_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_12_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_12_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_12_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_12_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_12_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_12_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_12_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_12_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_12_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_12_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_12_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_12_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_12_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_12_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_12 0x00001964 +#define BNX2_RPM_RC_VALUE_MASK_12_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_12_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_13 0x00001968 #define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_13_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_13_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_13_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_13_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_13_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_13_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_13_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_13_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_13_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_13_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_13_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_13_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_13_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_13_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_13_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_13_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_13_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_13_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_13_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c +#define BNX2_RPM_RC_VALUE_MASK_13_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_13_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_14 0x00001970 #define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_14_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_14_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_14_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_14_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_14_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_14_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_14_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_14_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_14_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_14_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_14_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_14_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_14_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_14_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_14_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_14_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_14_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_14_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_14_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_14 0x00001974 +#define BNX2_RPM_RC_VALUE_MASK_14_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_14_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CNTL_15 0x00001978 #define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0) #define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19) +#define BNX2_RPM_RC_CNTL_15_OFFSET_XI (0xffL<<0) +#define BNX2_RPM_RC_CNTL_15_CLASS_XI (0x7L<<8) +#define BNX2_RPM_RC_CNTL_15_PRIORITY_XI (1L<<11) +#define BNX2_RPM_RC_CNTL_15_P4_XI (1L<<12) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_XI (0x7L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_START_XI (0L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_IP_XI (1L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_XI (2L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_UDP_XI (3L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_DATA_XI (4L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_TCP_UDP_XI (5L<<13) +#define BNX2_RPM_RC_CNTL_15_HDR_TYPE_ICMPV6_XI (6L<<13) +#define BNX2_RPM_RC_CNTL_15_COMP_XI (0x3L<<16) +#define BNX2_RPM_RC_CNTL_15_COMP_EQUAL_XI (0L<<16) +#define BNX2_RPM_RC_CNTL_15_COMP_NEQUAL_XI (1L<<16) +#define BNX2_RPM_RC_CNTL_15_COMP_GREATER_XI (2L<<16) +#define BNX2_RPM_RC_CNTL_15_COMP_LESS_XI (3L<<16) +#define BNX2_RPM_RC_CNTL_15_MAP_XI (1L<<18) +#define BNX2_RPM_RC_CNTL_15_SBIT_XI (1L<<19) +#define BNX2_RPM_RC_CNTL_15_CMDSEL_XI (0x1fL<<20) +#define BNX2_RPM_RC_CNTL_15_DISCARD_XI (1L<<25) +#define BNX2_RPM_RC_CNTL_15_MASK_XI (1L<<26) +#define BNX2_RPM_RC_CNTL_15_P1_XI (1L<<27) +#define BNX2_RPM_RC_CNTL_15_P2_XI (1L<<28) +#define BNX2_RPM_RC_CNTL_15_P3_XI (1L<<29) +#define BNX2_RPM_RC_CNTL_15_NBIT_XI (1L<<30) #define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c +#define BNX2_RPM_RC_VALUE_MASK_15_VALUE (0xffffL<<0) +#define BNX2_RPM_RC_VALUE_MASK_15_MASK (0xffffL<<16) + #define BNX2_RPM_RC_CONFIG 0x00001980 #define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0) +#define BNX2_RPM_RC_CONFIG_RULE_ENABLE_XI (0xfffffL<<0) #define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24) +#define BNX2_RPM_RC_CONFIG_KNUM_OVERWRITE (1L<<31) #define BNX2_RPM_DEBUG0 0x00001984 #define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0) @@ -3401,6 +4026,16 @@ struct l2_fhdr { #define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29) #define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30) #define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31) +#define BNX2_RPM_DEBUG9_BEMEM_R_XI (0x1fL<<0) +#define BNX2_RPM_DEBUG9_EO_XI (1L<<5) +#define BNX2_RPM_DEBUG9_AEOF_DE_XI (1L<<6) +#define BNX2_RPM_DEBUG9_SO_XI (1L<<7) +#define BNX2_RPM_DEBUG9_WD64_CT_XI (0x1fL<<8) +#define BNX2_RPM_DEBUG9_EOF_VLDBYTE_XI (0x7L<<13) +#define BNX2_RPM_DEBUG9_ACPI_RDE_PAT_ID_XI (0xfL<<16) +#define BNX2_RPM_DEBUG9_CALCRC_RESULT_XI (0x3ffL<<20) +#define BNX2_RPM_DEBUG9_DATA_IN_VL_XI (1L<<30) +#define BNX2_RPM_DEBUG9_CALCRC_BUFFER_VLD_XI (1L<<31) #define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0 #define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4 @@ -3418,6 +4053,56 @@ struct l2_fhdr { #define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4 #define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8 #define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL 0x00001a00 +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_BYTE_ADDRESS (0xffffL<<0) +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_DEBUGRD (1L<<28) +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_MODE (1L<<29) +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_INIT (1L<<30) +#define BNX2_RPM_ACPI_BYTE_ENABLE_CTRL_WR (1L<<31) + +#define BNX2_RPM_ACPI_PATTERN_CTRL 0x00001a04 +#define BNX2_RPM_ACPI_PATTERN_CTRL_PATTERN_ID (0xfL<<0) +#define BNX2_RPM_ACPI_PATTERN_CTRL_CRC_SM_CLR (1L<<30) +#define BNX2_RPM_ACPI_PATTERN_CTRL_WR (1L<<31) + +#define BNX2_RPM_ACPI_DATA 0x00001a08 +#define BNX2_RPM_ACPI_DATA_PATTERN_BE (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_LEN0 0x00001a0c +#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN3 (0xffL<<0) +#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN2 (0xffL<<8) +#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN1 (0xffL<<16) +#define BNX2_RPM_ACPI_PATTERN_LEN0_PATTERN_LEN0 (0xffL<<24) + +#define BNX2_RPM_ACPI_PATTERN_LEN1 0x00001a10 +#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN7 (0xffL<<0) +#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN6 (0xffL<<8) +#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN5 (0xffL<<16) +#define BNX2_RPM_ACPI_PATTERN_LEN1_PATTERN_LEN4 (0xffL<<24) + +#define BNX2_RPM_ACPI_PATTERN_CRC0 0x00001a18 +#define BNX2_RPM_ACPI_PATTERN_CRC0_PATTERN_CRC0 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC1 0x00001a1c +#define BNX2_RPM_ACPI_PATTERN_CRC1_PATTERN_CRC1 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC2 0x00001a20 +#define BNX2_RPM_ACPI_PATTERN_CRC2_PATTERN_CRC2 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC3 0x00001a24 +#define BNX2_RPM_ACPI_PATTERN_CRC3_PATTERN_CRC3 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC4 0x00001a28 +#define BNX2_RPM_ACPI_PATTERN_CRC4_PATTERN_CRC4 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC5 0x00001a2c +#define BNX2_RPM_ACPI_PATTERN_CRC5_PATTERN_CRC5 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC6 0x00001a30 +#define BNX2_RPM_ACPI_PATTERN_CRC6_PATTERN_CRC6 (0xffffffffL<<0) + +#define BNX2_RPM_ACPI_PATTERN_CRC7 0x00001a34 +#define BNX2_RPM_ACPI_PATTERN_CRC7_PATTERN_CRC7 (0xffffffffL<<0) /* @@ -3428,15 +4113,20 @@ struct l2_fhdr { #define BNX2_RBUF_COMMAND_ENABLED (1L<<0) #define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1) #define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2) +#define BNX2_RBUF_COMMAND_PKT_OFFSET_OVFL (1L<<3) #define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4) #define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5) +#define BNX2_RBUF_COMMAND_EN_PRI_CHNGE_TE (1L<<6) +#define BNX2_RBUF_COMMAND_CU_ISOLATE_XI (1L<<5) +#define BNX2_RBUF_COMMAND_EN_PRI_CHANGE_XI (1L<<6) +#define BNX2_RBUF_COMMAND_GRC_ENDIAN_CONV_DIS_XI (1L<<7) #define BNX2_RBUF_STATUS1 0x00200004 #define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0) #define BNX2_RBUF_STATUS2 0x00200008 -#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0) -#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16) +#define BNX2_RBUF_STATUS2_FREE_TAIL (0x1ffL<<0) +#define BNX2_RBUF_STATUS2_FREE_HEAD (0x1ffL<<16) #define BNX2_RBUF_CONFIG 0x0020000c #define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0) @@ -3444,16 +4134,21 @@ struct l2_fhdr { #define BNX2_RBUF_FW_BUF_ALLOC 0x00200010 #define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7) +#define BNX2_RBUF_FW_BUF_ALLOC_TYPE (1L<<16) +#define BNX2_RBUF_FW_BUF_ALLOC_ALLOC_REQ (1L<<31) #define BNX2_RBUF_FW_BUF_FREE 0x00200014 #define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0) #define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7) #define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16) +#define BNX2_RBUF_FW_BUF_FREE_TYPE (1L<<25) +#define BNX2_RBUF_FW_BUF_FREE_FREE_REQ (1L<<31) #define BNX2_RBUF_FW_BUF_SEL 0x00200018 #define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0) #define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7) #define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16) +#define BNX2_RBUF_FW_BUF_SEL_SEL_REQ (1L<<31) #define BNX2_RBUF_CONFIG2 0x0020001c #define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0) @@ -3541,6 +4236,8 @@ struct l2_fhdr { #define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0) #define BNX2_RV2P_INSTR_LOW 0x00002834 +#define BNX2_RV2P_INSTR_LOW_LOW (0xffffffffL<<0) + #define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838 #define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0) #define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31) @@ -3560,7 +4257,29 @@ struct l2_fhdr { #define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) #define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) -#define BNX2_RV2P_PFTQ_DATA 0x00002b40 +#define BNX2_RV2P_MPFE_PFE_CTL 0x00002afc +#define BNX2_RV2P_MPFE_PFE_CTL_INC_USAGE_CNT (1L<<0) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE (0xfL<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_0 (0L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_1 (1L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_2 (2L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_3 (3L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_4 (4L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_5 (5L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_6 (6L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_7 (7L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_8 (8L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_9 (9L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_10 (10L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_11 (11L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_12 (12L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_13 (13L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_14 (14L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_SIZE_15 (15L<<4) +#define BNX2_RV2P_MPFE_PFE_CTL_PFE_COUNT (0xfL<<12) +#define BNX2_RV2P_MPFE_PFE_CTL_OFFSET (0x1ffL<<16) + +#define BNX2_RV2P_RV2PPQ 0x00002b40 #define BNX2_RV2P_PFTQ_CMD 0x00002b78 #define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10) @@ -3581,7 +4300,7 @@ struct l2_fhdr { #define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22) -#define BNX2_RV2P_TFTQ_DATA 0x00002b80 +#define BNX2_RV2P_RV2PTQ 0x00002b80 #define BNX2_RV2P_TFTQ_CMD 0x00002bb8 #define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10) @@ -3602,7 +4321,7 @@ struct l2_fhdr { #define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22) -#define BNX2_RV2P_MFTQ_DATA 0x00002bc0 +#define BNX2_RV2P_RV2PMQ 0x00002bc0 #define BNX2_RV2P_MFTQ_CMD 0x00002bf8 #define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10) @@ -3631,18 +4350,26 @@ struct l2_fhdr { */ #define BNX2_MQ_COMMAND 0x00003c00 #define BNX2_MQ_COMMAND_ENABLED (1L<<0) +#define BNX2_MQ_COMMAND_INIT (1L<<1) #define BNX2_MQ_COMMAND_OVERFLOW (1L<<4) #define BNX2_MQ_COMMAND_WR_ERROR (1L<<5) #define BNX2_MQ_COMMAND_RD_ERROR (1L<<6) +#define BNX2_MQ_COMMAND_IDB_CFG_ERROR (1L<<7) +#define BNX2_MQ_COMMAND_IDB_OVERFLOW (1L<<10) +#define BNX2_MQ_COMMAND_NO_BIN_ERROR (1L<<11) +#define BNX2_MQ_COMMAND_NO_MAP_ERROR (1L<<12) #define BNX2_MQ_STATUS 0x00003c04 #define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16) #define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17) #define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18) +#define BNX2_MQ_STATUS_IDB_OFLOW_STAT (1L<<19) #define BNX2_MQ_CONFIG 0x00003c08 #define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0) #define BNX2_MQ_CONFIG_HALT_DIS (1L<<1) +#define BNX2_MQ_CONFIG_BIN_MQ_MODE (1L<<2) +#define BNX2_MQ_CONFIG_DIS_IDB_DROP (1L<<3) #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4) #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4) #define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4) @@ -3698,6 +4425,7 @@ struct l2_fhdr { #define BNX2_MQ_MEM_WR_DATA2 0x00003c80 #define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0) +#define BNX2_MQ_MEM_WR_DATA2_VALUE_XI (0x7fffffffL<<0) #define BNX2_MQ_MEM_RD_ADDR 0x00003c84 #define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0) @@ -3710,6 +4438,16 @@ struct l2_fhdr { #define BNX2_MQ_MEM_RD_DATA2 0x00003c90 #define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0) +#define BNX2_MQ_MEM_RD_DATA2_VALUE_XI (0x7fffffffL<<0) + + +/* + * tsch_reg definition + * offset: 0x4c00 + */ +#define BNX2_TSCH_TSS_CFG 0x00004c1c +#define BNX2_TSCH_TSS_CFG_TSS_START_CID (0x7ffL<<8) +#define BNX2_TSCH_TSS_CFG_NUM_OF_TSS_CON (0xfL<<24) @@ -3759,7 +4497,11 @@ struct l2_fhdr { #define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) #define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) -#define BNX2_TBDR_FTQ_DATA 0x000053c0 +#define BNX2_TBDR_CKSUM_ERROR_STATUS 0x00005010 +#define BNX2_TBDR_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) +#define BNX2_TBDR_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + +#define BNX2_TBDR_TBDRQ 0x000053c0 #define BNX2_TBDR_FTQ_CMD 0x000053f8 #define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10) @@ -3789,7 +4531,15 @@ struct l2_fhdr { #define BNX2_TDMA_COMMAND 0x00005c00 #define BNX2_TDMA_COMMAND_ENABLED (1L<<0) #define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4) +#define BNX2_TDMA_COMMAND_CS16_ERR (1L<<5) #define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7) +#define BNX2_TDMA_COMMAND_MASK_CS1 (1L<<20) +#define BNX2_TDMA_COMMAND_MASK_CS2 (1L<<21) +#define BNX2_TDMA_COMMAND_MASK_CS3 (1L<<22) +#define BNX2_TDMA_COMMAND_MASK_CS4 (1L<<23) +#define BNX2_TDMA_COMMAND_FORCE_ILOCK_CKERR (1L<<24) +#define BNX2_TDMA_COMMAND_OFIFO_CLR (1L<<30) +#define BNX2_TDMA_COMMAND_IFIFO_CLR (1L<<31) #define BNX2_TDMA_STATUS 0x00005c04 #define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0) @@ -3798,10 +4548,18 @@ struct l2_fhdr { #define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3) #define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16) #define BNX2_TDMA_STATUS_BURST_CNT (1L<<17) +#define BNX2_TDMA_STATUS_MAX_IFIFO_DEPTH (0x3fL<<20) +#define BNX2_TDMA_STATUS_OFIFO_OVERFLOW (1L<<30) +#define BNX2_TDMA_STATUS_IFIFO_OVERFLOW (1L<<31) #define BNX2_TDMA_CONFIG 0x00005c08 #define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0) #define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1) +#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN (0x3L<<2) +#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_0 (0L<<2) +#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_1 (1L<<2) +#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_2 (2L<<2) +#define BNX2_TDMA_CONFIG_NUM_DMA_CHAN_3 (3L<<2) #define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4) #define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4) #define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4) @@ -3814,7 +4572,35 @@ struct l2_fhdr { #define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8) #define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15) #define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16) +#define BNX2_TDMA_CONFIG_CMPL_ENTRY (1L<<17) +#define BNX2_TDMA_CONFIG_OFIFO_CMP (1L<<19) +#define BNX2_TDMA_CONFIG_OFIFO_CMP_3 (0L<<19) +#define BNX2_TDMA_CONFIG_OFIFO_CMP_2 (1L<<19) #define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_XI (0x7L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_0_XI (0L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_4_XI (1L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_8_XI (2L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_16_XI (3L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_32_XI (4L<<20) +#define BNX2_TDMA_CONFIG_IFIFO_DEPTH_64_XI (5L<<20) +#define BNX2_TDMA_CONFIG_FIFO_CMP_EN_XI (1L<<23) +#define BNX2_TDMA_CONFIG_BYTES_OST_XI (0x7L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_512_XI (0L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_1024_XI (1L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_2048_XI (2L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_4096_XI (3L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_8192_XI (4L<<24) +#define BNX2_TDMA_CONFIG_BYTES_OST_16384_XI (5L<<24) +#define BNX2_TDMA_CONFIG_HC_BYPASS_XI (1L<<27) +#define BNX2_TDMA_CONFIG_LCL_MRRS_XI (0x7L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_128_XI (0L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_256_XI (1L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_512_XI (2L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_1024_XI (3L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_2048_XI (4L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_4096_XI (5L<<28) +#define BNX2_TDMA_CONFIG_LCL_MRRS_EN_XI (1L<<31) #define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c #define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3) @@ -3850,7 +4636,22 @@ struct l2_fhdr { #define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12) #define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16) -#define BNX2_TDMA_FTQ_DATA 0x00005fc0 +#define BNX2_TDMA_PUSH_FSM 0x00005c90 +#define BNX2_TDMA_BD_IF_DEBUG 0x00005c94 +#define BNX2_TDMA_DMAD_IF_DEBUG 0x00005c98 +#define BNX2_TDMA_CTX_IF_DEBUG 0x00005c9c +#define BNX2_TDMA_TPBUF_IF_DEBUG 0x00005ca0 +#define BNX2_TDMA_DR_IF_DEBUG 0x00005ca4 +#define BNX2_TDMA_TPATQ_IF_DEBUG 0x00005ca8 +#define BNX2_TDMA_TDMA_ILOCK_CKSUM 0x00005cac +#define BNX2_TDMA_TDMA_ILOCK_CKSUM_CALCULATED (0xffffL<<0) +#define BNX2_TDMA_TDMA_ILOCK_CKSUM_EXPECTED (0xffffL<<16) + +#define BNX2_TDMA_TDMA_PCIE_CKSUM 0x00005cb0 +#define BNX2_TDMA_TDMA_PCIE_CKSUM_CALCULATED (0xffffL<<0) +#define BNX2_TDMA_TDMA_PCIE_CKSUM_EXPECTED (0xffffL<<16) + +#define BNX2_TDMA_TDMAQ 0x00005fc0 #define BNX2_TDMA_FTQ_CMD 0x00005ff8 #define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10) @@ -3889,6 +4690,8 @@ struct l2_fhdr { #define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19) #define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19) #define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21) +#define BNX2_HC_COMMAND_MAIN_PWR_INT (1L<<22) +#define BNX2_HC_COMMAND_COAL_ON_NEXT_EVENT (1L<<27) #define BNX2_HC_STATUS 0x00006804 #define BNX2_HC_STATUS_MASTER_ABORT (1L<<0) @@ -3911,6 +4714,23 @@ struct l2_fhdr { #define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5) #define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6) #define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8) +#define BNX2_HC_CONFIG_PER_MODE (1L<<16) +#define BNX2_HC_CONFIG_ONE_SHOT (1L<<17) +#define BNX2_HC_CONFIG_USE_INT_PARAM (1L<<18) +#define BNX2_HC_CONFIG_SET_MASK_AT_RD (1L<<19) +#define BNX2_HC_CONFIG_PER_COLLECT_LIMIT (0xfL<<20) +#define BNX2_HC_CONFIG_SB_ADDR_INC (0x7L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_64B (0L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_128B (1L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_256B (2L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_512B (3L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_1024B (4L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_2048B (5L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_4096B (6L<<24) +#define BNX2_HC_CONFIG_SB_ADDR_INC_8192B (7L<<24) +#define BNX2_HC_CONFIG_GEN_STAT_AVG_INTR (1L<<29) +#define BNX2_HC_CONFIG_UNMASK_ALL (1L<<30) +#define BNX2_HC_CONFIG_TX_SEL (1L<<31) #define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c #define BNX2_HC_STATUS_ADDR_L 0x00006810 @@ -3947,6 +4767,7 @@ struct l2_fhdr { #define BNX2_HC_PERIODIC_TICKS 0x0000683c #define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_HC_INT_PERIODIC_TICKS (0xffffL<<16) #define BNX2_HC_STAT_COLLECT_TICKS 0x00006840 #define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4) @@ -3954,6 +4775,10 @@ struct l2_fhdr { #define BNX2_HC_STATS_TICKS 0x00006844 #define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8) +#define BNX2_HC_STATS_INTERRUPT_STATUS 0x00006848 +#define BNX2_HC_STATS_INTERRUPT_STATUS_SB_STATUS (0x1ffL<<0) +#define BNX2_HC_STATS_INTERRUPT_STATUS_INT_STATUS (0x1ffL<<16) + #define BNX2_HC_STAT_MEM_DATA 0x0000684c #define BNX2_HC_STAT_GEN_SEL_0 0x00006850 #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0) @@ -4082,24 +4907,108 @@ struct l2_fhdr { #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8) #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16) #define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_XI (0xffL<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UMP_RX_FRAME_DROP_XI (52L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S0_XI (57L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S1_XI (58L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S2_XI (85L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S3_XI (86L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S4_XI (87L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S5_XI (88L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S6_XI (89L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S7_XI (90L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S8_XI (91L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S9_XI (92L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_UNUSED_S10_XI (93L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MQ_IDB_OFLOW_XI (94L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_RD_CNT_XI (123L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_BLK_WR_CNT_XI (124L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_HITS_XI (125L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_MISSES_XI (126L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC1_XI (128L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC1_XI (129L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC1_XI (130L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC1_XI (131L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC1_XI (132L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC1_XI (133L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC2_XI (134L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC2_XI (135L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC2_XI (136L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC2_XI (137L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC2_XI (138L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC2_XI (139L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC3_XI (140L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC3_XI (141L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC3_XI (142L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC3_XI (143L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC3_XI (144L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC3_XI (145L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC4_XI (146L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC4_XI (147L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC4_XI (148L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC4_XI (149L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC4_XI (150L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC4_XI (151L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC5_XI (152L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC5_XI (153L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC5_XI (154L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC5_XI (155L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC5_XI (156L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC5_XI (157L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC6_XI (158L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC6_XI (159L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC6_XI (160L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC6_XI (161L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC6_XI (162L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC6_XI (163L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC7_XI (164L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC7_XI (165L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC7_XI (166L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC7_XI (167L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC7_XI (168L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC7_XI (169L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS_VEC8_XI (170L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN_VEC8_XI (171L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR_VEC8_XI (172L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK_VEC8_XI (173L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK_VEC8_XI (174L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK_VEC8_XI (175L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_CMD_CNT_XI (176L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCS_SLOT_CNT_XI (177L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PCSQ_VALID_CNT_XI (178L<<0) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1_XI (0xffL<<8) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2_XI (0xffL<<16) +#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3_XI (0xffL<<24) #define BNX2_HC_STAT_GEN_SEL_1 0x00006854 #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0) #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8) #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16) #define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4_XI (0xffL<<0) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5_XI (0xffL<<8) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6_XI (0xffL<<16) +#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7_XI (0xffL<<24) #define BNX2_HC_STAT_GEN_SEL_2 0x00006858 #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0) #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8) #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16) #define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8_XI (0xffL<<0) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9_XI (0xffL<<8) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10_XI (0xffL<<16) +#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11_XI (0xffL<<24) #define BNX2_HC_STAT_GEN_SEL_3 0x0000685c #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0) #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8) #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16) #define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12_XI (0xffL<<0) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13_XI (0xffL<<8) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14_XI (0xffL<<16) +#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15_XI (0xffL<<24) #define BNX2_HC_STAT_GEN_STAT0 0x00006888 #define BNX2_HC_STAT_GEN_STAT1 0x0000688c @@ -4133,6 +5042,7 @@ struct l2_fhdr { #define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc #define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900 #define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904 +#define BNX2_HC_STAT_GEN_STAT_AC 0x000068c8 #define BNX2_HC_VIS 0x00006908 #define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0) #define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0) @@ -4203,6 +5113,349 @@ struct l2_fhdr { #define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27) #define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28) +#define BNX2_HC_COALESCE_NOW 0x00006914 +#define BNX2_HC_COALESCE_NOW_COAL_NOW (0x1ffL<<1) +#define BNX2_HC_COALESCE_NOW_COAL_NOW_WO_INT (0x1ffL<<11) +#define BNX2_HC_COALESCE_NOW_COAL_ON_NXT_EVENT (0x1ffL<<21) + +#define BNX2_HC_MSIX_BIT_VECTOR 0x00006918 +#define BNX2_HC_MSIX_BIT_VECTOR_VAL (0x1ffL<<0) + +#define BNX2_HC_SB_CONFIG_1 0x00006a00 +#define BNX2_HC_SB_CONFIG_1_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_1_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_1_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_1_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_1_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_1_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_1_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_1_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_1 0x00006a04 +#define BNX2_HC_TX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_1_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_1 0x00006a08 +#define BNX2_HC_COMP_PROD_TRIP_1_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_1_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_1 0x00006a0c +#define BNX2_HC_RX_QUICK_CONS_TRIP_1_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_1_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_1 0x00006a10 +#define BNX2_HC_RX_TICKS_1_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_1_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_1 0x00006a14 +#define BNX2_HC_TX_TICKS_1_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_1_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_1 0x00006a18 +#define BNX2_HC_COM_TICKS_1_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_1_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_1 0x00006a1c +#define BNX2_HC_CMD_TICKS_1_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_1_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_1 0x00006a20 +#define BNX2_HC_PERIODIC_TICKS_1_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_1_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_2 0x00006a24 +#define BNX2_HC_SB_CONFIG_2_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_2_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_2_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_2_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_2_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_2_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_2_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_2_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_2 0x00006a28 +#define BNX2_HC_TX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_2_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_2 0x00006a2c +#define BNX2_HC_COMP_PROD_TRIP_2_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_2_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_2 0x00006a30 +#define BNX2_HC_RX_QUICK_CONS_TRIP_2_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_2_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_2 0x00006a34 +#define BNX2_HC_RX_TICKS_2_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_2_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_2 0x00006a38 +#define BNX2_HC_TX_TICKS_2_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_2_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_2 0x00006a3c +#define BNX2_HC_COM_TICKS_2_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_2_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_2 0x00006a40 +#define BNX2_HC_CMD_TICKS_2_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_2_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_2 0x00006a44 +#define BNX2_HC_PERIODIC_TICKS_2_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_2_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_3 0x00006a48 +#define BNX2_HC_SB_CONFIG_3_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_3_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_3_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_3_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_3_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_3_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_3_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_3_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_3 0x00006a4c +#define BNX2_HC_TX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_3_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_3 0x00006a50 +#define BNX2_HC_COMP_PROD_TRIP_3_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_3_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_3 0x00006a54 +#define BNX2_HC_RX_QUICK_CONS_TRIP_3_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_3_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_3 0x00006a58 +#define BNX2_HC_RX_TICKS_3_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_3_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_3 0x00006a5c +#define BNX2_HC_TX_TICKS_3_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_3_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_3 0x00006a60 +#define BNX2_HC_COM_TICKS_3_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_3_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_3 0x00006a64 +#define BNX2_HC_CMD_TICKS_3_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_3_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_3 0x00006a68 +#define BNX2_HC_PERIODIC_TICKS_3_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_3_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_4 0x00006a6c +#define BNX2_HC_SB_CONFIG_4_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_4_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_4_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_4_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_4_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_4_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_4_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_4_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_4 0x00006a70 +#define BNX2_HC_TX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_4_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_4 0x00006a74 +#define BNX2_HC_COMP_PROD_TRIP_4_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_4_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_4 0x00006a78 +#define BNX2_HC_RX_QUICK_CONS_TRIP_4_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_4_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_4 0x00006a7c +#define BNX2_HC_RX_TICKS_4_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_4_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_4 0x00006a80 +#define BNX2_HC_TX_TICKS_4_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_4_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_4 0x00006a84 +#define BNX2_HC_COM_TICKS_4_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_4_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_4 0x00006a88 +#define BNX2_HC_CMD_TICKS_4_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_4_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_4 0x00006a8c +#define BNX2_HC_PERIODIC_TICKS_4_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_4_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_5 0x00006a90 +#define BNX2_HC_SB_CONFIG_5_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_5_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_5_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_5_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_5_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_5_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_5_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_5_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_5 0x00006a94 +#define BNX2_HC_TX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_5_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_5 0x00006a98 +#define BNX2_HC_COMP_PROD_TRIP_5_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_5_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_5 0x00006a9c +#define BNX2_HC_RX_QUICK_CONS_TRIP_5_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_5_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_5 0x00006aa0 +#define BNX2_HC_RX_TICKS_5_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_5_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_5 0x00006aa4 +#define BNX2_HC_TX_TICKS_5_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_5_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_5 0x00006aa8 +#define BNX2_HC_COM_TICKS_5_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_5_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_5 0x00006aac +#define BNX2_HC_CMD_TICKS_5_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_5_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_5 0x00006ab0 +#define BNX2_HC_PERIODIC_TICKS_5_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_5_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_6 0x00006ab4 +#define BNX2_HC_SB_CONFIG_6_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_6_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_6_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_6_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_6_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_6_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_6_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_6_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_6 0x00006ab8 +#define BNX2_HC_TX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_6_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_6 0x00006abc +#define BNX2_HC_COMP_PROD_TRIP_6_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_6_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_6 0x00006ac0 +#define BNX2_HC_RX_QUICK_CONS_TRIP_6_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_6_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_6 0x00006ac4 +#define BNX2_HC_RX_TICKS_6_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_6_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_6 0x00006ac8 +#define BNX2_HC_TX_TICKS_6_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_6_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_6 0x00006acc +#define BNX2_HC_COM_TICKS_6_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_6_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_6 0x00006ad0 +#define BNX2_HC_CMD_TICKS_6_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_6_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_6 0x00006ad4 +#define BNX2_HC_PERIODIC_TICKS_6_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_6_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_7 0x00006ad8 +#define BNX2_HC_SB_CONFIG_7_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_7_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_7_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_7_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_7_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_7_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_7_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_7_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_7 0x00006adc +#define BNX2_HC_TX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_7_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_7 0x00006ae0 +#define BNX2_HC_COMP_PROD_TRIP_7_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_7_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_7 0x00006ae4 +#define BNX2_HC_RX_QUICK_CONS_TRIP_7_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_7_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_7 0x00006ae8 +#define BNX2_HC_RX_TICKS_7_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_7_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_7 0x00006aec +#define BNX2_HC_TX_TICKS_7_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_7_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_7 0x00006af0 +#define BNX2_HC_COM_TICKS_7_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_7_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_7 0x00006af4 +#define BNX2_HC_CMD_TICKS_7_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_7_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_7 0x00006af8 +#define BNX2_HC_PERIODIC_TICKS_7_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_7_HC_INT_PERIODIC_TICKS (0xffffL<<16) + +#define BNX2_HC_SB_CONFIG_8 0x00006afc +#define BNX2_HC_SB_CONFIG_8_RX_TMR_MODE (1L<<1) +#define BNX2_HC_SB_CONFIG_8_TX_TMR_MODE (1L<<2) +#define BNX2_HC_SB_CONFIG_8_COM_TMR_MODE (1L<<3) +#define BNX2_HC_SB_CONFIG_8_CMD_TMR_MODE (1L<<4) +#define BNX2_HC_SB_CONFIG_8_PER_MODE (1L<<16) +#define BNX2_HC_SB_CONFIG_8_ONE_SHOT (1L<<17) +#define BNX2_HC_SB_CONFIG_8_USE_INT_PARAM (1L<<18) +#define BNX2_HC_SB_CONFIG_8_PER_COLLECT_LIMIT (0xfL<<20) + +#define BNX2_HC_TX_QUICK_CONS_TRIP_8 0x00006b00 +#define BNX2_HC_TX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0) +#define BNX2_HC_TX_QUICK_CONS_TRIP_8_INT (0xffL<<16) + +#define BNX2_HC_COMP_PROD_TRIP_8 0x00006b04 +#define BNX2_HC_COMP_PROD_TRIP_8_VALUE (0xffL<<0) +#define BNX2_HC_COMP_PROD_TRIP_8_INT (0xffL<<16) + +#define BNX2_HC_RX_QUICK_CONS_TRIP_8 0x00006b08 +#define BNX2_HC_RX_QUICK_CONS_TRIP_8_VALUE (0xffL<<0) +#define BNX2_HC_RX_QUICK_CONS_TRIP_8_INT (0xffL<<16) + +#define BNX2_HC_RX_TICKS_8 0x00006b0c +#define BNX2_HC_RX_TICKS_8_VALUE (0x3ffL<<0) +#define BNX2_HC_RX_TICKS_8_INT (0x3ffL<<16) + +#define BNX2_HC_TX_TICKS_8 0x00006b10 +#define BNX2_HC_TX_TICKS_8_VALUE (0x3ffL<<0) +#define BNX2_HC_TX_TICKS_8_INT (0x3ffL<<16) + +#define BNX2_HC_COM_TICKS_8 0x00006b14 +#define BNX2_HC_COM_TICKS_8_VALUE (0x3ffL<<0) +#define BNX2_HC_COM_TICKS_8_INT (0x3ffL<<16) + +#define BNX2_HC_CMD_TICKS_8 0x00006b18 +#define BNX2_HC_CMD_TICKS_8_VALUE (0x3ffL<<0) +#define BNX2_HC_CMD_TICKS_8_INT (0x3ffL<<16) + +#define BNX2_HC_PERIODIC_TICKS_8 0x00006b1c +#define BNX2_HC_PERIODIC_TICKS_8_HC_PERIODIC_TICKS (0xffffL<<0) +#define BNX2_HC_PERIODIC_TICKS_8_HC_INT_PERIODIC_TICKS (0xffffL<<16) /* @@ -4228,7 +5481,7 @@ struct l2_fhdr { #define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_TXP_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4276,7 +5529,7 @@ struct l2_fhdr { #define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_TXP_CPU_REG_FILE 0x00045200 -#define BNX2_TXP_FTQ_DATA 0x000453c0 +#define BNX2_TXP_TXPQ 0x000453c0 #define BNX2_TXP_FTQ_CMD 0x000453f8 #define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10) @@ -4323,7 +5576,7 @@ struct l2_fhdr { #define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_TPAT_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4371,7 +5624,7 @@ struct l2_fhdr { #define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_TPAT_CPU_REG_FILE 0x00085200 -#define BNX2_TPAT_FTQ_DATA 0x000853c0 +#define BNX2_TPAT_TPATQ 0x000853c0 #define BNX2_TPAT_FTQ_CMD 0x000853f8 #define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10) @@ -4418,7 +5671,7 @@ struct l2_fhdr { #define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_RXP_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4466,7 +5719,29 @@ struct l2_fhdr { #define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_RXP_CPU_REG_FILE 0x000c5200 -#define BNX2_RXP_CFTQ_DATA 0x000c5380 +#define BNX2_RXP_PFE_PFE_CTL 0x000c537c +#define BNX2_RXP_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) +#define BNX2_RXP_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) +#define BNX2_RXP_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + +#define BNX2_RXP_RXPCQ 0x000c5380 #define BNX2_RXP_CFTQ_CMD 0x000c53b8 #define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10) @@ -4487,7 +5762,7 @@ struct l2_fhdr { #define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22) -#define BNX2_RXP_FTQ_DATA 0x000c53c0 +#define BNX2_RXP_RXPQ 0x000c53c0 #define BNX2_RXP_FTQ_CMD 0x000c53f8 #define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10) @@ -4515,6 +5790,10 @@ struct l2_fhdr { * com_reg definition * offset: 0x100000 */ +#define BNX2_COM_CKSUM_ERROR_STATUS 0x00100000 +#define BNX2_COM_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) +#define BNX2_COM_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + #define BNX2_COM_CPU_MODE 0x00105000 #define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0) #define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1) @@ -4534,7 +5813,7 @@ struct l2_fhdr { #define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_COM_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4582,7 +5861,29 @@ struct l2_fhdr { #define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_COM_CPU_REG_FILE 0x00105200 -#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340 +#define BNX2_COM_COMTQ_PFE_PFE_CTL 0x001052bc +#define BNX2_COM_COMTQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) +#define BNX2_COM_COMTQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + +#define BNX2_COM_COMXQ 0x00105340 #define BNX2_COM_COMXQ_FTQ_CMD 0x00105378 #define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10) @@ -4603,7 +5904,7 @@ struct l2_fhdr { #define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) -#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380 +#define BNX2_COM_COMTQ 0x00105380 #define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8 #define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10) @@ -4624,7 +5925,7 @@ struct l2_fhdr { #define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12) #define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22) -#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0 +#define BNX2_COM_COMQ 0x001053c0 #define BNX2_COM_COMQ_FTQ_CMD 0x001053f8 #define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10) @@ -4654,6 +5955,10 @@ struct l2_fhdr { * cp_reg definition * offset: 0x180000 */ +#define BNX2_CP_CKSUM_ERROR_STATUS 0x00180000 +#define BNX2_CP_CKSUM_ERROR_STATUS_CALCULATED (0xffffL<<0) +#define BNX2_CP_CKSUM_ERROR_STATUS_EXPECTED (0xffffL<<16) + #define BNX2_CP_CPU_MODE 0x00185000 #define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0) #define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1) @@ -4673,7 +5978,7 @@ struct l2_fhdr { #define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_CP_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4721,7 +6026,29 @@ struct l2_fhdr { #define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_CP_CPU_REG_FILE 0x00185200 -#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0 +#define BNX2_CP_CPQ_PFE_PFE_CTL 0x001853bc +#define BNX2_CP_CPQ_PFE_PFE_CTL_INC_USAGE_CNT (1L<<0) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE (0xfL<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_0 (0L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_1 (1L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_2 (2L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_3 (3L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_4 (4L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_5 (5L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_6 (6L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_7 (7L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_8 (8L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_9 (9L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_10 (10L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_11 (11L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_12 (12L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_13 (13L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_14 (14L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_SIZE_15 (15L<<4) +#define BNX2_CP_CPQ_PFE_PFE_CTL_PFE_COUNT (0xfL<<12) +#define BNX2_CP_CPQ_PFE_PFE_CTL_OFFSET (0x1ffL<<16) + +#define BNX2_CP_CPQ 0x001853c0 #define BNX2_CP_CPQ_FTQ_CMD 0x001853f8 #define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10) @@ -4749,6 +6076,59 @@ struct l2_fhdr { * mcp_reg definition * offset: 0x140000 */ +#define BNX2_MCP_MCP_CONTROL 0x00140080 +#define BNX2_MCP_MCP_CONTROL_SMBUS_SEL (1L<<30) +#define BNX2_MCP_MCP_CONTROL_MCP_ISOLATE (1L<<31) + +#define BNX2_MCP_MCP_ATTENTION_STATUS 0x00140084 +#define BNX2_MCP_MCP_ATTENTION_STATUS_DRV_DOORBELL (1L<<29) +#define BNX2_MCP_MCP_ATTENTION_STATUS_WATCHDOG_TIMEOUT (1L<<30) +#define BNX2_MCP_MCP_ATTENTION_STATUS_CPU_EVENT (1L<<31) + +#define BNX2_MCP_MCP_HEARTBEAT_CONTROL 0x00140088 +#define BNX2_MCP_MCP_HEARTBEAT_CONTROL_MCP_HEARTBEAT_ENABLE (1L<<31) + +#define BNX2_MCP_MCP_HEARTBEAT_STATUS 0x0014008c +#define BNX2_MCP_MCP_HEARTBEAT_STATUS_MCP_HEARTBEAT_PERIOD (0x7ffL<<0) +#define BNX2_MCP_MCP_HEARTBEAT_STATUS_VALID (1L<<31) + +#define BNX2_MCP_MCP_HEARTBEAT 0x00140090 +#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_COUNT (0x3fffffffL<<0) +#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_INC (1L<<30) +#define BNX2_MCP_MCP_HEARTBEAT_MCP_HEARTBEAT_RESET (1L<<31) + +#define BNX2_MCP_WATCHDOG_RESET 0x00140094 +#define BNX2_MCP_WATCHDOG_RESET_WATCHDOG_RESET (1L<<31) + +#define BNX2_MCP_WATCHDOG_CONTROL 0x00140098 +#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_TIMEOUT (0xfffffffL<<0) +#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ATTN (1L<<29) +#define BNX2_MCP_WATCHDOG_CONTROL_MCP_RST_ENABLE (1L<<30) +#define BNX2_MCP_WATCHDOG_CONTROL_WATCHDOG_ENABLE (1L<<31) + +#define BNX2_MCP_ACCESS_LOCK 0x0014009c +#define BNX2_MCP_ACCESS_LOCK_LOCK (1L<<31) + +#define BNX2_MCP_TOE_ID 0x001400a0 +#define BNX2_MCP_TOE_ID_FUNCTION_ID (1L<<31) + +#define BNX2_MCP_MAILBOX_CFG 0x001400a4 +#define BNX2_MCP_MAILBOX_CFG_MAILBOX_OFFSET (0x3fffL<<0) +#define BNX2_MCP_MAILBOX_CFG_MAILBOX_SIZE (0xfffL<<20) + +#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC 0x001400a8 +#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_OFFSET (0x3fffL<<0) +#define BNX2_MCP_MAILBOX_CFG_OTHER_FUNC_MAILBOX_SIZE (0xfffL<<20) + +#define BNX2_MCP_MCP_DOORBELL 0x001400ac +#define BNX2_MCP_MCP_DOORBELL_MCP_DOORBELL (1L<<31) + +#define BNX2_MCP_DRIVER_DOORBELL 0x001400b0 +#define BNX2_MCP_DRIVER_DOORBELL_DRIVER_DOORBELL (1L<<31) + +#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC 0x001400b4 +#define BNX2_MCP_DRIVER_DOORBELL_OTHER_FUNC_DRIVER_DOORBELL (1L<<31) + #define BNX2_MCP_CPU_MODE 0x00145000 #define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0) #define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1) @@ -4768,7 +6148,7 @@ struct l2_fhdr { #define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3) #define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4) #define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5) -#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6) +#define BNX2_MCP_CPU_STATE_BAD_PC_HALTED (1L<<6) #define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7) #define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8) #define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10) @@ -4816,7 +6196,7 @@ struct l2_fhdr { #define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2) #define BNX2_MCP_CPU_REG_FILE 0x00145200 -#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0 +#define BNX2_MCP_MCPQ 0x001453c0 #define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8 #define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0) #define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10) @@ -4971,6 +6351,7 @@ struct l2_fhdr { #define INVALID_CID_ADDR 0xffffffff #define TX_CID 16 +#define TX_TSS_CID 32 #define RX_CID 0 #define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID) @@ -5056,6 +6437,8 @@ struct bnx2 { u32 tx_prod_bseq __attribute__((aligned(L1_CACHE_BYTES))); u16 tx_prod; + u32 tx_bidx_addr; + u32 tx_bseq_addr; u16 tx_cons __attribute__((aligned(L1_CACHE_BYTES))); u16 hw_tx_cons; @@ -5112,6 +6495,7 @@ struct bnx2 { #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) #define CHIP_NUM_5706 0x57060000 #define CHIP_NUM_5708 0x57080000 +#define CHIP_NUM_5709 0x57090000 #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) #define CHIP_REV_Ax 0x00000000 @@ -5174,6 +6558,10 @@ struct bnx2 { struct statistics_block *stats_blk; dma_addr_t stats_blk_mapping; + int ctx_pages; + void *ctx_blk[4]; + dma_addr_t ctx_blk_mapping[4]; + u32 hc_cmd; u32 rx_mode; -- cgit v1.2.3 From 59b47d8ad35b9858d63d6fd3db76e698e4a98f36 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:10:45 -0800 Subject: [BNX2]: Add 5709 init code. Add basic support to initialize the 5709 chip. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 167 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 130 insertions(+), 37 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 2633579b8c43..baad015b3d6d 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -236,8 +236,23 @@ static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val) { offset += cid_addr; - REG_WR(bp, BNX2_CTX_DATA_ADR, offset); - REG_WR(bp, BNX2_CTX_DATA, val); + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + int i; + + REG_WR(bp, BNX2_CTX_CTX_DATA, val); + REG_WR(bp, BNX2_CTX_CTX_CTRL, + offset | BNX2_CTX_CTX_CTRL_WRITE_REQ); + for (i = 0; i < 5; i++) { + u32 val; + val = REG_RD(bp, BNX2_CTX_CTX_CTRL); + if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0) + break; + udelay(5); + } + } else { + REG_WR(bp, BNX2_CTX_DATA_ADR, offset); + REG_WR(bp, BNX2_CTX_DATA, val); + } } static int @@ -403,6 +418,14 @@ bnx2_free_mem(struct bnx2 *bp) { int i; + for (i = 0; i < bp->ctx_pages; i++) { + if (bp->ctx_blk[i]) { + pci_free_consistent(bp->pdev, BCM_PAGE_SIZE, + bp->ctx_blk[i], + bp->ctx_blk_mapping[i]); + bp->ctx_blk[i] = NULL; + } + } if (bp->status_blk) { pci_free_consistent(bp->pdev, bp->status_stats_size, bp->status_blk, bp->status_blk_mapping); @@ -481,6 +504,18 @@ bnx2_alloc_mem(struct bnx2 *bp) bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size; + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE; + if (bp->ctx_pages == 0) + bp->ctx_pages = 1; + for (i = 0; i < bp->ctx_pages; i++) { + bp->ctx_blk[i] = pci_alloc_consistent(bp->pdev, + BCM_PAGE_SIZE, + &bp->ctx_blk_mapping[i]); + if (bp->ctx_blk[i] == NULL) + goto alloc_mem_err; + } + } return 0; alloc_mem_err: @@ -803,13 +838,13 @@ bnx2_set_mac_link(struct bnx2 *bp) val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | - BNX2_EMAC_MODE_25G); + BNX2_EMAC_MODE_25G_MODE); if (bp->link_up) { switch (bp->line_speed) { case SPEED_10: - if (CHIP_NUM(bp) == CHIP_NUM_5708) { - val |= BNX2_EMAC_MODE_PORT_MII_10; + if (CHIP_NUM(bp) != CHIP_NUM_5706) { + val |= BNX2_EMAC_MODE_PORT_MII_10M; break; } /* fall through */ @@ -817,7 +852,7 @@ bnx2_set_mac_link(struct bnx2 *bp) val |= BNX2_EMAC_MODE_PORT_MII; break; case SPEED_2500: - val |= BNX2_EMAC_MODE_25G; + val |= BNX2_EMAC_MODE_25G_MODE; /* fall through */ case SPEED_1000: val |= BNX2_EMAC_MODE_PORT_GMII; @@ -1263,9 +1298,8 @@ bnx2_init_5706s_phy(struct bnx2 *bp) { bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; - if (CHIP_NUM(bp) == CHIP_NUM_5706) { - REG_WR(bp, BNX2_MISC_UNUSED0, 0x300); - } + if (CHIP_NUM(bp) == CHIP_NUM_5706) + REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300); if (bp->dev->mtu > 1500) { u32 val; @@ -1408,7 +1442,7 @@ bnx2_set_phy_loopback(struct bnx2 *bp) mac_mode = REG_RD(bp, BNX2_EMAC_MODE); mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | - BNX2_EMAC_MODE_25G); + BNX2_EMAC_MODE_25G_MODE); mac_mode |= BNX2_EMAC_MODE_PORT_GMII; REG_WR(bp, BNX2_EMAC_MODE, mac_mode); @@ -1459,6 +1493,40 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent) return 0; } +static int +bnx2_init_5709_context(struct bnx2 *bp) +{ + int i, ret = 0; + u32 val; + + val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12); + val |= (BCM_PAGE_BITS - 8) << 16; + REG_WR(bp, BNX2_CTX_COMMAND, val); + for (i = 0; i < bp->ctx_pages; i++) { + int j; + + REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0, + (bp->ctx_blk_mapping[i] & 0xffffffff) | + BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID); + REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1, + (u64) bp->ctx_blk_mapping[i] >> 32); + REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i | + BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ); + for (j = 0; j < 10; j++) { + + val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL); + if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ)) + break; + udelay(5); + } + if (val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ) { + ret = -EBUSY; + break; + } + } + return ret; +} + static void bnx2_init_context(struct bnx2 *bp) { @@ -1581,9 +1649,8 @@ bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index) return -ENOMEM; } - if (unlikely((align = (unsigned long) skb->data & 0x7))) { - skb_reserve(skb, 8 - align); - } + if (unlikely((align = (unsigned long) skb->data & (BNX2_RX_ALIGN - 1)))) + skb_reserve(skb, BNX2_RX_ALIGN - align); mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size, PCI_DMA_FROMDEVICE); @@ -3282,7 +3349,10 @@ bnx2_init_chip(struct bnx2 *bp) /* Initialize context mapping and zero out the quick contexts. The * context block must have already been enabled. */ - bnx2_init_context(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5709) + bnx2_init_5709_context(bp); + else + bnx2_init_context(bp); if ((rc = bnx2_init_cpus(bp)) != 0) return rc; @@ -3393,12 +3463,40 @@ bnx2_init_chip(struct bnx2 *bp) return rc; } +static void +bnx2_init_tx_context(struct bnx2 *bp, u32 cid) +{ + u32 val, offset0, offset1, offset2, offset3; + + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + offset0 = BNX2_L2CTX_TYPE_XI; + offset1 = BNX2_L2CTX_CMD_TYPE_XI; + offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; + offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI; + } else { + offset0 = BNX2_L2CTX_TYPE; + offset1 = BNX2_L2CTX_CMD_TYPE; + offset2 = BNX2_L2CTX_TBDR_BHADDR_HI; + offset3 = BNX2_L2CTX_TBDR_BHADDR_LO; + } + val = BNX2_L2CTX_TYPE_TYPE_L2 | BNX2_L2CTX_TYPE_SIZE_L2; + CTX_WR(bp, GET_CID_ADDR(cid), offset0, val); + + val = BNX2_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16); + CTX_WR(bp, GET_CID_ADDR(cid), offset1, val); + + val = (u64) bp->tx_desc_mapping >> 32; + CTX_WR(bp, GET_CID_ADDR(cid), offset2, val); + + val = (u64) bp->tx_desc_mapping & 0xffffffff; + CTX_WR(bp, GET_CID_ADDR(cid), offset3, val); +} static void bnx2_init_tx_ring(struct bnx2 *bp) { struct tx_bd *txbd; - u32 val; + u32 cid; bp->tx_wake_thresh = bp->tx_ring_size / 2; @@ -3412,19 +3510,11 @@ bnx2_init_tx_ring(struct bnx2 *bp) bp->hw_tx_cons = 0; bp->tx_prod_bseq = 0; - val = BNX2_L2CTX_TYPE_TYPE_L2; - val |= BNX2_L2CTX_TYPE_SIZE_L2; - CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val); + cid = TX_CID; + bp->tx_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BIDX; + bp->tx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_TX_HOST_BSEQ; - val = BNX2_L2CTX_CMD_TYPE_TYPE_L2; - val |= 8 << 16; - CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val); - - val = (u64) bp->tx_desc_mapping >> 32; - CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, val); - - val = (u64) bp->tx_desc_mapping & 0xffffffff; - CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val); + bnx2_init_tx_context(bp, cid); } static void @@ -3437,8 +3527,8 @@ bnx2_init_rx_ring(struct bnx2 *bp) /* 8 for CRC and VLAN */ bp->rx_buf_use_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8; - /* 8 for alignment */ - bp->rx_buf_size = bp->rx_buf_use_size + 8; + /* hw alignment */ + bp->rx_buf_size = bp->rx_buf_use_size + BNX2_RX_ALIGN; ring_prod = prod = bp->rx_prod = 0; bp->rx_cons = 0; @@ -5542,13 +5632,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) goto err_out_release; } - bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); - if (bp->pcix_cap == 0) { - dev_err(&pdev->dev, "Cannot find PCIX capability, aborting.\n"); - rc = -EIO; - goto err_out_release; - } - if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) { bp->flags |= USING_DAC_FLAG; if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) { @@ -5571,7 +5654,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) INIT_WORK(&bp->reset_task, bnx2_reset_task, bp); dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0); - mem_len = MB_GET_CID_ADDR(17); + mem_len = MB_GET_CID_ADDR(TX_TSS_CID + 1); dev->mem_end = dev->mem_start + mem_len; dev->irq = pdev->irq; @@ -5595,6 +5678,16 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->chip_id = REG_RD(bp, BNX2_MISC_ID); + if (CHIP_NUM(bp) != CHIP_NUM_5709) { + bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX); + if (bp->pcix_cap == 0) { + dev_err(&pdev->dev, + "Cannot find PCIX capability, aborting.\n"); + rc = -EIO; + goto err_out_unmap; + } + } + /* Get bus information. */ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { -- cgit v1.2.3 From 234754d5c1ef25bbc64631a420ba66eeb2904633 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:11:41 -0800 Subject: [BNX2]: Add 5709 reset and runtime code. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 61 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index baad015b3d6d..52fe620e1a4c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3247,31 +3247,44 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code) * before we issue a reset. */ val = REG_RD(bp, BNX2_MISC_ID); - val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | - BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET); + REG_RD(bp, BNX2_MISC_COMMAND); + udelay(5); - /* Chip reset. */ - REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; - if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || - (CHIP_ID(bp) == CHIP_ID_5706_A1)) - msleep(15); + pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, val); - /* Reset takes approximate 30 usec */ - for (i = 0; i < 10; i++) { - val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG); - if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) { - break; + } else { + val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA | + BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP; + + /* Chip reset. */ + REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val); + + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1)) { + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ / 50); } - udelay(10); - } - if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | - BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { - printk(KERN_ERR PFX "Chip reset did not complete\n"); - return -EBUSY; + /* Reset takes approximate 30 usec */ + for (i = 0; i < 10; i++) { + val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG); + if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) + break; + udelay(10); + } + + if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ | + BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) { + printk(KERN_ERR PFX "Chip reset did not complete\n"); + return -EBUSY; + } } /* Make sure byte swapping is properly configured. */ @@ -3976,8 +3989,8 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) bp->tx_prod = NEXT_TX_BD(bp->tx_prod); bp->tx_prod_bseq += pkt_size; - REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, bp->tx_prod); - REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq); + REG_WR16(bp, bp->tx_bidx_addr, bp->tx_prod); + REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq); udelay(100); @@ -4529,8 +4542,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) prod = NEXT_TX_BD(prod); bp->tx_prod_bseq += skb->len; - REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod); - REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq); + REG_WR16(bp, bp->tx_bidx_addr, prod); + REG_WR(bp, bp->tx_bseq_addr, bp->tx_prod_bseq); mmiowb(); -- cgit v1.2.3 From b6690cc2bd5e2831f971231a2ff8c4a74b06acc4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:12:28 -0800 Subject: [BNX2]: New firmware to support 5709 (part 1). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2_fw2.h | 1078 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1078 insertions(+) create mode 100644 drivers/net/bnx2_fw2.h (limited to 'drivers') diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h new file mode 100644 index 000000000000..b6f4b20c70f1 --- /dev/null +++ b/drivers/net/bnx2_fw2.h @@ -0,0 +1,1078 @@ +/* bnx2_fw2.h: Broadcom NX2 network driver. + * + * Copyright (c) 2006 Broadcom Corporation + * + * 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, except as noted below. + * + * This file contains firmware data derived from proprietary unpublished + * source code, Copyright (c) 2006 Broadcom Corporation. + * + * Permission is hereby granted for the distribution of this firmware data + * in hexadecimal or equivalent format, provided this copyright notice is + * accompanying it. + */ + +static u8 bnx2_COM_b09FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0xac, 0xfb, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xdc, 0x5b, 0x6b, 0x70, + 0x1b, 0xd7, 0x75, 0x3e, 0xfb, 0x00, 0x09, 0x91, 0x10, 0xb5, 0xa4, 0x60, + 0x1a, 0x96, 0x68, 0x07, 0x20, 0x57, 0x22, 0x6a, 0xb1, 0x29, 0x4c, 0x33, + 0x16, 0x9b, 0xc2, 0x12, 0x02, 0x50, 0xae, 0x26, 0xc3, 0x3a, 0x94, 0xcd, + 0xd8, 0x4a, 0xaa, 0xc9, 0x30, 0x00, 0xa5, 0xf4, 0x61, 0xb7, 0x92, 0xab, + 0xa9, 0x5d, 0xd7, 0xaa, 0x21, 0x92, 0x6a, 0xf5, 0x83, 0xe5, 0x2a, 0x16, + 0x43, 0xa9, 0xd3, 0x74, 0xc2, 0x12, 0x56, 0xac, 0x4e, 0x31, 0x85, 0xfc, + 0xd6, 0x38, 0xb1, 0xc9, 0x4a, 0x76, 0xeb, 0xf4, 0xe1, 0xa6, 0x33, 0xcd, + 0xa3, 0x9d, 0x36, 0xf6, 0xa8, 0x3f, 0xea, 0xe9, 0xd3, 0x33, 0x6e, 0xa7, + 0xea, 0xd8, 0x0e, 0xfa, 0x7d, 0x77, 0x77, 0x81, 0x25, 0x48, 0xbd, 0xfc, + 0xc8, 0x8f, 0x70, 0x06, 0xb3, 0x7b, 0xef, 0xde, 0xbd, 0xf7, 0xdc, 0xf3, + 0xf8, 0xce, 0x63, 0x2f, 0xfb, 0x44, 0x5a, 0xc4, 0xfb, 0x5b, 0x8b, 0x5f, + 0xfc, 0xfe, 0x5f, 0x2d, 0x7c, 0x7c, 0xf0, 0xe3, 0xfd, 0x22, 0xb7, 0xdc, + 0xa2, 0xb7, 0x86, 0x75, 0xf6, 0x1b, 0xf8, 0x45, 0xf1, 0xeb, 0xf7, 0xee, + 0x57, 0xfb, 0xb3, 0xf0, 0x7b, 0x13, 0x0f, 0xc7, 0xfe, 0x55, 0x44, 0xbb, + 0xc4, 0x98, 0xe0, 0x5f, 0xb5, 0x7a, 0xf9, 0xe7, 0x5c, 0x38, 0x7e, 0x89, + 0x67, 0x86, 0xbb, 0x9c, 0xa2, 0x97, 0x3f, 0x09, 0xeb, 0x69, 0x39, 0x94, + 0xb5, 0x25, 0x6c, 0xa4, 0xdf, 0x3c, 0x54, 0xb0, 0x45, 0x32, 0xe5, 0x2d, + 0xf1, 0x9c, 0xbc, 0x57, 0x2d, 0x46, 0x4d, 0x61, 0xff, 0x8d, 0xe9, 0x77, + 0xbf, 0xf6, 0xe2, 0xd6, 0xc4, 0x5b, 0xf3, 0x86, 0x84, 0xad, 0xf4, 0x19, + 0xb1, 0x36, 0x4b, 0xb8, 0x0b, 0xef, 0x7c, 0xb5, 0xf7, 0x3d, 0x91, 0x36, + 0x7f, 0xae, 0x37, 0xab, 0x2f, 0xf6, 0x4a, 0x71, 0x43, 0x3a, 0x2c, 0x7a, + 0x7a, 0xd3, 0xf7, 0xb3, 0x86, 0x35, 0x66, 0xa4, 0x2d, 0x59, 0xac, 0xc8, + 0xc8, 0xde, 0x69, 0x09, 0x87, 0xd3, 0x47, 0x9b, 0x9b, 0x37, 0x49, 0xd8, + 0x4c, 0x8f, 0x1d, 0xfa, 0x6d, 0xfb, 0xd1, 0xaa, 0x6e, 0xdb, 0xc9, 0x05, + 0x89, 0x0c, 0x9e, 0x1a, 0xc0, 0xf3, 0x72, 0x22, 0x29, 0xb2, 0x55, 0x74, + 0xbb, 0x18, 0x31, 0xec, 0xb0, 0x64, 0x2b, 0xb6, 0xe4, 0x2a, 0x22, 0x7f, + 0x5e, 0xd6, 0xe4, 0x94, 0xdd, 0x29, 0x0b, 0x7d, 0xef, 0x56, 0x33, 0xa0, + 0xe5, 0xcf, 0xec, 0xb1, 0x43, 0x53, 0x36, 0xe9, 0x9d, 0x6d, 0x76, 0xe9, + 0x9d, 0x6a, 0x2a, 0xd8, 0xa6, 0x4c, 0x94, 0xd9, 0x37, 0xa2, 0xb3, 0x2f, + 0x94, 0x7e, 0x68, 0xcd, 0x29, 0x3b, 0xe2, 0xf5, 0xed, 0xdc, 0x9e, 0xc5, + 0x7c, 0x93, 0x65, 0x8e, 0x3d, 0x93, 0x2a, 0xd8, 0x51, 0xaf, 0x3f, 0x79, + 0x5b, 0xd6, 0x8e, 0xa1, 0xbf, 0xcb, 0x7b, 0x76, 0xf2, 0xbe, 0x82, 0x6d, + 0x7b, 0xcf, 0xbe, 0x8a, 0xb9, 0x93, 0x5e, 0xff, 0x7d, 0xdb, 0x0a, 0x76, + 0x9f, 0xd7, 0x3f, 0xbd, 0x2d, 0x6b, 0xa7, 0xbc, 0xfe, 0xe4, 0xee, 0x82, + 0x3d, 0xe0, 0xf5, 0x9f, 0xbd, 0x3d, 0x6b, 0x0f, 0x7a, 0xfd, 0x0f, 0x6d, + 0x2d, 0xd8, 0x69, 0xf4, 0x1f, 0x6d, 0xd6, 0x37, 0x59, 0x72, 0xa4, 0x1c, + 0xc7, 0x2f, 0x83, 0x67, 0x43, 0xe8, 0xdb, 0x89, 0xdf, 0x30, 0x7e, 0xbf, + 0xb8, 0x4e, 0xda, 0x46, 0x70, 0xfd, 0xc6, 0x46, 0x97, 0x77, 0xe0, 0x91, + 0x13, 0x96, 0x37, 0x8c, 0x98, 0xbc, 0xd8, 0xfb, 0x06, 0x78, 0x68, 0xc9, + 0x99, 0x8a, 0x68, 0x23, 0xbd, 0x31, 0xf0, 0x2e, 0x2a, 0x4f, 0x56, 0x5a, + 0xc5, 0x78, 0xcc, 0x00, 0x6f, 0x3e, 0x2f, 0xf9, 0x68, 0x58, 0xda, 0xe7, + 0x34, 0xe9, 0xee, 0x0f, 0x4b, 0xc6, 0x52, 0x72, 0x13, 0x7d, 0x26, 0x2a, + 0xc6, 0x5c, 0x66, 0xbd, 0x2e, 0x9b, 0xac, 0x9c, 0x14, 0xc1, 0xbb, 0xef, + 0x51, 0x27, 0xf1, 0x2c, 0x2e, 0xb9, 0xe9, 0x9b, 0x65, 0xcc, 0x22, 0x5d, + 0x3b, 0x6f, 0x74, 0xd7, 0x0a, 0x6b, 0xd9, 0x13, 0x23, 0x72, 0xc4, 0x89, + 0x68, 0xb9, 0x13, 0xdb, 0x24, 0x9b, 0x92, 0x28, 0xde, 0x8b, 0xe5, 0xf1, + 0xa4, 0x54, 0x1e, 0x91, 0x29, 0x47, 0xb4, 0xac, 0x43, 0x7e, 0x76, 0xe2, + 0x79, 0x9b, 0x1a, 0x8b, 0xbe, 0x2e, 0x43, 0xcd, 0x1d, 0x46, 0xbf, 0x85, + 0xfe, 0x0e, 0x6d, 0x48, 0xcd, 0xa1, 0xfa, 0xe3, 0x93, 0x12, 0x91, 0xc7, + 0xcb, 0x51, 0x6f, 0x6c, 0xb5, 0x9a, 0x4d, 0x59, 0x18, 0x37, 0x22, 0x93, + 0x4e, 0x54, 0xc6, 0x70, 0x9d, 0x70, 0xb8, 0x7e, 0x0c, 0x3a, 0xf5, 0xda, + 0xa1, 0xfc, 0xac, 0x9a, 0x2f, 0x6e, 0xa4, 0x39, 0x5f, 0x17, 0xc6, 0x4d, + 0x80, 0x2e, 0x4d, 0x4c, 0x25, 0xcb, 0x8c, 0xe4, 0xa7, 0x35, 0xe8, 0x1b, + 0xae, 0x8a, 0xaf, 0x43, 0xa0, 0xdf, 0x14, 0xbb, 0x5f, 0x93, 0x02, 0x64, + 0x55, 0xb4, 0xd0, 0x2e, 0x9f, 0xd5, 0xb3, 0x4e, 0xb3, 0xe4, 0xcc, 0xb8, + 0x18, 0x33, 0x4a, 0x97, 0x64, 0x12, 0xef, 0xe8, 0x36, 0xc7, 0x5c, 0xc4, + 0xbe, 0xc7, 0x94, 0x1c, 0x9a, 0xd2, 0x45, 0x3d, 0x57, 0xe9, 0x14, 0x7d, + 0x6e, 0x8f, 0xbc, 0x3c, 0x2d, 0x96, 0x91, 0x7e, 0xb7, 0x9a, 0xb5, 0xa7, + 0xf4, 0xec, 0x13, 0xa6, 0x84, 0x66, 0x34, 0x99, 0xb2, 0x13, 0xb0, 0x80, + 0xa3, 0xfa, 0x8e, 0xca, 0x59, 0x8c, 0xe3, 0x7b, 0x18, 0x57, 0xd6, 0xc1, + 0x57, 0xde, 0x6f, 0xb1, 0x74, 0xa5, 0xcf, 0x1c, 0x03, 0x19, 0x60, 0x1f, + 0x4f, 0x3a, 0x90, 0x89, 0x92, 0x51, 0x1c, 0x32, 0x7a, 0x15, 0x32, 0x1a, + 0x80, 0x6c, 0x52, 0xf2, 0x52, 0xa5, 0x4f, 0x9e, 0xaf, 0x24, 0xe5, 0x39, + 0xe8, 0xeb, 0xb3, 0x95, 0xb8, 0x3c, 0x53, 0xe9, 0x92, 0xa7, 0x2b, 0x31, + 0x79, 0x4a, 0xc9, 0x2d, 0x07, 0xdb, 0x50, 0xb2, 0x0c, 0x5f, 0x9f, 0x96, + 0x70, 0x27, 0xe4, 0xd1, 0x01, 0xfd, 0x69, 0x87, 0x6e, 0x7e, 0xa5, 0x37, + 0x2c, 0xb3, 0xbd, 0x92, 0x59, 0x8f, 0xfe, 0x9b, 0xd2, 0xa6, 0xe2, 0x91, + 0x89, 0xe7, 0x93, 0xd3, 0x21, 0xc9, 0x59, 0x8f, 0xcb, 0x85, 0x19, 0x53, + 0x26, 0x2b, 0xdb, 0x6f, 0x72, 0x65, 0xc6, 0xf6, 0xbc, 0x9c, 0x9f, 0x69, + 0xc2, 0xb3, 0x79, 0x79, 0x79, 0xb3, 0x2e, 0x13, 0xb3, 0x6f, 0x89, 0x09, + 0x1e, 0x0e, 0x29, 0x79, 0x3f, 0x2e, 0xff, 0xfc, 0x27, 0x22, 0x23, 0xe0, + 0x8b, 0xde, 0xff, 0xef, 0xd5, 0x8c, 0x05, 0x7e, 0xf4, 0xf7, 0x41, 0x3f, + 0x74, 0x5c, 0x29, 0xcf, 0x38, 0xc6, 0x98, 0x5a, 0xce, 0x39, 0x0d, 0x9b, + 0x6a, 0xd5, 0xb2, 0xc7, 0x45, 0x0a, 0xc7, 0xab, 0x52, 0x48, 0x85, 0xe4, + 0x01, 0xab, 0x2a, 0x43, 0xa9, 0x26, 0x39, 0x60, 0x75, 0xca, 0x44, 0xdf, + 0xcf, 0x68, 0x3e, 0x96, 0x7d, 0xa5, 0x92, 0xc6, 0x3d, 0xfb, 0x44, 0x66, + 0xd5, 0xbd, 0xdb, 0x5f, 0xac, 0x84, 0x24, 0x13, 0x2d, 0xc6, 0x4c, 0xb9, + 0xa0, 0xb9, 0xb4, 0xed, 0xf4, 0x9f, 0x41, 0x5e, 0x63, 0xc0, 0x90, 0x84, + 0xd2, 0xa5, 0xfc, 0xf4, 0x9a, 0x8b, 0x19, 0xd5, 0x1d, 0x52, 0x7a, 0x6a, + 0xa4, 0x4d, 0xd2, 0x31, 0xa6, 0xa5, 0xa3, 0xd2, 0xad, 0xec, 0x64, 0x00, + 0x63, 0x06, 0xb5, 0xbb, 0x2b, 0x94, 0x37, 0xee, 0xcb, 0xa4, 0x75, 0x03, + 0xc6, 0x9a, 0xb8, 0x66, 0x3c, 0x9a, 0x83, 0x74, 0x72, 0x2e, 0xd2, 0xc9, + 0xeb, 0xde, 0x00, 0x9d, 0xfb, 0x6a, 0xf7, 0xb3, 0x81, 0xfb, 0x62, 0xe5, + 0xd7, 0x5b, 0x5c, 0xfa, 0xc8, 0xd7, 0x41, 0x99, 0x98, 0x7e, 0xc8, 0x5b, + 0x0b, 0xf7, 0x65, 0xae, 0xb1, 0x00, 0x3e, 0xa9, 0x91, 0x57, 0x58, 0xab, + 0x18, 0x58, 0xeb, 0x70, 0x60, 0xad, 0xc3, 0x81, 0xb5, 0x8a, 0xe0, 0xad, + 0xac, 0xd3, 0x81, 0x33, 0x79, 0xc2, 0xbc, 0x1c, 0xc5, 0x9c, 0x6f, 0x88, + 0x91, 0xa6, 0x2d, 0xf8, 0x36, 0xf9, 0x07, 0x18, 0x9f, 0x96, 0x73, 0x0e, + 0x78, 0x73, 0x3c, 0x24, 0x77, 0xa9, 0x71, 0xff, 0xb1, 0xc6, 0xa5, 0x31, + 0xf8, 0x2c, 0x2c, 0xbb, 0xa2, 0xbc, 0xf7, 0x9f, 0x99, 0xe0, 0x37, 0xdb, + 0x93, 0x37, 0xb8, 0x6d, 0xde, 0x9f, 0xf5, 0xf6, 0xd2, 0xee, 0xbe, 0x57, + 0x79, 0x53, 0x61, 0xc6, 0x62, 0x85, 0xb6, 0x2d, 0x29, 0xc3, 0x96, 0xfd, + 0x43, 0xa9, 0x4e, 0x99, 0xb4, 0xb4, 0xd4, 0x44, 0xb2, 0x99, 0xfc, 0xcf, + 0xe8, 0x76, 0x2b, 0xec, 0x47, 0xe2, 0x3a, 0x71, 0x51, 0xed, 0xeb, 0x5b, + 0x1e, 0xfd, 0x16, 0xdb, 0x23, 0xba, 0xdd, 0xd1, 0xd0, 0x4f, 0xfd, 0xff, + 0x4b, 0xdc, 0xd3, 0x06, 0xfa, 0x75, 0x77, 0xed, 0xbf, 0x42, 0x9b, 0x58, + 0x15, 0xf1, 0xda, 0xfe, 0xf3, 0xff, 0x32, 0x96, 0xb7, 0x8f, 0x6d, 0x5c, + 0xde, 0xf6, 0x6d, 0x29, 0x88, 0x73, 0xdc, 0x2b, 0x6c, 0xd8, 0xa6, 0xfe, + 0x85, 0x40, 0x6b, 0x0a, 0x36, 0xdc, 0xec, 0xd1, 0xf0, 0xba, 0x47, 0x03, + 0x68, 0xc5, 0xb8, 0x89, 0x0a, 0xdf, 0x51, 0xa2, 0x6c, 0x68, 0x93, 0xf7, + 0xfe, 0xfd, 0x5a, 0xf5, 0xfc, 0x0d, 0x83, 0xeb, 0xf8, 0x57, 0xd1, 0x86, + 0x60, 0x67, 0x93, 0xb3, 0xa6, 0xe4, 0x53, 0x31, 0x65, 0x0f, 0xf9, 0x54, + 0x1d, 0x3f, 0x26, 0xa7, 0x1b, 0xf1, 0x83, 0xef, 0x11, 0x3f, 0x5c, 0xec, + 0x98, 0x98, 0x25, 0x8e, 0xd4, 0x71, 0xe3, 0xc8, 0xb4, 0x8f, 0x25, 0x9c, + 0x9b, 0x18, 0xe2, 0xe3, 0x07, 0xdf, 0x23, 0x7e, 0x18, 0x90, 0x15, 0xe7, + 0xf4, 0xd7, 0x9f, 0x6a, 0x98, 0x7b, 0x4a, 0x61, 0x93, 0x8b, 0xcb, 0x6f, + 0x06, 0x70, 0xbe, 0x0b, 0x18, 0x1d, 0x85, 0xfc, 0x7c, 0x8c, 0x26, 0x76, + 0xc6, 0x80, 0xeb, 0xe0, 0x91, 0xc2, 0xe4, 0x08, 0x70, 0xcc, 0xf4, 0x30, + 0x35, 0xec, 0x61, 0x6a, 0x04, 0x78, 0xca, 0xb6, 0xe5, 0xb5, 0xa3, 0x5e, + 0x3b, 0x86, 0x36, 0xfc, 0xef, 0x1c, 0x6d, 0xec, 0xb5, 0x43, 0xe3, 0xb3, + 0x0a, 0xa7, 0x89, 0xf1, 0xc0, 0x0a, 0xe2, 0x2c, 0xf1, 0xb6, 0x4b, 0x16, + 0xca, 0x58, 0xaf, 0x86, 0x69, 0x94, 0x47, 0x90, 0x1e, 0xd2, 0xb2, 0x46, + 0xf4, 0xc7, 0xdc, 0xfd, 0xe8, 0xe9, 0xcf, 0xeb, 0xd2, 0xc2, 0x7d, 0x90, + 0xee, 0x1b, 0x41, 0x2b, 0xf7, 0xf6, 0xa3, 0xa4, 0x95, 0xeb, 0x35, 0xd2, + 0x7b, 0x1a, 0xf4, 0x66, 0x80, 0xb7, 0xa2, 0x8d, 0xf6, 0x8e, 0x82, 0xde, + 0x11, 0x60, 0xf1, 0x30, 0xb0, 0x78, 0x27, 0xb0, 0x78, 0x08, 0x58, 0x9c, + 0x06, 0x0e, 0x0f, 0x02, 0x87, 0x07, 0x80, 0xc3, 0x29, 0xec, 0x2b, 0x2a, + 0xf3, 0xc0, 0xe5, 0x79, 0xe0, 0xf3, 0x3c, 0xe4, 0x35, 0x31, 0x27, 0xda, + 0x17, 0xb0, 0xfe, 0x63, 0x33, 0x89, 0xd3, 0xd0, 0xcd, 0x58, 0x51, 0x87, + 0x3d, 0xa5, 0x06, 0xa1, 0x23, 0x49, 0x29, 0x55, 0x46, 0xa5, 0x40, 0x3f, + 0xb6, 0xb9, 0x07, 0xb6, 0x0b, 0xfb, 0x89, 0xf9, 0x71, 0xd3, 0x5a, 0xef, + 0xfa, 0xf7, 0x22, 0xf6, 0x1f, 0x83, 0x27, 0x89, 0xb8, 0xc8, 0xb0, 0xe4, + 0x9d, 0x1e, 0x2b, 0xab, 0x27, 0x31, 0x8e, 0xed, 0xb8, 0xb6, 0xf7, 0x78, + 0x42, 0x1b, 0x3f, 0xce, 0x3d, 0x4d, 0x03, 0xe3, 0xaa, 0x32, 0x95, 0xa2, + 0xad, 0x56, 0xe5, 0x54, 0x2a, 0x31, 0x58, 0x94, 0x56, 0x39, 0x12, 0x9d, + 0x56, 0xfe, 0xcd, 0x4c, 0x1f, 0x53, 0xfa, 0x51, 0xb0, 0x71, 0x2d, 0x77, + 0x6b, 0xf9, 0xe3, 0xf4, 0x3b, 0x3d, 0xf8, 0x85, 0x40, 0x0b, 0xe7, 0x37, + 0x65, 0x68, 0x40, 0xb4, 0x7d, 0xbd, 0x45, 0xa0, 0x62, 0xc2, 0x3a, 0x87, + 0x95, 0x73, 0xd3, 0x3d, 0xb1, 0x9c, 0x6e, 0xca, 0x98, 0xa9, 0xc9, 0x04, + 0xec, 0x65, 0x28, 0xf5, 0x7f, 0xd5, 0x23, 0x51, 0x3e, 0x6f, 0x96, 0xdf, + 0x51, 0x38, 0x8b, 0xb5, 0x4b, 0xb3, 0x58, 0x37, 0x04, 0xfe, 0x71, 0x5d, + 0xce, 0x83, 0x36, 0x30, 0xcf, 0xb4, 0x13, 0xa7, 0x8b, 0xb2, 0x1d, 0x76, + 0xb7, 0x4e, 0xb2, 0x7d, 0x4d, 0x92, 0x19, 0x89, 0xcb, 0xc4, 0xcc, 0x76, + 0xe0, 0x1e, 0x64, 0x60, 0xb7, 0x48, 0x7e, 0x34, 0x2e, 0x5f, 0x9e, 0x61, + 0x5f, 0x06, 0xfb, 0x4f, 0x1c, 0xcd, 0x08, 0xf7, 0x1f, 0x52, 0xfb, 0x8a, + 0xeb, 0x19, 0x39, 0xe0, 0xbc, 0xa4, 0xbb, 0x76, 0xe9, 0xb6, 0xf7, 0x42, + 0x1e, 0xa7, 0xc0, 0xef, 0xbc, 0x63, 0xcb, 0x02, 0xfc, 0x4a, 0xee, 0x38, + 0x70, 0xd5, 0x6e, 0x03, 0x06, 0x26, 0xce, 0xd2, 0x3e, 0x0c, 0xc4, 0x5a, + 0x25, 0xc5, 0xeb, 0x2e, 0x39, 0x3e, 0xa3, 0xcb, 0xb3, 0xb7, 0xc5, 0xd1, + 0x06, 0xd6, 0xa6, 0x12, 0x67, 0xc6, 0xf4, 0x2e, 0xb9, 0xb5, 0x23, 0x86, + 0xf7, 0x52, 0x5a, 0xde, 0xf9, 0x37, 0xf2, 0xf2, 0x64, 0x5c, 0xe7, 0x58, + 0x5d, 0x72, 0x29, 0x03, 0x3a, 0x56, 0xc4, 0xf8, 0x7f, 0x40, 0x7f, 0x97, + 0xcc, 0x21, 0xbe, 0x99, 0x03, 0x4d, 0xd9, 0x14, 0xb1, 0x30, 0x71, 0x72, + 0x49, 0x07, 0x66, 0xcd, 0x41, 0x37, 0x47, 0x11, 0x3f, 0xcc, 0xfc, 0x37, + 0xc6, 0xc4, 0x21, 0xd3, 0x1e, 0x6b, 0x02, 0xf8, 0x92, 0xe9, 0xe2, 0x3d, + 0xe7, 0xb4, 0xe5, 0x94, 0x43, 0x1d, 0x8a, 0xcb, 0xe3, 0x15, 0xbe, 0xd7, + 0x73, 0xf6, 0x69, 0xb1, 0xe5, 0x41, 0xe7, 0x7f, 0x30, 0xfe, 0x1d, 0xc4, + 0x9e, 0x96, 0x94, 0x20, 0xb7, 0x02, 0x78, 0x99, 0x89, 0xb9, 0xed, 0x89, + 0xb9, 0xc4, 0xd9, 0x0b, 0x3a, 0xef, 0xed, 0xe2, 0x82, 0x7e, 0xb3, 0x48, + 0x07, 0xf9, 0x99, 0x02, 0x2f, 0x6d, 0x4b, 0xd7, 0x37, 0x7b, 0xf1, 0x16, + 0x6d, 0xc0, 0x06, 0x7d, 0xa6, 0x2c, 0xf4, 0x07, 0x6d, 0x80, 0x7e, 0xd6, + 0xb7, 0x81, 0x44, 0x6c, 0x49, 0xd7, 0xf1, 0xdc, 0x94, 0x63, 0xaa, 0xad, + 0x81, 0xd6, 0x44, 0x8c, 0xfb, 0x9b, 0x2c, 0x27, 0xe5, 0x71, 0x87, 0xe3, + 0xc1, 0xe7, 0xe9, 0x88, 0x37, 0x1e, 0xf1, 0x8e, 0xc3, 0x98, 0x29, 0x09, + 0x9a, 0x5d, 0xbb, 0x58, 0x98, 0x8e, 0xaa, 0x67, 0x47, 0x1c, 0x37, 0x36, + 0xd2, 0x11, 0x3f, 0xcd, 0x23, 0x7e, 0xca, 0x29, 0x1b, 0xb1, 0x32, 0x88, + 0xaf, 0xe1, 0x67, 0x5d, 0xfb, 0x28, 0x95, 0x49, 0xcb, 0x3d, 0xa0, 0x2f, + 0x51, 0x04, 0x31, 0xc7, 0x74, 0xb8, 0xeb, 0xec, 0x80, 0x14, 0x19, 0x63, + 0x9d, 0x33, 0x1e, 0x91, 0xb1, 0x12, 0xfd, 0x1b, 0x7e, 0x8e, 0x6d, 0x31, + 0xa6, 0xcf, 0x28, 0xdf, 0xd3, 0x03, 0x3d, 0x80, 0x5f, 0x4a, 0xb5, 0x8b, + 0xeb, 0x07, 0xf7, 0x40, 0x9e, 0xc3, 0x90, 0x7b, 0x5a, 0xc6, 0x4f, 0x8c, + 0x53, 0xa7, 0x93, 0x25, 0x49, 0x24, 0x8f, 0xc8, 0x16, 0x6b, 0x01, 0xbe, + 0x30, 0x33, 0x5a, 0xdd, 0xae, 0xa7, 0xf9, 0xce, 0xa3, 0x78, 0x07, 0xd7, + 0xd2, 0xb8, 0x3c, 0x50, 0x61, 0xdf, 0x9d, 0x86, 0xb4, 0xc0, 0x56, 0x06, + 0xf6, 0x78, 0x76, 0x80, 0xf9, 0x4c, 0x7f, 0xbe, 0x71, 0x6f, 0x3e, 0x8e, + 0xe3, 0x18, 0xbe, 0x53, 0x9f, 0x77, 0x07, 0x7d, 0x1b, 0xb0, 0x64, 0x87, + 0x5e, 0xdd, 0x1e, 0xc2, 0xf3, 0x53, 0x03, 0xbc, 0xc7, 0x3c, 0xf0, 0x6d, + 0x96, 0x3d, 0x8c, 0xb1, 0xa3, 0x98, 0x73, 0x8d, 0x64, 0x3b, 0x7d, 0x7a, + 0xa9, 0x03, 0x8c, 0x3f, 0xd8, 0x8e, 0xae, 0x77, 0x79, 0xff, 0x25, 0xc3, + 0xd5, 0xc9, 0x11, 0xb4, 0x69, 0x7f, 0x07, 0x25, 0xe7, 0x24, 0xb0, 0x4f, + 0xf0, 0xb6, 0x32, 0xe1, 0xed, 0x11, 0xfc, 0x1f, 0x39, 0x0c, 0x3e, 0x48, + 0xd1, 0xe5, 0x0d, 0xf9, 0x42, 0x9e, 0xfc, 0x16, 0x74, 0xff, 0x61, 0x8c, + 0x81, 0x7f, 0x50, 0x3c, 0x58, 0xea, 0x70, 0x63, 0xd1, 0x44, 0x31, 0xc3, + 0xfc, 0xa9, 0x83, 0x98, 0x07, 0xfc, 0xa9, 0x40, 0xb1, 0x30, 0xf7, 0x92, + 0xbe, 0x86, 0xf4, 0xc6, 0x97, 0x0c, 0x83, 0xed, 0xe4, 0x12, 0x74, 0xb8, + 0x04, 0xf9, 0x64, 0xfb, 0x68, 0xb3, 0x36, 0xe4, 0x31, 0x63, 0x50, 0x5f, + 0x4b, 0x88, 0x05, 0xf3, 0xce, 0x16, 0xeb, 0x5e, 0xf2, 0xcd, 0xb2, 0xe4, + 0x69, 0x27, 0x88, 0x1d, 0x3b, 0x30, 0x94, 0x7a, 0x18, 0x85, 0x1e, 0x98, + 0xf0, 0xc9, 0x31, 0xc8, 0xfc, 0xc5, 0x0e, 0x77, 0x2f, 0xbc, 0x37, 0x65, + 0xde, 0xc2, 0x9a, 0xce, 0xef, 0xaf, 0x73, 0xfb, 0x78, 0xcf, 0xb8, 0xc8, + 0x97, 0xab, 0x4f, 0x3b, 0xe5, 0xdb, 0x28, 0xd3, 0x43, 0xd8, 0x0b, 0xfb, + 0x71, 0x2d, 0x1d, 0x94, 0x71, 0xd0, 0x56, 0x18, 0xd8, 0x14, 0x3b, 0x8f, + 0xf1, 0x39, 0xe0, 0x79, 0xd1, 0xe4, 0xb3, 0x8b, 0x5a, 0xfd, 0x1d, 0xc4, + 0x5c, 0x36, 0xfd, 0xd9, 0x92, 0xf6, 0x85, 0xca, 0xcb, 0x5a, 0xb6, 0x74, + 0x51, 0xcb, 0x41, 0x4f, 0x4a, 0x0e, 0x73, 0x06, 0xda, 0x8f, 0x85, 0xb5, + 0x13, 0xb1, 0xb7, 0xf5, 0x9e, 0xf8, 0x02, 0xb0, 0x60, 0x2f, 0x6c, 0x3a, + 0x67, 0xee, 0x94, 0x02, 0xb0, 0x35, 0x7f, 0x62, 0x0b, 0xec, 0x2d, 0x1e, + 0xa0, 0x8b, 0x78, 0x56, 0xa4, 0x4f, 0xd5, 0x76, 0x38, 0x52, 0x6c, 0x4a, + 0x13, 0xd7, 0x36, 0x41, 0x77, 0xd0, 0x57, 0xae, 0xeb, 0xdf, 0x1d, 0x2b, + 0x68, 0x45, 0x7e, 0x39, 0xb0, 0x9c, 0xde, 0x92, 0x5c, 0x99, 0xde, 0x1d, + 0x35, 0x7a, 0x89, 0x19, 0xc0, 0x7f, 0xd8, 0xcd, 0x4b, 0xd0, 0xdf, 0xe7, + 0x1d, 0xe0, 0xbf, 0x03, 0xfc, 0x87, 0x4d, 0x3d, 0x03, 0xdd, 0x7b, 0xda, + 0x81, 0x0f, 0x70, 0xe0, 0x03, 0x1c, 0xf8, 0x00, 0x27, 0x0b, 0x39, 0x11, + 0xe7, 0xe9, 0x43, 0x76, 0xd7, 0x7c, 0x9e, 0x1b, 0x37, 0xdd, 0xe0, 0xc5, + 0x22, 0xa3, 0x88, 0x45, 0x36, 0xc8, 0x44, 0xf2, 0x7a, 0xec, 0xad, 0x05, + 0xd7, 0x56, 0x5c, 0xb1, 0x46, 0xf2, 0x76, 0xcf, 0x4e, 0x1e, 0x06, 0x5d, + 0x88, 0xbf, 0x93, 0x3f, 0x0d, 0x3d, 0x6c, 0x02, 0x3d, 0x3f, 0xe5, 0xc5, + 0x2c, 0x0f, 0x9a, 0xae, 0x1e, 0xb6, 0xa2, 0xef, 0x93, 0xe8, 0x6b, 0xc5, + 0x98, 0x03, 0x18, 0xc3, 0x98, 0xa7, 0xcd, 0xeb, 0x0b, 0x8e, 0x63, 0xec, + 0xf3, 0x19, 0xac, 0x95, 0xc0, 0xb8, 0x36, 0xcc, 0xdd, 0x85, 0x31, 0xdb, + 0x30, 0xe6, 0x46, 0xb4, 0x19, 0x33, 0x6f, 0x44, 0xfb, 0x13, 0x0d, 0xef, + 0x7c, 0x0c, 0x7d, 0xb7, 0x37, 0xf4, 0x9d, 0x43, 0x1f, 0xf2, 0x50, 0xeb, + 0xbc, 0xf7, 0x5e, 0x11, 0xed, 0xce, 0x86, 0x31, 0xaf, 0xa2, 0x0f, 0x71, + 0xaf, 0xf5, 0x2d, 0x5c, 0x91, 0x7f, 0x5a, 0xa4, 0xc9, 0x7f, 0xc6, 0xb8, + 0x37, 0x8e, 0xfe, 0x90, 0x17, 0xbb, 0xfe, 0xa6, 0x09, 0xbd, 0xd3, 0x86, + 0x9c, 0xdf, 0x30, 0xdd, 0x58, 0xef, 0x4e, 0xcb, 0xd5, 0x43, 0xbf, 0xfd, + 0x70, 0x43, 0x9b, 0x63, 0x17, 0x1a, 0xfa, 0xfe, 0xa5, 0xa1, 0xfd, 0xdd, + 0xd0, 0xca, 0x77, 0x06, 0xdb, 0x97, 0xf7, 0x15, 0x3a, 0x96, 0xb7, 0xed, + 0xa6, 0x95, 0xef, 0xe8, 0xeb, 0x96, 0xf7, 0xdd, 0xb8, 0xbe, 0x61, 0x0c, + 0x74, 0x2a, 0x8a, 0x1c, 0xc9, 0x1f, 0x1f, 0xbe, 0xce, 0x7d, 0x4e, 0xfe, + 0x36, 0xea, 0x92, 0xda, 0x3a, 0xda, 0x3a, 0xe4, 0xb0, 0xa4, 0xc1, 0x9e, + 0x2c, 0x3d, 0xfd, 0xb2, 0x96, 0x83, 0x4e, 0x65, 0x2b, 0xfe, 0x7c, 0xb4, + 0xd9, 0xc6, 0xdc, 0xdc, 0xcf, 0xc9, 0x19, 0x2b, 0x45, 0xa0, 0x37, 0xf7, + 0xd0, 0x27, 0x1d, 0x2d, 0x4a, 0xdd, 0x3e, 0xbb, 0xf5, 0x4b, 0xd9, 0xe7, + 0xed, 0x1e, 0x46, 0x1d, 0x06, 0x9d, 0x55, 0x19, 0x49, 0x35, 0xd3, 0xc7, + 0x78, 0xd8, 0x45, 0xdc, 0xa9, 0x56, 0x8d, 0xcd, 0x55, 0xd9, 0x9f, 0x7a, + 0xa7, 0x2a, 0x0a, 0xf3, 0x06, 0x15, 0xee, 0xc4, 0xf5, 0x1e, 0xc8, 0xc8, + 0x42, 0x6e, 0x82, 0x7c, 0x3a, 0x4a, 0x9f, 0x74, 0x90, 0xf1, 0xc9, 0xa3, + 0x2e, 0xa6, 0x12, 0x77, 0xd0, 0x46, 0x5e, 0x96, 0x3f, 0xce, 0xf5, 0x71, + 0x2d, 0x11, 0xc7, 0x47, 0x95, 0x4f, 0xc9, 0x5b, 0x9c, 0x77, 0x35, 0x6c, + 0x3c, 0x6b, 0x32, 0xa6, 0x33, 0xed, 0xd3, 0xf0, 0x6f, 0x7c, 0xc6, 0x58, + 0xe1, 0x34, 0xe3, 0x92, 0x00, 0x56, 0x6d, 0x35, 0xe0, 0x32, 0x8b, 0xcb, + 0xf7, 0xb5, 0x81, 0x79, 0xc4, 0x55, 0xec, 0x75, 0x75, 0x2c, 0xea, 0xd1, + 0xaf, 0x6c, 0xdb, 0xbb, 0x6a, 0xb6, 0xed, 0xeb, 0xde, 0x6a, 0x39, 0xf8, + 0xf7, 0x95, 0x2c, 0x9e, 0xaa, 0x24, 0x8e, 0x15, 0x61, 0x4b, 0x8b, 0x2a, + 0xef, 0xf6, 0xe5, 0xc2, 0x18, 0x27, 0x71, 0x72, 0x1e, 0x6f, 0x8e, 0xab, + 0x1c, 0x83, 0xf9, 0x45, 0x55, 0x76, 0xa4, 0x5a, 0xa3, 0xe4, 0x43, 0x46, + 0xff, 0x76, 0x88, 0x31, 0xc3, 0xa2, 0x43, 0x9e, 0xa5, 0xf0, 0x3c, 0x05, + 0x4c, 0xf8, 0x27, 0xc9, 0x45, 0xd9, 0xf7, 0x76, 0x75, 0x01, 0x71, 0x95, + 0x8a, 0x8f, 0x94, 0xbf, 0x67, 0x7c, 0xb7, 0x1f, 0xfc, 0x22, 0x4f, 0x47, + 0xc0, 0x67, 0x3f, 0x06, 0x78, 0x8d, 0x75, 0x15, 0x59, 0x1e, 0x07, 0x8b, + 0x3c, 0x50, 0x7e, 0x19, 0x73, 0xea, 0x6e, 0xac, 0xc2, 0x3c, 0xdc, 0x66, + 0x7f, 0x47, 0x88, 0xb1, 0x9c, 0xeb, 0xeb, 0x0d, 0xac, 0x87, 0xdc, 0xbe, + 0xfc, 0x8f, 0x2a, 0x6e, 0x2a, 0x28, 0x79, 0x20, 0x86, 0xaa, 0xf0, 0x19, + 0xfb, 0xc2, 0x5e, 0xec, 0x1c, 0xf1, 0x62, 0x65, 0xcb, 0x8b, 0x95, 0x49, + 0x07, 0x6b, 0x6f, 0x7e, 0x5c, 0x40, 0x99, 0x2d, 0x1d, 0xd2, 0x37, 0x33, + 0x2e, 0x68, 0x93, 0xd5, 0xe3, 0x02, 0x9f, 0xa6, 0x6d, 0xa0, 0x89, 0x71, + 0x9e, 0xaa, 0xbd, 0x74, 0xb8, 0xf5, 0x1e, 0xd2, 0xe0, 0xfb, 0x47, 0xe5, + 0x87, 0x8f, 0xc2, 0xe5, 0x61, 0x6f, 0x69, 0xd0, 0xba, 0x53, 0xb2, 0xd3, + 0xdb, 0x3c, 0x7f, 0xcb, 0x1c, 0x80, 0xf1, 0xb7, 0xab, 0xb3, 0xd9, 0xd4, + 0x84, 0x3f, 0x4f, 0x27, 0x3c, 0x64, 0xa0, 0x2e, 0xc4, 0xb5, 0x18, 0xc7, + 0xf8, 0x31, 0xcd, 0x4e, 0x2f, 0xa6, 0x19, 0x96, 0xfd, 0x8e, 0x1b, 0xf3, + 0x8f, 0xa0, 0x3f, 0xef, 0x28, 0xda, 0x63, 0x8c, 0x2d, 0x75, 0xc4, 0xdc, + 0x99, 0x3d, 0x09, 0x24, 0x0f, 0xee, 0x5e, 0xba, 0xb1, 0x97, 0x52, 0x6d, + 0x2f, 0xad, 0x4b, 0xcb, 0xf7, 0x32, 0xaa, 0xde, 0x9d, 0x5a, 0xf1, 0xae, + 0x60, 0x1f, 0xbb, 0x2f, 0xf1, 0x8c, 0x7b, 0x64, 0xdc, 0x60, 0x79, 0x7b, + 0xf4, 0xe5, 0x74, 0x00, 0x7b, 0x4c, 0x6a, 0x79, 0x15, 0x6b, 0xed, 0x51, + 0x3c, 0xcf, 0x97, 0xc7, 0x70, 0xa5, 0x7d, 0xa8, 0x79, 0x94, 0x8d, 0x4c, + 0x28, 0x3e, 0x8f, 0xab, 0x7d, 0x2c, 0x94, 0x7f, 0x41, 0x0a, 0x27, 0x7e, + 0x09, 0x7e, 0x2f, 0x58, 0x0f, 0x63, 0x2d, 0x91, 0xfc, 0x28, 0x06, 0xf0, + 0x93, 0x7b, 0x65, 0xad, 0xeb, 0x0f, 0x43, 0x6e, 0x7e, 0x10, 0x81, 0x8c, + 0x35, 0xf7, 0xb9, 0x5a, 0xdf, 0xe7, 0x6b, 0x53, 0x80, 0x9e, 0x2a, 0x62, + 0xce, 0x18, 0x68, 0x08, 0xbe, 0x73, 0x50, 0x86, 0x1c, 0xca, 0xa3, 0x27, + 0x36, 0x2e, 0xb6, 0x95, 0x17, 0x3f, 0xce, 0xe0, 0xfa, 0xb4, 0xf9, 0x5c, + 0xcc, 0x10, 0xd6, 0x2f, 0x7d, 0xde, 0xf9, 0x7c, 0x8b, 0x2c, 0x35, 0xea, + 0xc0, 0x14, 0xe8, 0x29, 0x38, 0xe4, 0x93, 0xaf, 0x9b, 0xfe, 0xda, 0xaf, + 0xaa, 0xfd, 0x4c, 0xaa, 0x9a, 0xdd, 0x73, 0x35, 0x1d, 0x9d, 0x40, 0x0c, + 0xe2, 0xea, 0xdc, 0x7d, 0x1e, 0x6f, 0x7c, 0xdd, 0x8c, 0x78, 0x72, 0x66, + 0x1e, 0x47, 0xdb, 0xf1, 0xf5, 0x60, 0x93, 0x75, 0xb7, 0xe2, 0x05, 0x9f, + 0x11, 0x53, 0x5c, 0x59, 0x8e, 0xd5, 0x64, 0xb9, 0xb6, 0x41, 0x2f, 0xbf, + 0xb7, 0xce, 0xb5, 0x43, 0xda, 0x1b, 0xec, 0x16, 0xf4, 0x3d, 0xb5, 0xcc, + 0xbe, 0x93, 0x97, 0xa8, 0x83, 0x46, 0xc4, 0x98, 0xfb, 0x53, 0xf0, 0xf2, + 0x63, 0xc8, 0x55, 0x44, 0xcc, 0x19, 0xe2, 0x10, 0xe3, 0x8d, 0x7a, 0xbc, + 0xbb, 0x20, 0xab, 0xc5, 0xba, 0x57, 0x8a, 0x35, 0x7e, 0xf2, 0x2a, 0x63, + 0x8d, 0x78, 0x93, 0xb4, 0x10, 0x8b, 0x86, 0x11, 0xdb, 0x6a, 0xd2, 0x64, + 0x3f, 0x08, 0x1f, 0x76, 0xc6, 0x6c, 0xb6, 0x7d, 0x4c, 0x88, 0x48, 0xfb, + 0xdc, 0x06, 0x85, 0x0b, 0xd6, 0x4c, 0x1d, 0x17, 0x26, 0xc0, 0xfb, 0x11, + 0xb7, 0xb6, 0x1a, 0x6d, 0x97, 0xab, 0xcd, 0x8d, 0xeb, 0x71, 0xff, 0x58, + 0x2d, 0xee, 0xbf, 0xa1, 0x81, 0x8f, 0xab, 0xe1, 0xe2, 0x19, 0xf0, 0x2d, + 0x8d, 0xfc, 0x97, 0x79, 0xed, 0x10, 0xf2, 0x61, 0xe6, 0x62, 0x19, 0xe4, + 0xc4, 0x89, 0x33, 0xc0, 0x2a, 0xe4, 0xc8, 0x89, 0xb7, 0xe0, 0x57, 0x90, + 0x37, 0x27, 0xe6, 0x99, 0xbb, 0x2e, 0x22, 0x3f, 0x7e, 0x1a, 0xf9, 0xf1, + 0x53, 0x95, 0x3e, 0xf0, 0x37, 0xa9, 0xb0, 0x73, 0xef, 0x71, 0xd1, 0xee, + 0x52, 0xf5, 0x61, 0xda, 0x73, 0x14, 0x7e, 0xb4, 0x5a, 0x3d, 0x90, 0xea, + 0x41, 0x4e, 0x1e, 0x97, 0x4f, 0x99, 0xcc, 0x63, 0x35, 0xb3, 0xbb, 0x7f, + 0xc1, 0x08, 0xc6, 0xa4, 0xd9, 0x2b, 0xfa, 0x81, 0x95, 0xbc, 0xcf, 0x29, + 0x5f, 0x70, 0xcc, 0xb8, 0x1c, 0xef, 0xef, 0xaa, 0xf1, 0xfe, 0xc2, 0x1a, + 0x69, 0x19, 0x56, 0x35, 0x80, 0xee, 0xfe, 0x03, 0xc4, 0xab, 0x14, 0xfc, + 0x3a, 0xfc, 0x6f, 0x55, 0xee, 0x48, 0x5d, 0xac, 0x9e, 0xb7, 0xd7, 0x49, + 0xbe, 0xef, 0x8b, 0x1e, 0x66, 0x8f, 0x3d, 0x92, 0xb5, 0x8b, 0xb0, 0x0f, + 0xb7, 0x16, 0x39, 0x3e, 0x1d, 0x46, 0x14, 0xca, 0xbf, 0x0e, 0x59, 0x18, + 0xfc, 0x1b, 0xc8, 0x70, 0xcb, 0x69, 0x16, 0xb0, 0x74, 0xe0, 0xf0, 0x42, + 0x34, 0xa2, 0xea, 0x33, 0xd7, 0xd9, 0xec, 0xb7, 0x20, 0xd3, 0x51, 0x59, + 0x40, 0xfc, 0x50, 0x1a, 0x04, 0x8d, 0x7d, 0x9d, 0x18, 0x4f, 0xbb, 0x23, + 0xcf, 0x47, 0xe1, 0x7b, 0xc9, 0xd3, 0x28, 0xc6, 0xef, 0xc2, 0x98, 0x0e, + 0x5c, 0xbf, 0x68, 0x2c, 0x58, 0xcc, 0x9d, 0x7f, 0x0e, 0x6d, 0xce, 0x11, + 0xf4, 0x9d, 0x9f, 0x0e, 0x89, 0x9a, 0x93, 0xef, 0x74, 0x2a, 0xfb, 0xaf, + 0xaf, 0xc5, 0x75, 0xf8, 0xec, 0xbd, 0xea, 0x2d, 0xfd, 0x83, 0x81, 0xf5, + 0xda, 0x02, 0xeb, 0x0d, 0x06, 0xd6, 0x23, 0x9d, 0x1d, 0x01, 0x3a, 0x3b, + 0xf0, 0x7e, 0x0e, 0x6b, 0x0f, 0xab, 0x98, 0xa7, 0xbe, 0xe6, 0xfd, 0x81, + 0x35, 0xfd, 0xfd, 0x75, 0x06, 0xde, 0x7b, 0x07, 0xeb, 0xb1, 0x2f, 0x1a, + 0xe8, 0x23, 0x0d, 0xeb, 0xd1, 0xc7, 0x76, 0x47, 0x80, 0x2e, 0xd2, 0xba, + 0x16, 0xfd, 0x2a, 0x7e, 0x02, 0x9f, 0x5b, 0xe0, 0xb7, 0x74, 0xf8, 0x0e, + 0xd6, 0xa0, 0x1b, 0xf7, 0xfa, 0x65, 0xac, 0xeb, 0xcf, 0x17, 0xc5, 0x1c, + 0x1c, 0xcf, 0xb1, 0x86, 0xf7, 0x3e, 0xfb, 0xf9, 0xfc, 0x1b, 0xd5, 0xaf, + 0x2b, 0xbe, 0xad, 0x07, 0xed, 0xaa, 0xee, 0x22, 0xf3, 0x1d, 0x26, 0xe4, + 0xc9, 0xfc, 0x58, 0x93, 0x9b, 0x6c, 0x5d, 0xeb, 0xe9, 0xa7, 0xec, 0xd7, + 0x79, 0x58, 0xda, 0xa2, 0x65, 0x8f, 0xb3, 0x5e, 0xd0, 0xea, 0xe5, 0x7c, + 0xc8, 0x3d, 0x94, 0x8f, 0x31, 0xbd, 0xe7, 0xf4, 0x31, 0x8c, 0x5b, 0xe8, + 0x3f, 0x33, 0xde, 0x3d, 0xae, 0xd0, 0xe1, 0x7d, 0xa5, 0x0e, 0x39, 0xaf, + 0x78, 0x6a, 0xc9, 0xb9, 0x1a, 0x4f, 0x43, 0xde, 0xb7, 0x90, 0x83, 0xde, + 0x77, 0x06, 0x03, 0x71, 0x11, 0xee, 0xcb, 0x19, 0xd0, 0x10, 0x97, 0x9e, + 0x7e, 0xe6, 0x6e, 0x45, 0x5c, 0x59, 0xa7, 0xd0, 0x70, 0x75, 0xeb, 0x17, + 0x3d, 0xfd, 0xf0, 0x4b, 0xc0, 0xa1, 0x9e, 0xfe, 0xef, 0xa8, 0x7c, 0xae, + 0x54, 0xb1, 0xb4, 0x3b, 0x1c, 0xb7, 0x46, 0x74, 0xce, 0xbe, 0x5c, 0x8d, + 0x68, 0xa0, 0x99, 0x75, 0x0d, 0xbf, 0x46, 0x74, 0x4e, 0x54, 0x8d, 0xe8, + 0xe4, 0x15, 0x6a, 0x44, 0x99, 0xab, 0xaf, 0x11, 0x71, 0x7e, 0x53, 0xee, + 0x1e, 0x10, 0xed, 0x4b, 0x5e, 0x8d, 0xe8, 0x82, 0xb8, 0x35, 0xa2, 0xf3, + 0xb2, 0x7a, 0x8d, 0xe8, 0x68, 0x43, 0x8d, 0x68, 0xbd, 0xaa, 0x11, 0x71, + 0x1e, 0xb7, 0x46, 0xc4, 0x76, 0xbe, 0x7f, 0x30, 0x50, 0xeb, 0x00, 0xfe, + 0x3a, 0xb7, 0x82, 0x6f, 0x96, 0x36, 0xea, 0xf8, 0x98, 0x46, 0xec, 0xbf, + 0xbe, 0xe6, 0xbf, 0xea, 0xf8, 0xa6, 0x29, 0x9d, 0xbb, 0x12, 0xbe, 0x8d, + 0xba, 0x71, 0xc9, 0x32, 0x6c, 0x9b, 0xaa, 0xc5, 0x2e, 0xbf, 0xdc, 0xcc, + 0x1c, 0x7a, 0xb2, 0x5c, 0x9f, 0x77, 0x12, 0xf2, 0x1e, 0xab, 0xd5, 0x49, + 0x2e, 0x15, 0x1f, 0x45, 0xe5, 0xe0, 0xaa, 0xdf, 0x9a, 0x62, 0x99, 0x95, + 0xdf, 0x9a, 0x34, 0x89, 0x82, 0xce, 0x7c, 0x7f, 0x5e, 0xe5, 0x5d, 0x0b, + 0xce, 0xcf, 0xcb, 0xd2, 0xbd, 0x16, 0xf0, 0xc7, 0xaf, 0x9f, 0x50, 0xbe, + 0x75, 0x9f, 0x92, 0xd5, 0x3f, 0xba, 0x1a, 0xca, 0x3e, 0x55, 0x43, 0xf9, + 0x5a, 0x73, 0xb0, 0x86, 0x72, 0x4e, 0x2e, 0x5f, 0x43, 0xd9, 0xb7, 0x4a, + 0x0d, 0xe5, 0x15, 0xa9, 0xd7, 0x50, 0x5e, 0x11, 0xbf, 0x86, 0x62, 0xc8, + 0xd2, 0x7a, 0xce, 0xb3, 0x1f, 0xef, 0x8c, 0xe0, 0x37, 0x8c, 0x9f, 0x5b, + 0x53, 0x39, 0x57, 0xa3, 0x7f, 0xb5, 0x9a, 0xca, 0x37, 0x9b, 0xdf, 0x4f, + 0x4d, 0xc5, 0xf5, 0x01, 0x7e, 0x4d, 0xa5, 0x05, 0xf1, 0x0e, 0x7c, 0x8e, + 0x1e, 0xac, 0xa9, 0xfc, 0x2d, 0xed, 0x01, 0x7d, 0x2a, 0x46, 0x40, 0x3f, + 0xec, 0x02, 0x7e, 0x29, 0xa3, 0x6a, 0x1c, 0x9f, 0xf6, 0x78, 0xb8, 0x1b, + 0x7b, 0x8e, 0x43, 0x16, 0xe4, 0x63, 0x8f, 0x8a, 0x2d, 0x33, 0x66, 0x4c, + 0xcb, 0xf6, 0xc2, 0x9b, 0x4d, 0xf3, 0x5b, 0x74, 0x4c, 0xc6, 0x2b, 0xd4, + 0xf1, 0x2e, 0xc4, 0xe2, 0x26, 0xfa, 0x76, 0xa3, 0xed, 0xc7, 0x54, 0xfd, + 0xb5, 0x39, 0x68, 0x9b, 0x0b, 0xc0, 0x59, 0xe0, 0xc4, 0x55, 0xf8, 0xa8, + 0x6d, 0xa0, 0x39, 0xb8, 0x8f, 0x22, 0xfc, 0x13, 0xfa, 0x94, 0xcc, 0x19, + 0x5b, 0xfa, 0xb4, 0xc4, 0x69, 0xe7, 0x57, 0x31, 0x1f, 0xfb, 0xb6, 0xa9, + 0x7c, 0xac, 0x30, 0xc0, 0xbd, 0xd2, 0xd7, 0x2d, 0x82, 0x3e, 0xf4, 0x95, + 0x98, 0x03, 0xd2, 0xef, 0xf9, 0x39, 0x5a, 0x44, 0xe5, 0x68, 0x9d, 0x8a, + 0x1f, 0xe4, 0xf5, 0x8d, 0x61, 0x62, 0x65, 0xa7, 0xcd, 0x3d, 0x0c, 0x7b, + 0x58, 0xc7, 0xb6, 0x9b, 0x0b, 0x66, 0x74, 0xde, 0x3f, 0x02, 0xb9, 0xb2, + 0x4e, 0xe3, 0xcb, 0xef, 0x21, 0x6f, 0xdf, 0x83, 0x52, 0xec, 0x94, 0xf0, + 0x7a, 0xd0, 0x93, 0x9f, 0x61, 0xdc, 0xfd, 0x09, 0x95, 0x83, 0x44, 0xed, + 0x4b, 0xdb, 0xed, 0x5d, 0xd7, 0x60, 0xb7, 0x23, 0x97, 0xb5, 0xdb, 0xcf, + 0x85, 0x83, 0x76, 0x7b, 0xd7, 0x35, 0xd8, 0xed, 0xfe, 0x6b, 0xb2, 0x5b, + 0xee, 0x8d, 0x98, 0xe4, 0xd7, 0xc4, 0x56, 0xc6, 0x59, 0xfe, 0xba, 0x13, + 0x58, 0x33, 0x73, 0x89, 0x35, 0xc7, 0x2e, 0x59, 0x5b, 0x6d, 0x8c, 0xb1, + 0xae, 0x46, 0xde, 0xcc, 0xad, 0xe8, 0x6f, 0x23, 0x9e, 0x5f, 0xba, 0xdd, + 0xcb, 0xe7, 0xfd, 0xbc, 0x3e, 0x68, 0x3f, 0xd4, 0x0b, 0xea, 0xc2, 0x63, + 0xe0, 0x17, 0xf5, 0xc1, 0xb7, 0xb9, 0x9e, 0x06, 0x1d, 0x5c, 0x44, 0xbe, + 0xdf, 0xe3, 0xe9, 0x20, 0x65, 0xdd, 0xab, 0xbe, 0x11, 0x95, 0x9c, 0x47, + 0xdc, 0x3c, 0x1f, 0x3a, 0x90, 0x2f, 0xf9, 0xb6, 0x06, 0x9e, 0x44, 0xfd, + 0x67, 0xe4, 0xa3, 0x8d, 0x98, 0x67, 0x0b, 0xe2, 0x35, 0xf0, 0x48, 0xf5, + 0x2f, 0xaf, 0x09, 0x5f, 0x1e, 0xcf, 0xa4, 0x18, 0xc2, 0xd8, 0x53, 0x03, + 0xb0, 0xf1, 0x01, 0x62, 0x54, 0x1a, 0x79, 0x0f, 0xf5, 0x90, 0xba, 0xb9, + 0x29, 0xb9, 0x43, 0x67, 0x4c, 0xb5, 0x07, 0xb6, 0x47, 0x7d, 0x8d, 0xcb, + 0x8e, 0xca, 0xa6, 0x33, 0xe7, 0x74, 0xae, 0x51, 0xad, 0xe6, 0x99, 0x2b, + 0x5a, 0xa2, 0x77, 0xf7, 0xff, 0x45, 0x98, 0x7e, 0xe9, 0x7a, 0xdb, 0xf0, + 0x74, 0x2d, 0x83, 0x7b, 0xea, 0xed, 0xeb, 0xf0, 0xf7, 0xfc, 0xc6, 0xfe, + 0x03, 0xf4, 0xc7, 0x60, 0xf3, 0xf4, 0xef, 0xcc, 0x47, 0xb6, 0x7a, 0xe3, + 0x7a, 0xd4, 0xf7, 0xcf, 0x6c, 0xea, 0x56, 0xef, 0xbb, 0x13, 0xfd, 0x4f, + 0x82, 0x3e, 0x7b, 0x99, 0x9c, 0x79, 0x46, 0x21, 0xa7, 0xf2, 0x19, 0xbe, + 0xaf, 0x74, 0x12, 0x39, 0x88, 0x19, 0xa8, 0xa5, 0x87, 0xbd, 0xdc, 0x8d, + 0x36, 0x16, 0x81, 0x0c, 0xb7, 0x7b, 0xb9, 0x0a, 0xf3, 0xd7, 0xe5, 0x67, + 0x13, 0x56, 0xd7, 0x81, 0x0d, 0xef, 0x43, 0x07, 0x1a, 0xe5, 0x17, 0x86, + 0xed, 0xfb, 0xf2, 0xf3, 0xe3, 0x98, 0x79, 0x6f, 0xdf, 0x3d, 0xae, 0x0c, + 0x7f, 0x2c, 0xf6, 0xa9, 0x05, 0xf6, 0xe9, 0xe3, 0xd1, 0x3e, 0x6f, 0x9f, + 0x5b, 0x1b, 0xf0, 0x68, 0xa4, 0xc1, 0x66, 0x3f, 0x4a, 0x3c, 0x3a, 0xb4, + 0xe6, 0xa3, 0xc7, 0x23, 0xee, 0x6b, 0xe3, 0xaa, 0x38, 0xe4, 0xee, 0xe3, + 0x77, 0x45, 0x4f, 0x7f, 0x98, 0xf9, 0xde, 0xfb, 0x91, 0x4f, 0x10, 0x47, + 0x28, 0x93, 0x36, 0x15, 0xc3, 0xba, 0xb6, 0x07, 0x5f, 0x5e, 0x0a, 0xc9, + 0x1b, 0xf7, 0x84, 0xe5, 0x7f, 0x6f, 0xe3, 0xf7, 0x30, 0xd3, 0xab, 0x69, + 0xb1, 0xfd, 0xc2, 0x1a, 0xd7, 0x0f, 0xbd, 0xd0, 0xee, 0xfa, 0x1d, 0xbe, + 0xe3, 0xdb, 0xb3, 0x85, 0xe7, 0x7c, 0xb6, 0x91, 0x5f, 0x4c, 0xae, 0x21, + 0x07, 0xdc, 0x64, 0x5d, 0xd0, 0x57, 0xcb, 0x01, 0x2f, 0x5f, 0x0f, 0xac, + 0xe7, 0x80, 0xc4, 0xd9, 0x0e, 0xa5, 0x1b, 0xf9, 0x28, 0x73, 0x1f, 0xc3, + 0xc3, 0x4e, 0xde, 0x23, 0xb7, 0x75, 0x90, 0xef, 0x42, 0xb6, 0xcf, 0x21, + 0x5e, 0x7a, 0xd6, 0x41, 0x8e, 0xeb, 0x20, 0xb7, 0x75, 0x90, 0xdb, 0x3a, + 0xc8, 0x6d, 0x9d, 0xa4, 0x97, 0x23, 0x8f, 0x78, 0x75, 0x7f, 0x7e, 0xe3, + 0x66, 0x7d, 0xa1, 0x08, 0x5f, 0x32, 0xc5, 0x73, 0x13, 0x7a, 0x36, 0xb5, + 0xc6, 0xdb, 0x9f, 0x5f, 0x13, 0xef, 0xf2, 0x6a, 0x36, 0xdf, 0x54, 0x75, + 0x43, 0xd1, 0x1f, 0x68, 0x71, 0xbf, 0x83, 0xf3, 0x7c, 0xc7, 0xaf, 0x21, + 0x2e, 0x51, 0x67, 0x88, 0x68, 0xa3, 0x55, 0x3d, 0xcd, 0x9a, 0x8c, 0xe8, + 0x7a, 0xfa, 0x16, 0xbc, 0xb3, 0xc5, 0xcd, 0x09, 0xa2, 0x62, 0xe8, 0xe9, + 0x56, 0xf2, 0x54, 0xd3, 0xd3, 0x6b, 0xbd, 0xb9, 0xf6, 0xb7, 0xb8, 0xb1, + 0x55, 0x2f, 0xdb, 0xa6, 0xce, 0x38, 0x41, 0xc5, 0xda, 0x7e, 0xff, 0xc5, + 0xf6, 0xe5, 0x6b, 0x85, 0x14, 0xbe, 0x67, 0x53, 0xf7, 0x62, 0x3e, 0xb6, + 0xeb, 0xfc, 0xd6, 0x2f, 0xc9, 0xef, 0x90, 0xc7, 0x6f, 0x97, 0xc7, 0x06, + 0xc7, 0xa9, 0xba, 0x30, 0x79, 0xed, 0xcf, 0xa7, 0xea, 0x7a, 0x58, 0x47, + 0x9d, 0xcd, 0xc0, 0xf5, 0x07, 0xa6, 0xb4, 0x8d, 0xee, 0x0e, 0xd9, 0xc1, + 0x75, 0xfd, 0x6f, 0xe2, 0x57, 0xb3, 0x66, 0x8f, 0xfa, 0x8e, 0xe6, 0xfa, + 0x8c, 0x90, 0xd2, 0x41, 0x33, 0xcd, 0x7d, 0xfd, 0x50, 0x9d, 0xa9, 0xa1, + 0xfe, 0xe5, 0x90, 0xc7, 0x4c, 0x0d, 0x6c, 0x8a, 0x9b, 0xfa, 0x48, 0x0b, + 0xeb, 0xaf, 0x43, 0x15, 0x1f, 0xf7, 0xb8, 0x5e, 0xa3, 0x1f, 0x67, 0x5d, + 0xcd, 0xc7, 0x33, 0xd9, 0xe0, 0xd6, 0xdb, 0x3e, 0x88, 0x2d, 0xb5, 0x34, + 0xd8, 0x92, 0xbf, 0x4f, 0xee, 0x9f, 0xd7, 0xd5, 0xcf, 0x43, 0x2c, 0x56, + 0x02, 0xdf, 0x47, 0x6a, 0xba, 0xc1, 0xb3, 0x2a, 0x9f, 0x85, 0x0e, 0xf2, + 0xdb, 0xc0, 0x4e, 0xd8, 0x51, 0xb5, 0x3a, 0xc4, 0x1a, 0x73, 0xdf, 0x67, + 0x54, 0x7e, 0xa9, 0xa7, 0xe7, 0x55, 0xfd, 0xc1, 0x5c, 0x51, 0x7f, 0x18, + 0x82, 0xae, 0x20, 0x06, 0x70, 0xda, 0x54, 0x4c, 0xa7, 0xe2, 0x85, 0x4a, + 0xe3, 0xf7, 0x97, 0xfb, 0x5b, 0x5d, 0x3e, 0xfc, 0x5d, 0x8b, 0xfb, 0x0d, + 0xe2, 0x8f, 0xa2, 0xcb, 0xdb, 0x7c, 0xff, 0xaf, 0x5b, 0xfc, 0xb3, 0x3b, + 0x85, 0x13, 0x43, 0xd0, 0x45, 0xe4, 0xe4, 0x6a, 0x3e, 0xc4, 0xbb, 0x4f, + 0xcc, 0x76, 0x2c, 0x1f, 0x8f, 0xbe, 0x13, 0xfe, 0xf8, 0x8e, 0x86, 0xf1, + 0x1d, 0x18, 0xff, 0x7b, 0x0d, 0xe3, 0x3b, 0x02, 0xe3, 0xa3, 0x0d, 0xe3, + 0xa3, 0x18, 0xff, 0x7c, 0xc3, 0xf8, 0x68, 0x60, 0x7c, 0x67, 0xc3, 0xf8, + 0x4e, 0x8c, 0x7f, 0xa1, 0x61, 0x3c, 0xfa, 0x4e, 0x34, 0x79, 0xdf, 0xc5, + 0x88, 0xb1, 0xfb, 0xbd, 0x5c, 0x1c, 0xd7, 0x72, 0xe3, 0xb7, 0x16, 0xea, + 0x5d, 0x17, 0x64, 0xe0, 0x9f, 0xa7, 0xa3, 0xbd, 0x66, 0x60, 0xaf, 0xf5, + 0x58, 0xc6, 0xd5, 0xc7, 0xa0, 0x2e, 0x12, 0x1f, 0x8a, 0x62, 0xd8, 0xd0, + 0x9d, 0x12, 0x74, 0xa8, 0xe4, 0xfb, 0x24, 0x9e, 0x83, 0xe2, 0x19, 0x53, + 0xd7, 0xf7, 0x86, 0xec, 0x45, 0x2f, 0x07, 0x7b, 0x9b, 0xb4, 0x03, 0x2f, + 0x7d, 0xcc, 0x94, 0x63, 0xae, 0xdd, 0x50, 0x7f, 0x39, 0xbf, 0x67, 0x3f, + 0xd4, 0x55, 0x6f, 0x9d, 0xa1, 0x15, 0xb8, 0x16, 0x5f, 0x51, 0xdb, 0x32, + 0xae, 0x02, 0xd7, 0x46, 0x6a, 0xb8, 0xf6, 0x59, 0x99, 0xaf, 0xe5, 0xdb, + 0xc3, 0x72, 0xc0, 0xd9, 0xc5, 0x33, 0x36, 0xc7, 0x32, 0xf2, 0xe1, 0xe4, + 0xdb, 0xbb, 0x6a, 0x7e, 0x92, 0x67, 0x3a, 0x96, 0x0e, 0x31, 0x87, 0xf2, + 0x6b, 0xb3, 0x53, 0xce, 0xcf, 0xb6, 0x42, 0x2e, 0xb0, 0x8d, 0x6b, 0xcd, + 0xb7, 0x39, 0x5f, 0x54, 0x0e, 0xb8, 0xe7, 0x1d, 0x6a, 0xf3, 0x16, 0x6b, + 0xf3, 0xc6, 0x3c, 0x7b, 0xa3, 0x0f, 0xae, 0xfb, 0xcb, 0x1c, 0xfc, 0xe5, + 0x18, 0x72, 0xee, 0x45, 0x67, 0xb5, 0xfa, 0xe8, 0xb5, 0xfa, 0xcb, 0xc6, + 0x3a, 0x73, 0xa3, 0xbf, 0xe4, 0x3a, 0x8d, 0xb5, 0xe5, 0x78, 0x03, 0xfe, + 0x53, 0x9f, 0x0e, 0x7b, 0x31, 0x35, 0xae, 0xa5, 0xc3, 0xb0, 0x47, 0x5d, + 0xc6, 0x94, 0xfe, 0xb2, 0xed, 0xe7, 0x96, 0xbb, 0x6b, 0xb9, 0x65, 0x3d, + 0x1f, 0x44, 0xec, 0x9a, 0xfc, 0xa4, 0x87, 0x8f, 0x8c, 0x91, 0xa7, 0xd0, + 0x7f, 0x0c, 0x3a, 0xc0, 0x67, 0xac, 0x97, 0xde, 0x2c, 0x9f, 0x32, 0x5d, + 0xff, 0xe4, 0xd6, 0xa6, 0x76, 0xab, 0xf8, 0x9f, 0xdf, 0x0b, 0x0a, 0xa9, + 0x76, 0x2f, 0xde, 0xbb, 0x12, 0xae, 0x2e, 0xcf, 0x4d, 0x75, 0xfd, 0x51, + 0xbc, 0xcb, 0xdc, 0xd4, 0x8c, 0x10, 0x43, 0xb3, 0x95, 0xcb, 0xbe, 0x5f, + 0xa4, 0x7f, 0x29, 0xa8, 0xef, 0x82, 0x2a, 0x0f, 0xc5, 0xb8, 0x45, 0xef, + 0x7d, 0x37, 0x0f, 0xcd, 0x56, 0xbe, 0xdd, 0xea, 0xe2, 0xe0, 0xe5, 0x72, + 0x96, 0x9f, 0x88, 0xb0, 0xae, 0xb7, 0xe8, 0x5c, 0x89, 0xd6, 0x95, 0x79, + 0xaf, 0xb1, 0x22, 0xef, 0x1d, 0xf5, 0xf2, 0xda, 0xcf, 0xa9, 0xbc, 0xd7, + 0xe5, 0x31, 0xf7, 0x12, 0xcc, 0xa3, 0x6c, 0x60, 0x21, 0xbf, 0xa9, 0x10, + 0x1f, 0x26, 0x94, 0xdf, 0xca, 0x4f, 0xdf, 0x09, 0x3e, 0x47, 0x57, 0xd1, + 0x9b, 0x8f, 0xda, 0x4f, 0xf8, 0x7b, 0x3f, 0x2c, 0x6e, 0xbd, 0x6e, 0x27, + 0x68, 0x61, 0x6e, 0x15, 0xf2, 0xf4, 0xe1, 0xbb, 0xde, 0x39, 0x53, 0x7f, + 0x9c, 0x9f, 0xc7, 0xd7, 0xbe, 0xbb, 0x16, 0x33, 0xcb, 0xea, 0x27, 0x1b, + 0x09, 0xc3, 0x90, 0x7b, 0xe6, 0x1a, 0xbe, 0x5b, 0x7c, 0x90, 0xf3, 0x11, + 0x8d, 0x7e, 0x8d, 0xdf, 0x4d, 0xf9, 0xad, 0x54, 0xb4, 0xbb, 0x7b, 0x6d, + 0xd8, 0x00, 0xcf, 0x2c, 0x07, 0xf1, 0x35, 0x2c, 0xf9, 0x39, 0x09, 0x47, + 0xd3, 0xfc, 0x06, 0x40, 0xff, 0xff, 0xba, 0xb7, 0xcf, 0x98, 0xec, 0x9f, + 0x71, 0x6b, 0x9e, 0xfa, 0x65, 0xcf, 0xc5, 0x1d, 0x00, 0x1f, 0x12, 0x47, + 0xfd, 0x9a, 0xa7, 0xee, 0x9e, 0x8b, 0x3b, 0xfa, 0xe1, 0x9d, 0x8b, 0xe3, + 0xfc, 0xa6, 0xec, 0x5a, 0xe5, 0x5c, 0x9c, 0x71, 0x95, 0xe7, 0xe2, 0xda, + 0x55, 0xcd, 0x93, 0xf3, 0xb8, 0x35, 0x4f, 0xb6, 0xbb, 0xfb, 0x59, 0x2b, + 0xe1, 0xd9, 0xb7, 0x01, 0x75, 0x06, 0xb9, 0xbb, 0xff, 0x47, 0x91, 0xa3, + 0x7c, 0x3d, 0xf2, 0xd1, 0xe7, 0x28, 0xdc, 0xcb, 0xaf, 0xb8, 0xdf, 0x77, + 0xe5, 0x5a, 0xea, 0x00, 0x1f, 0xac, 0xae, 0xb9, 0x5f, 0xd5, 0x35, 0xbf, + 0x13, 0x09, 0xd6, 0x35, 0xf5, 0x2b, 0x9c, 0x0d, 0xdb, 0xbf, 0x4a, 0x5d, + 0x33, 0x14, 0x38, 0x1b, 0x16, 0xf2, 0xce, 0x86, 0xb5, 0xdb, 0xc8, 0x25, + 0xbd, 0x3a, 0xa6, 0x7e, 0xd9, 0xb3, 0x61, 0xff, 0x19, 0xf9, 0xe0, 0x75, + 0xcc, 0x15, 0x67, 0xc3, 0xe0, 0xeb, 0x36, 0x48, 0xfc, 0x9a, 0xf2, 0x9e, + 0x0f, 0x92, 0xf3, 0xf0, 0xbc, 0x7e, 0x13, 0xf6, 0x1c, 0x92, 0x5d, 0x51, + 0xea, 0x27, 0xcf, 0x36, 0xf6, 0xc2, 0x16, 0x70, 0xad, 0xb0, 0x9d, 0xa4, + 0x8c, 0xb4, 0x91, 0xde, 0xe5, 0xe7, 0x10, 0xea, 0xe7, 0x71, 0xc3, 0xb5, + 0xf3, 0xb8, 0x47, 0xa0, 0x37, 0xfa, 0x4c, 0x58, 0x16, 0x02, 0x3a, 0x35, + 0x85, 0x78, 0x4f, 0x9f, 0xb3, 0xbc, 0xe7, 0xfc, 0x9f, 0x8a, 0x28, 0x30, + 0x8f, 0x67, 0x78, 0xdb, 0xc4, 0x98, 0x73, 0xbf, 0x59, 0xba, 0xff, 0x57, + 0x12, 0xc3, 0x18, 0x9e, 0xf1, 0x0c, 0xc9, 0x01, 0x55, 0xb3, 0xf0, 0x75, + 0x79, 0xc7, 0x5a, 0x69, 0x59, 0x9f, 0xa9, 0xb7, 0xa3, 0xab, 0xf8, 0x7d, + 0xc4, 0x91, 0x33, 0xd4, 0xe7, 0x5b, 0x25, 0xe7, 0xd5, 0x83, 0x0a, 0x95, + 0x6d, 0x5e, 0x7e, 0xa1, 0xbe, 0xed, 0x80, 0x97, 0xdd, 0x9e, 0x0f, 0xc6, + 0xb5, 0xd4, 0x4d, 0x9f, 0x87, 0x35, 0x4e, 0xca, 0xd0, 0xf4, 0x96, 0xd8, + 0x38, 0xf0, 0x6e, 0x4c, 0xad, 0x79, 0x2d, 0x3c, 0xd7, 0x2e, 0xf1, 0xbd, + 0xf1, 0x6a, 0xf9, 0xee, 0xc7, 0xc7, 0x8f, 0x62, 0x7f, 0xdd, 0xd0, 0x8f, + 0x87, 0x25, 0x77, 0xe2, 0x66, 0x19, 0x9a, 0x4d, 0x80, 0x9e, 0x1f, 0x56, + 0x0b, 0x29, 0xc4, 0xd2, 0x4f, 0xf0, 0xdc, 0x18, 0x30, 0x14, 0x7c, 0x7b, + 0x66, 0xc5, 0x77, 0xec, 0xe0, 0x59, 0xb3, 0x64, 0xed, 0xec, 0xd0, 0x53, + 0x15, 0x09, 0x77, 0x90, 0xe6, 0x99, 0xfa, 0xd9, 0xef, 0xc5, 0xca, 0x0e, + 0xe5, 0xdb, 0x9e, 0xac, 0x2c, 0xab, 0xfd, 0x28, 0x19, 0x4e, 0x94, 0x9f, + 0x04, 0x2f, 0x5e, 0x51, 0xfe, 0xed, 0x88, 0x23, 0x37, 0x19, 0x42, 0x79, + 0x88, 0x06, 0x1e, 0xa8, 0x33, 0x1c, 0xee, 0xf7, 0xfd, 0x2e, 0x25, 0x57, + 0x17, 0x2b, 0x76, 0x06, 0xce, 0x60, 0xd4, 0x65, 0xeb, 0x9e, 0xcd, 0x70, + 0x65, 0xe1, 0x9e, 0x1f, 0x21, 0x3f, 0x97, 0x0e, 0xed, 0xb2, 0xdd, 0xf3, + 0x23, 0x3d, 0x73, 0xec, 0xeb, 0x6c, 0xf0, 0x7d, 0x61, 0xe8, 0x00, 0xcf, + 0x1d, 0xf1, 0xcc, 0x37, 0x69, 0x56, 0xb5, 0x8e, 0x55, 0xbf, 0x6d, 0x5f, + 0x5b, 0xcd, 0xd5, 0x5d, 0xb3, 0x5b, 0xad, 0x79, 0x9d, 0x87, 0x59, 0xfe, + 0x59, 0xef, 0x94, 0xf6, 0xff, 0xd4, 0x5d, 0x7b, 0x6c, 0x1b, 0xf7, 0x7d, + 0xff, 0xf2, 0x48, 0x3d, 0xac, 0xe7, 0x49, 0xa6, 0x64, 0x5a, 0x52, 0x94, + 0x3b, 0xe9, 0x64, 0x29, 0xb1, 0x12, 0x70, 0x9e, 0xba, 0x0a, 0x88, 0x9a, + 0xb0, 0x24, 0xfd, 0x58, 0x10, 0x0c, 0xb4, 0xad, 0x64, 0xee, 0x92, 0xad, + 0x0e, 0x25, 0xa7, 0x1d, 0x30, 0x60, 0x6e, 0xd6, 0x02, 0x69, 0x07, 0xc7, + 0x0c, 0x65, 0x27, 0xc6, 0xaa, 0x88, 0x4c, 0xcc, 0x6a, 0x1d, 0xb0, 0x62, + 0x1c, 0xa5, 0x38, 0x69, 0xa7, 0x80, 0x69, 0xda, 0x04, 0xc5, 0xfe, 0xb1, + 0x26, 0x3b, 0x7b, 0x61, 0x7f, 0x04, 0xdb, 0x80, 0x1a, 0x5b, 0x81, 0xba, + 0x76, 0x8a, 0x65, 0x1b, 0xe0, 0x34, 0xdb, 0xb0, 0x75, 0x58, 0x0b, 0xee, + 0xfb, 0xf9, 0x3d, 0xc8, 0x23, 0x79, 0xd4, 0xc3, 0x71, 0x06, 0x4c, 0x80, + 0x40, 0xde, 0xf1, 0x77, 0x77, 0xbf, 0xdf, 0xf7, 0xf7, 0x7d, 0xbf, 0x6e, + 0x2e, 0x33, 0x1e, 0xf2, 0x33, 0x7e, 0xcf, 0x15, 0x61, 0x5f, 0x37, 0xd2, + 0xe1, 0x36, 0x83, 0x67, 0xa4, 0x0e, 0x9e, 0xd5, 0x34, 0xc1, 0xf6, 0x78, + 0x99, 0x77, 0x4b, 0xd8, 0xc9, 0xf3, 0xc8, 0x63, 0xd7, 0x39, 0x0e, 0x12, + 0x76, 0x65, 0x1a, 0x5a, 0x72, 0xe7, 0x37, 0x54, 0x60, 0x77, 0xb2, 0x0c, + 0xbb, 0x3d, 0xff, 0x8f, 0x60, 0x77, 0x4d, 0xe8, 0xbf, 0xdf, 0x2e, 0x22, + 0x6f, 0x4d, 0xeb, 0x00, 0xba, 0x6e, 0x09, 0x70, 0x04, 0x3f, 0xb5, 0xf3, + 0xeb, 0x04, 0x9e, 0x8a, 0xbc, 0xe2, 0x52, 0xe9, 0x3b, 0xe1, 0xb2, 0x9f, + 0x92, 0xed, 0x12, 0xd8, 0x27, 0xf0, 0xe7, 0x35, 0x96, 0x91, 0x47, 0x6f, + 0x4b, 0x46, 0x42, 0x57, 0xaa, 0xb5, 0x4f, 0x7e, 0xbb, 0xcb, 0x6d, 0x9f, + 0x1c, 0xdd, 0xa1, 0x7d, 0x72, 0x5a, 0xda, 0x27, 0xa9, 0xed, 0xdb, 0x27, + 0x03, 0x75, 0x79, 0x5d, 0x95, 0xf5, 0xec, 0xdc, 0x3e, 0x31, 0x36, 0xb5, + 0x4f, 0x46, 0x5d, 0xbe, 0x18, 0xcc, 0xf7, 0x57, 0x29, 0x75, 0x0c, 0x3c, + 0x4e, 0xc3, 0x19, 0x30, 0x3e, 0x56, 0xe3, 0x17, 0xfe, 0x38, 0x61, 0xfd, + 0xd7, 0xff, 0xc7, 0xb0, 0x1e, 0xac, 0xf3, 0x79, 0x57, 0xd6, 0x03, 0x21, + 0xfe, 0x51, 0x60, 0x3d, 0xd8, 0xd0, 0x77, 0xda, 0x38, 0x67, 0xb1, 0xda, + 0x77, 0x3a, 0x62, 0x34, 0xe2, 0xed, 0x7f, 0xe4, 0xf2, 0xa9, 0xba, 0xf9, + 0x3b, 0x68, 0x8a, 0x7c, 0x47, 0xc7, 0xf5, 0xb3, 0x40, 0x4b, 0x76, 0x2a, + 0x45, 0xb0, 0x99, 0xf0, 0xbc, 0x90, 0xa0, 0xb5, 0x1a, 0x7d, 0x8b, 0x9f, + 0xc7, 0xeb, 0x7b, 0xf5, 0x09, 0x21, 0xa7, 0xa4, 0xff, 0x01, 0xe3, 0x27, + 0x7c, 0xf3, 0x62, 0xac, 0xcc, 0x6f, 0x52, 0xfe, 0x08, 0xa5, 0xfb, 0x37, + 0xf2, 0x43, 0xd4, 0xcb, 0xbc, 0x9d, 0xd9, 0x0a, 0x9a, 0xc6, 0xef, 0xe6, + 0x7d, 0x09, 0x55, 0xd9, 0x5a, 0xe0, 0x9f, 0xa7, 0x59, 0x2f, 0x18, 0x29, + 0xeb, 0x04, 0xd5, 0x7b, 0x73, 0x4e, 0xd8, 0x74, 0x9a, 0x77, 0x26, 0x64, + 0xee, 0xa9, 0x38, 0x0f, 0x3d, 0x4d, 0xf3, 0xce, 0x5a, 0x3d, 0xf8, 0x6e, + 0x0f, 0xbc, 0xf0, 0xca, 0x69, 0x2a, 0xef, 0x9d, 0x85, 0x9c, 0xf3, 0xb8, + 0xe7, 0xde, 0x95, 0x6b, 0xc2, 0x52, 0x95, 0xb1, 0xf2, 0xfa, 0xb8, 0x58, + 0xd7, 0x0f, 0x8e, 0x44, 0x51, 0xfb, 0x56, 0xae, 0x17, 0xab, 0xad, 0x77, + 0x82, 0x1c, 0xd0, 0x74, 0xa8, 0x6b, 0xa2, 0x01, 0x8b, 0x61, 0x8f, 0x7a, + 0x27, 0xb7, 0x2c, 0xc1, 0x75, 0xb5, 0xb0, 0xa8, 0xc8, 0x91, 0xf3, 0x4a, + 0x8e, 0x14, 0x5c, 0x7c, 0xbc, 0x5e, 0x6f, 0xef, 0xf5, 0xd0, 0xdb, 0xbd, + 0x6a, 0x9e, 0x30, 0xa7, 0x67, 0x58, 0x0f, 0xb9, 0x1f, 0x7a, 0x88, 0x89, + 0xba, 0x25, 0xa9, 0x8b, 0xe0, 0x77, 0x96, 0x35, 0xaf, 0x86, 0x18, 0x57, + 0x8e, 0xd0, 0x53, 0xac, 0x6b, 0x5f, 0xa2, 0x7b, 0x94, 0x7d, 0x16, 0x71, + 0xe5, 0x99, 0x22, 0x8f, 0xdf, 0x47, 0xa9, 0x27, 0xec, 0x89, 0x08, 0x1d, + 0xa1, 0x53, 0x22, 0x67, 0x06, 0xf1, 0x3d, 0xe4, 0x1c, 0xdc, 0x2b, 0x9e, + 0x2f, 0x7d, 0x19, 0x77, 0x22, 0xa7, 0x6e, 0xfb, 0xf9, 0xfb, 0xba, 0x56, + 0x2f, 0x2a, 0x9e, 0xb9, 0xaa, 0x68, 0x4a, 0x9c, 0xe3, 0xeb, 0x9f, 0x31, + 0xea, 0xaf, 0x8f, 0x18, 0xf1, 0x62, 0xdc, 0x88, 0xae, 0x60, 0xdc, 0x33, + 0x46, 0xac, 0x08, 0x1b, 0x52, 0xe3, 0x88, 0x1d, 0x06, 0xbd, 0x6d, 0xd0, + 0xd6, 0xb1, 0x88, 0x02, 0xd5, 0xd4, 0x49, 0x6c, 0x63, 0xde, 0x87, 0xaa, + 0xe6, 0xad, 0xe1, 0x8b, 0xef, 0xf0, 0xf7, 0x44, 0x18, 0xa6, 0x5a, 0xaf, + 0x6d, 0x83, 0x7f, 0x7d, 0x22, 0x45, 0x9b, 0xe9, 0xb5, 0x76, 0x9d, 0x5e, + 0x5b, 0xd8, 0x72, 0xde, 0x1f, 0x95, 0xc6, 0x65, 0x3d, 0xa2, 0xdf, 0x11, + 0xfa, 0x2b, 0xcf, 0xbb, 0x4a, 0xb7, 0xad, 0xc1, 0x29, 0x8c, 0xd1, 0x7e, + 0x70, 0xed, 0x07, 0xeb, 0x52, 0xf9, 0xc0, 0x3a, 0x3f, 0xa1, 0x0d, 0xf5, + 0x5e, 0xa6, 0xcc, 0x6b, 0x85, 0x8d, 0xb5, 0xce, 0xf3, 0x83, 0xbd, 0xf5, + 0xa0, 0x98, 0x23, 0xdb, 0x5b, 0x56, 0x8c, 0xa4, 0xaf, 0x7b, 0xbe, 0x58, + 0x55, 0xff, 0xe9, 0x51, 0x07, 0x39, 0xe2, 0x51, 0x07, 0xe9, 0xa6, 0xb5, + 0x80, 0x8b, 0xd6, 0x42, 0x2e, 0xbd, 0x6d, 0x88, 0xed, 0x96, 0x0e, 0xe6, + 0x21, 0xb0, 0x5b, 0xda, 0xc8, 0xff, 0xb2, 0xdb, 0x6e, 0xa9, 0xad, 0x45, + 0x07, 0xdd, 0x41, 0x37, 0x93, 0x36, 0x4c, 0x3c, 0x57, 0xae, 0x63, 0xe7, + 0x75, 0x57, 0x6a, 0x0e, 0x57, 0xea, 0xea, 0x23, 0xbd, 0xe6, 0x3b, 0x5c, + 0x37, 0x5f, 0xc8, 0xaf, 0x48, 0x43, 0x9d, 0xce, 0xcb, 0xae, 0xba, 0x53, + 0xf3, 0xab, 0xe5, 0x67, 0x78, 0xd6, 0x88, 0xf0, 0x79, 0xa7, 0xca, 0xbc, + 0x6c, 0x5a, 0xce, 0x37, 0x53, 0x6d, 0x67, 0xf8, 0x97, 0x48, 0xc1, 0xce, + 0x9b, 0xb7, 0xef, 0xcc, 0x7f, 0xd6, 0x5e, 0x23, 0x77, 0xdf, 0x33, 0xa5, + 0x5f, 0xac, 0x49, 0xe5, 0x61, 0xf7, 0x29, 0x7b, 0x6f, 0x2b, 0x7c, 0xc7, + 0xb9, 0x26, 0xe5, 0x4b, 0xb4, 0xad, 0x3c, 0x01, 0xcf, 0x8f, 0x9d, 0x68, + 0x72, 0x4c, 0x15, 0xcb, 0x42, 0xbc, 0x0a, 0x78, 0xaf, 0xef, 0x0f, 0x9e, + 0xbd, 0x9d, 0x3d, 0xb3, 0xea, 0xf6, 0x4c, 0xe2, 0x15, 0x6c, 0x2d, 0xe4, + 0x17, 0x4f, 0xd6, 0xe4, 0x78, 0x7f, 0x14, 0x58, 0x74, 0x79, 0xe4, 0x3d, + 0x23, 0x6f, 0xb9, 0xd1, 0x3c, 0xaf, 0xbb, 0xf4, 0x72, 0xcc, 0xb7, 0x54, + 0x7a, 0x23, 0x3c, 0x20, 0x65, 0x71, 0xd1, 0x5b, 0x47, 0x32, 0xb7, 0x3d, + 0xbf, 0x5a, 0xd9, 0xbb, 0x77, 0x9b, 0xb2, 0x57, 0xf4, 0xf4, 0xf0, 0x1d, + 0x14, 0x3c, 0xa0, 0x83, 0x56, 0x72, 0xc8, 0xbf, 0xfe, 0x05, 0xd0, 0x3c, + 0xf3, 0x59, 0x57, 0x4d, 0x9a, 0xf7, 0x3e, 0x96, 0x63, 0x2a, 0x81, 0x19, + 0xc4, 0xfe, 0x90, 0x5b, 0xd2, 0xcb, 0xbc, 0x07, 0xe3, 0xc7, 0xac, 0xab, + 0xf0, 0xf7, 0x2a, 0xff, 0x53, 0x5c, 0xc9, 0x97, 0x83, 0xdb, 0x88, 0xad, + 0xec, 0x8c, 0x4f, 0xdb, 0xd6, 0x3a, 0x21, 0xee, 0x83, 0x7c, 0xe1, 0xfb, + 0xba, 0xa8, 0xeb, 0x33, 0x2d, 0x2d, 0xce, 0x97, 0x7a, 0x64, 0x2c, 0x0a, + 0xbf, 0x75, 0xd0, 0x2b, 0x39, 0xe4, 0x72, 0xe3, 0xb7, 0xdf, 0xe0, 0xdf, + 0xbc, 0x78, 0x94, 0xce, 0x45, 0x87, 0x2e, 0x27, 0xf7, 0x27, 0x4f, 0xb0, + 0x95, 0x4a, 0xf4, 0xb7, 0xe1, 0x5f, 0x94, 0xf1, 0x8c, 0xe2, 0x9d, 0x8e, + 0xd5, 0x78, 0xf9, 0x0b, 0xdf, 0xec, 0xb9, 0xdd, 0xdc, 0xc8, 0x2f, 0x6c, + 0xcb, 0x5f, 0x88, 0x38, 0xff, 0x76, 0x62, 0x26, 0x3a, 0x36, 0x3c, 0x25, + 0x6a, 0x4e, 0xdd, 0x78, 0x70, 0x67, 0xe2, 0xc3, 0xc0, 0x87, 0xe1, 0x3a, + 0x5e, 0xf5, 0xd1, 0xfd, 0xfd, 0xb5, 0x70, 0x6d, 0xf3, 0xf4, 0x55, 0x79, + 0xc7, 0x81, 0x11, 0xf3, 0x87, 0x9f, 0xfa, 0x21, 0x9a, 0xbf, 0x08, 0x1c, + 0x36, 0x18, 0xdb, 0x46, 0x69, 0x21, 0x88, 0xba, 0x22, 0x51, 0x9b, 0xa3, + 0xe2, 0x86, 0xb2, 0x56, 0x68, 0x5e, 0xd4, 0x40, 0x8e, 0x85, 0x6e, 0xf2, + 0xbc, 0xe7, 0x8b, 0x29, 0x3a, 0xc5, 0x32, 0xf6, 0xd4, 0x4a, 0x45, 0x77, + 0xaf, 0xaf, 0x83, 0xac, 0xc6, 0xf1, 0x9b, 0x02, 0xc7, 0x87, 0x36, 0xc5, + 0xf1, 0xc3, 0x65, 0x1c, 0xff, 0x44, 0xaf, 0xc4, 0xe7, 0x67, 0xf9, 0x5e, + 0x5d, 0x74, 0x50, 0xdc, 0x37, 0xc5, 0xdf, 0xdb, 0xe9, 0xa0, 0xec, 0x61, + 0xc1, 0xcf, 0x66, 0x1e, 0x9f, 0x49, 0xd1, 0x53, 0x17, 0x53, 0xbe, 0xb8, + 0xa8, 0x5f, 0x70, 0xf7, 0xe8, 0xd0, 0xd7, 0x63, 0x5c, 0x23, 0xfc, 0xd7, + 0x7c, 0x49, 0xd6, 0x5c, 0xe5, 0x25, 0x7f, 0xa2, 0x77, 0xc3, 0x83, 0x35, + 0xf8, 0x5f, 0x6d, 0x3b, 0x9e, 0x56, 0x32, 0xf0, 0xd8, 0x26, 0x7e, 0x8d, + 0x7a, 0xbc, 0xec, 0xf1, 0xd0, 0x87, 0x7f, 0xbd, 0x57, 0xc6, 0xa9, 0x36, + 0xf3, 0x6b, 0xb8, 0x71, 0xb4, 0x2a, 0x6e, 0xcf, 0x7c, 0xff, 0xbf, 0x55, + 0x1c, 0xfd, 0xa5, 0x5e, 0x29, 0x2f, 0x50, 0x1f, 0x98, 0x60, 0x38, 0x9c, + 0x64, 0x5d, 0x65, 0x90, 0x9a, 0x5f, 0xd6, 0x6b, 0x1d, 0x14, 0xfc, 0xd6, + 0xed, 0xa7, 0x39, 0xa7, 0x6a, 0xbb, 0xd3, 0xae, 0x35, 0x9d, 0x13, 0x36, + 0x4e, 0x63, 0x7a, 0x6b, 0x9c, 0x73, 0x35, 0x54, 0x23, 0x13, 0x6a, 0xf1, + 0x0d, 0xbd, 0x4f, 0xb0, 0xbf, 0x64, 0x48, 0x3d, 0x78, 0x9a, 0xf5, 0xdb, + 0x9d, 0xc6, 0x8b, 0x3e, 0xaa, 0x8e, 0x58, 0xdb, 0x53, 0xa3, 0xf6, 0x3b, + 0xf6, 0x41, 0xda, 0x1c, 0xc9, 0x57, 0x1f, 0x12, 0xbc, 0xe0, 0xdc, 0x64, + 0x89, 0x62, 0xe1, 0x4e, 0x4a, 0x4e, 0xf2, 0xb3, 0xa7, 0x1d, 0xb6, 0xbd, + 0xfc, 0x94, 0x62, 0xfa, 0x4d, 0x4e, 0xee, 0x52, 0xfa, 0xa2, 0xf6, 0xa7, + 0xb7, 0xa8, 0x3c, 0x87, 0x67, 0x45, 0x5c, 0x52, 0xf6, 0xc6, 0xe0, 0xef, + 0x2b, 0xfa, 0xde, 0xcf, 0x8a, 0xf8, 0x68, 0xf2, 0x62, 0xb3, 0x1a, 0xd7, + 0xee, 0x1a, 0x87, 0x31, 0xed, 0x6a, 0x2c, 0xee, 0xa9, 0x75, 0x8a, 0x56, + 0xc5, 0x6f, 0x1f, 0x11, 0x75, 0x60, 0xb2, 0x56, 0x0f, 0xbf, 0x9f, 0xa6, + 0xb9, 0xf2, 0x5a, 0xda, 0x79, 0xec, 0xcf, 0x4a, 0x11, 0x61, 0xcb, 0xb5, + 0xb3, 0xce, 0x8b, 0x79, 0xd7, 0xcf, 0x09, 0x6b, 0xf1, 0x8b, 0xf8, 0x10, + 0x7f, 0x57, 0xcf, 0x39, 0x59, 0x9e, 0x13, 0x72, 0x34, 0xec, 0x90, 0xbc, + 0x97, 0x1e, 0xd7, 0xee, 0x1a, 0xa7, 0x79, 0x85, 0x8e, 0x3f, 0xfc, 0x80, + 0xe7, 0xf1, 0x37, 0x2a, 0x87, 0xd7, 0x14, 0xf1, 0x53, 0x99, 0xa3, 0xa1, + 0xbf, 0xc3, 0xbf, 0x8c, 0x9c, 0x0a, 0xe4, 0x49, 0xb8, 0xf9, 0x8d, 0x5c, + 0x6f, 0x00, 0xb2, 0xa8, 0x88, 0xb8, 0x29, 0xe2, 0x15, 0x8d, 0x74, 0xe7, + 0xbd, 0xc8, 0xcd, 0xdf, 0x81, 0x0e, 0xba, 0x1d, 0xfa, 0xb3, 0x3c, 0xe8, + 0xcf, 0xfd, 0x7c, 0xd4, 0xc1, 0xa1, 0x1e, 0x2e, 0x35, 0x61, 0x50, 0x89, + 0x6d, 0x05, 0x83, 0xf2, 0xa6, 0x8f, 0x9e, 0x72, 0xec, 0xf0, 0x0a, 0xc9, + 0x9a, 0xc9, 0xd8, 0xa2, 0x3d, 0xb1, 0x4e, 0xfb, 0x45, 0xcd, 0x38, 0x7a, + 0x1f, 0xe4, 0x59, 0x06, 0x9f, 0xa4, 0x09, 0xb6, 0x8f, 0xd8, 0xfe, 0x9c, + 0x45, 0xbc, 0x45, 0xef, 0x0b, 0x6a, 0xe0, 0xf1, 0x39, 0xc1, 0x70, 0x7a, + 0x6c, 0x37, 0xb5, 0x45, 0xf8, 0x9e, 0x13, 0xe0, 0x4f, 0xe8, 0xe7, 0x45, + 0x51, 0xb6, 0x93, 0x60, 0xb3, 0x9e, 0x9c, 0xb5, 0xcd, 0x3c, 0x19, 0x3c, + 0x16, 0xb6, 0x2b, 0xee, 0x83, 0xeb, 0x23, 0x66, 0x13, 0xd5, 0xd6, 0xe4, + 0x3e, 0x2b, 0xea, 0x14, 0xdf, 0x0d, 0xdf, 0x47, 0x46, 0x3f, 0xf8, 0x15, + 0xf6, 0xed, 0x5e, 0x15, 0x27, 0x3a, 0xcb, 0xdf, 0xc7, 0xd5, 0xf7, 0xaf, + 0x88, 0xfd, 0x94, 0xdf, 0x35, 0x7e, 0xe3, 0xef, 0x5f, 0x5a, 0xc8, 0xf9, + 0xa1, 0xca, 0x59, 0xa9, 0xca, 0x05, 0x09, 0x8d, 0x1a, 0x5f, 0xa1, 0xd3, + 0x2b, 0x9b, 0xf9, 0x5f, 0xbc, 0x6a, 0x5d, 0xbb, 0xb7, 0x59, 0xeb, 0xfa, + 0x07, 0xbb, 0x65, 0x6d, 0x99, 0x7b, 0x2e, 0xff, 0xc9, 0x73, 0xf1, 0xd2, + 0xc9, 0xea, 0xf4, 0x44, 0x5e, 0x6f, 0x89, 0xfe, 0x29, 0xfc, 0x49, 0xba, + 0x1e, 0x0c, 0xa9, 0x9c, 0x25, 0xe4, 0x28, 0xdd, 0xa7, 0xf0, 0x5a, 0xf3, + 0x7e, 0xf2, 0xe0, 0xfd, 0x8f, 0x89, 0x5c, 0x4d, 0x29, 0x3b, 0x06, 0x15, + 0x3c, 0x00, 0xb3, 0x90, 0x0b, 0x66, 0x7d, 0x2e, 0x98, 0x19, 0xea, 0x7b, + 0xa7, 0x38, 0x3e, 0xbd, 0xf2, 0x99, 0x6e, 0x59, 0x2f, 0x8e, 0x58, 0xe2, + 0xbc, 0xfa, 0xbe, 0xd5, 0x7a, 0x7f, 0xce, 0x6b, 0x15, 0xfe, 0x26, 0xd7, + 0x5a, 0x5f, 0x27, 0x72, 0x5a, 0x82, 0xf5, 0x30, 0xf8, 0x8e, 0xeb, 0x3c, + 0xe6, 0x38, 0xe6, 0x9a, 0xe3, 0x88, 0x6b, 0x8e, 0x77, 0x37, 0x98, 0x23, + 0xf3, 0xf8, 0xe2, 0x69, 0xfe, 0xbf, 0xdd, 0xb9, 0xca, 0x79, 0xce, 0x0b, + 0x78, 0xb6, 0x53, 0x3a, 0x18, 0x52, 0xb2, 0xe3, 0xfb, 0xaa, 0x16, 0xdd, + 0x6b, 0xce, 0xff, 0x40, 0x8d, 0xf7, 0xcd, 0x8d, 0xab, 0xee, 0xfa, 0xe3, + 0x97, 0x28, 0x26, 0xeb, 0xc8, 0x15, 0x6d, 0x7f, 0xb5, 0x81, 0x1f, 0xfa, + 0x41, 0xa1, 0xff, 0xcc, 0xcb, 0x78, 0xd0, 0x80, 0xec, 0xbf, 0x16, 0xa0, + 0xd5, 0x72, 0x2d, 0xaf, 0x5f, 0xd5, 0xee, 0xdc, 0x1f, 0xbc, 0xb3, 0x75, + 0xbc, 0x38, 0xff, 0x88, 0xf0, 0xe5, 0xc9, 0xf8, 0x51, 0x42, 0xd5, 0x23, + 0xdb, 0x16, 0x72, 0x03, 0x0a, 0x6b, 0xf0, 0xbf, 0x36, 0xaa, 0xdd, 0xc5, + 0xb5, 0xf0, 0x03, 0x6a, 0x3b, 0xfe, 0x84, 0xe0, 0x89, 0xd2, 0x3f, 0x26, + 0xeb, 0x6f, 0x0b, 0x6b, 0x27, 0x45, 0xcd, 0x6b, 0x54, 0xd5, 0xf1, 0x26, + 0xa9, 0x43, 0xe8, 0xb9, 0xb7, 0x5f, 0x7f, 0xfb, 0x5c, 0x70, 0xe7, 0xf5, + 0xb7, 0xee, 0x6b, 0x76, 0x56, 0x7f, 0x6b, 0xf2, 0xda, 0x8d, 0x65, 0x59, + 0x7f, 0x5b, 0x1d, 0x93, 0x91, 0xfe, 0xc0, 0xa4, 0x4b, 0x7f, 0x90, 0xfa, + 0xfa, 0x6f, 0xb9, 0xf2, 0xb7, 0x65, 0x6d, 0x6d, 0xa1, 0xac, 0xb3, 0xca, + 0xda, 0x5a, 0x99, 0xef, 0xed, 0xee, 0x03, 0x23, 0x63, 0x3f, 0xf2, 0x39, + 0x9d, 0x35, 0xb1, 0x1f, 0x59, 0x53, 0x6b, 0x19, 0x8d, 0x6c, 0x38, 0xd1, + 0xe7, 0xa2, 0x8f, 0xba, 0x22, 0x8c, 0xbb, 0xed, 0x0d, 0xfa, 0x21, 0x44, + 0x1a, 0xf4, 0x43, 0x70, 0xf3, 0x7e, 0xb7, 0x8e, 0x05, 0x9d, 0x18, 0xb2, + 0x11, 0xba, 0x30, 0xfa, 0x19, 0x84, 0xe9, 0x74, 0x59, 0xf7, 0xbc, 0x8f, + 0x12, 0x4a, 0xf7, 0x3c, 0xbd, 0xa2, 0xf9, 0xd1, 0x48, 0x0d, 0x3f, 0xf2, + 0xd2, 0x45, 0x6d, 0x95, 0xe7, 0xa3, 0xe9, 0x35, 0xe5, 0xa2, 0xd7, 0x94, + 0x07, 0xbd, 0x8a, 0x67, 0x34, 0x98, 0xf7, 0xf7, 0xd5, 0x35, 0xf8, 0x4f, + 0x84, 0xd0, 0xb3, 0x85, 0x79, 0x6a, 0x50, 0xe9, 0x7f, 0x2e, 0x7a, 0x3d, + 0xc5, 0xf4, 0xaa, 0xcf, 0x63, 0xbe, 0x0d, 0x73, 0x41, 0x95, 0xce, 0x38, + 0xe8, 0x3b, 0x74, 0xf1, 0x1b, 0x22, 0x4f, 0xaa, 0xda, 0x5e, 0xd4, 0xfa, + 0xc4, 0x3e, 0x41, 0x4b, 0xd7, 0xfd, 0xc8, 0x5b, 0xd1, 0xe7, 0x4c, 0xe5, + 0x27, 0xd3, 0xb0, 0x68, 0xae, 0xd2, 0x39, 0x2a, 0xfa, 0x86, 0xc8, 0xf1, + 0x75, 0xcd, 0xed, 0x43, 0x9e, 0x9b, 0x3e, 0xaf, 0x65, 0xe6, 0xb5, 0x2a, + 0x7f, 0xc6, 0xe5, 0xaa, 0x9e, 0x83, 0xf0, 0x1d, 0x75, 0x26, 0x0c, 0x27, + 0x2e, 0x72, 0x4c, 0x7b, 0x1c, 0xf8, 0xc9, 0xa2, 0x4c, 0xfb, 0x3d, 0x09, + 0xe4, 0x33, 0xf7, 0x2c, 0x59, 0x74, 0x3c, 0x73, 0xff, 0x5d, 0x12, 0x57, + 0xce, 0x8a, 0x3e, 0x92, 0xe8, 0x67, 0x16, 0x63, 0xf9, 0x1c, 0xf5, 0x4f, + 0xd3, 0xf9, 0x62, 0x0b, 0x15, 0x58, 0xbb, 0xf7, 0x3b, 0x79, 0xe1, 0xeb, + 0x63, 0x9e, 0x94, 0x45, 0x2f, 0x51, 0x63, 0xb9, 0x99, 0xef, 0xdb, 0x4f, + 0xab, 0xb9, 0x31, 0xd1, 0x13, 0x4a, 0xf6, 0x17, 0xc1, 0x58, 0x1f, 0xf5, + 0x3a, 0x07, 0xfb, 0xa8, 0xed, 0xb3, 0x22, 0xc7, 0xb2, 0x90, 0x3d, 0x2b, + 0x3f, 0xf3, 0x0f, 0xa8, 0x67, 0xf0, 0xf3, 0x8a, 0x7f, 0x4a, 0x91, 0x5e, + 0xcb, 0x65, 0xcb, 0xb9, 0xff, 0xbc, 0xf5, 0x95, 0xa3, 0x3b, 0xd2, 0x57, + 0x52, 0x89, 0x8a, 0xbe, 0xe2, 0xbe, 0x77, 0x39, 0x07, 0xa6, 0x5f, 0xf6, + 0x7b, 0x00, 0x0c, 0xda, 0xa1, 0x8b, 0x25, 0x00, 0x4b, 0x63, 0xc6, 0x0e, + 0x45, 0xfd, 0x53, 0xb4, 0x50, 0x1c, 0x32, 0x92, 0x59, 0xe8, 0xcc, 0xfc, + 0x99, 0x8f, 0xee, 0x91, 0x3e, 0x1a, 0x7d, 0x0d, 0xf8, 0xca, 0x6e, 0x1e, + 0xff, 0x7a, 0xbf, 0xcc, 0xcb, 0x76, 0x9f, 0xef, 0xe2, 0xf3, 0x7b, 0x42, + 0xd5, 0xe7, 0x77, 0xf1, 0xf9, 0xde, 0x04, 0xf6, 0xd0, 0x58, 0x82, 0x5f, + 0xd2, 0xa1, 0x34, 0xef, 0xcd, 0x42, 0x91, 0x65, 0xeb, 0xcb, 0xcc, 0x47, + 0x57, 0xf4, 0xb8, 0x3e, 0xd4, 0xec, 0x88, 0x3d, 0x31, 0x78, 0xcc, 0xb9, + 0xcc, 0x04, 0x8f, 0x1b, 0x24, 0xff, 0xcb, 0x6c, 0x8b, 0xae, 0x68, 0x5c, + 0xd5, 0xf9, 0xf6, 0xdf, 0xe8, 0x93, 0x39, 0x55, 0xdf, 0xdd, 0x23, 0xe1, + 0xe7, 0x08, 0x9e, 0x72, 0x9e, 0xe1, 0xf2, 0xbc, 0xc0, 0x43, 0x7b, 0xda, + 0x2a, 0x3f, 0xbf, 0x13, 0x78, 0xd5, 0x8a, 0xbc, 0xd9, 0xc0, 0x12, 0xf3, + 0xc5, 0x19, 0xc7, 0x4c, 0x97, 0x73, 0xd5, 0x1e, 0x1f, 0x90, 0xd7, 0xbf, + 0xd9, 0x27, 0xfb, 0x83, 0x7e, 0x6b, 0x40, 0xf7, 0x48, 0x94, 0x32, 0x07, + 0xf9, 0xcb, 0x3e, 0x01, 0x1b, 0xff, 0x32, 0xf8, 0xa5, 0xc1, 0xdf, 0x79, + 0x3d, 0x09, 0xcc, 0xf1, 0x4a, 0x9f, 0xee, 0x17, 0x23, 0xd7, 0x15, 0xe7, + 0xf9, 0x46, 0x78, 0x5d, 0xfa, 0xfc, 0x0c, 0x1f, 0x7b, 0xed, 0x2f, 0xee, + 0xd5, 0x96, 0x90, 0xfd, 0xc5, 0xda, 0x12, 0xc9, 0x09, 0xb9, 0xcf, 0x15, + 0x9f, 0x6e, 0xa8, 0xec, 0xd3, 0x3d, 0x9f, 0xb9, 0xd5, 0x07, 0xff, 0x86, + 0xb1, 0xc4, 0xfb, 0x1d, 0x7c, 0x9e, 0xc7, 0xa2, 0x56, 0x21, 0xcd, 0x9f, + 0x1d, 0x2a, 0xaf, 0xa7, 0x1e, 0x57, 0x64, 0x9e, 0x84, 0x96, 0x5b, 0xb8, + 0xf6, 0x43, 0xbe, 0x87, 0x94, 0x5d, 0x8d, 0x9f, 0x43, 0x75, 0x79, 0x30, + 0xf5, 0x38, 0xb6, 0x99, 0x1f, 0x56, 0xc4, 0x13, 0x3d, 0xf0, 0x6c, 0xb3, + 0x7e, 0x06, 0xd7, 0x84, 0x1f, 0x2d, 0x56, 0x47, 0xaf, 0xa0, 0xe3, 0x00, + 0xfd, 0xce, 0x62, 0x8a, 0x76, 0xf1, 0x5e, 0xfd, 0xa6, 0xf1, 0x00, 0xe2, + 0xed, 0x24, 0x73, 0x9e, 0x18, 0xc6, 0x19, 0x67, 0xe2, 0x94, 0x11, 0x01, + 0xbf, 0x2c, 0x05, 0x9c, 0x0e, 0x6a, 0x66, 0x5a, 0xfd, 0x65, 0x1a, 0x65, + 0xfb, 0x0f, 0x34, 0xeb, 0x84, 0xe2, 0x04, 0x7a, 0xb3, 0xcd, 0x43, 0xac, + 0x13, 0xc7, 0x8a, 0xc0, 0x67, 0x83, 0x3e, 0x9f, 0x23, 0xfa, 0x5c, 0x6e, + 0xd4, 0xfc, 0x26, 0x39, 0x56, 0xe5, 0x77, 0xdb, 0x8c, 0xf2, 0x3c, 0xe2, + 0xc5, 0x2f, 0xd3, 0xfb, 0xa2, 0xcf, 0x09, 0xe0, 0xa8, 0xf7, 0xfd, 0x4b, + 0x74, 0x32, 0x81, 0x79, 0x6f, 0x9f, 0x3e, 0x8f, 0xef, 0x88, 0x3e, 0xdb, + 0x3c, 0xe8, 0xf3, 0xc5, 0x7e, 0x89, 0x37, 0x25, 0xc6, 0xd1, 0x36, 0x9a, + 0xcb, 0x22, 0x07, 0xec, 0xd3, 0xe8, 0x3b, 0x95, 0x4d, 0x32, 0x5f, 0x4a, + 0x56, 0xf8, 0xd2, 0x85, 0x28, 0x1b, 0xc3, 0x4c, 0xe3, 0xe8, 0xcb, 0xa6, + 0xf2, 0x7e, 0xb0, 0x8e, 0x01, 0x1a, 0x5d, 0x6e, 0xe7, 0x6b, 0x69, 0x3d, + 0x3a, 0x15, 0x51, 0xb5, 0xfe, 0xb6, 0x15, 0x63, 0xfe, 0x78, 0x9e, 0x69, + 0x39, 0x9d, 0xbd, 0x97, 0x0a, 0xc1, 0x21, 0x1a, 0x59, 0xd6, 0xfd, 0x4d, + 0x44, 0xce, 0xc6, 0xa0, 0xe4, 0x49, 0x7a, 0xdd, 0x9f, 0x10, 0xbe, 0x0b, + 0xeb, 0xd2, 0xc7, 0xb5, 0xee, 0xf6, 0x2d, 0xf8, 0xd2, 0x25, 0x45, 0xb3, + 0xa5, 0xcb, 0xd1, 0x30, 0xa5, 0xa2, 0x53, 0xaf, 0xf4, 0x03, 0xff, 0x47, + 0x2e, 0xc1, 0x0f, 0x07, 0x1e, 0x6d, 0x51, 0x22, 0x53, 0x0b, 0x8b, 0x21, + 0x5e, 0x37, 0x7e, 0x2f, 0x7d, 0x30, 0x17, 0x7e, 0x40, 0xc8, 0xfe, 0xd1, + 0x4b, 0x3c, 0x4e, 0xca, 0x26, 0xc5, 0x37, 0xbc, 0xf0, 0x50, 0xf7, 0xc5, + 0xd4, 0xb8, 0x28, 0x73, 0x3d, 0x59, 0x7f, 0x33, 0x13, 0xfe, 0x5a, 0x9c, + 0xbc, 0xe6, 0x3b, 0xba, 0x68, 0xd1, 0xb1, 0x8c, 0xfd, 0xf5, 0x14, 0x4d, + 0x31, 0x5d, 0xbb, 0xe5, 0x05, 0x8f, 0x27, 0xe0, 0xd9, 0x34, 0xd3, 0x3e, + 0xdb, 0xcd, 0x59, 0x4b, 0xe6, 0xdd, 0x89, 0xde, 0x73, 0x38, 0x46, 0xdd, + 0xf1, 0x5f, 0xf5, 0x6b, 0x79, 0x90, 0xcc, 0xa2, 0x8e, 0x90, 0x3f, 0xf3, + 0x3c, 0x1e, 0xb9, 0xff, 0x39, 0xdc, 0x07, 0xf2, 0x0e, 0x73, 0xe7, 0xe3, + 0x55, 0xb9, 0xaf, 0x23, 0x7c, 0x6f, 0xd4, 0xdd, 0x1f, 0x2b, 0x4e, 0xf2, + 0xfe, 0x76, 0x09, 0xde, 0x2c, 0xf7, 0x73, 0x9a, 0xce, 0x79, 0xf2, 0x15, + 0xb9, 0x2f, 0x49, 0x17, 0x7d, 0x27, 0x05, 0x7d, 0x4f, 0x8b, 0xfd, 0x48, + 0xe6, 0x0c, 0xd6, 0xd7, 0xb4, 0xef, 0x81, 0xed, 0xec, 0x5c, 0x40, 0xe7, + 0x06, 0xf2, 0xf7, 0x0f, 0xfb, 0x45, 0x5e, 0x22, 0xec, 0xef, 0x1c, 0x3e, + 0xa7, 0xe9, 0x79, 0x96, 0xeb, 0x2f, 0x64, 0x5a, 0xe8, 0x6a, 0xb6, 0x85, + 0xde, 0xc9, 0x0e, 0xd1, 0x95, 0xc5, 0x6e, 0x3a, 0xc7, 0x3a, 0xf3, 0x39, + 0x27, 0x60, 0xa5, 0xa9, 0x1b, 0xf1, 0x45, 0xe4, 0x0c, 0x31, 0xdd, 0x61, + 0x3c, 0xf4, 0xbf, 0xe8, 0x5e, 0xc6, 0x39, 0xd6, 0xbd, 0x5b, 0xe9, 0x3d, + 0x7e, 0x66, 0x3a, 0xa3, 0x73, 0x1d, 0xe0, 0x93, 0x1f, 0x2b, 0xeb, 0xaf, + 0x5b, 0xe3, 0x88, 0xb9, 0x05, 0x8e, 0x4c, 0x8b, 0xf8, 0xd6, 0xc2, 0x22, + 0xff, 0xbe, 0x08, 0xff, 0x39, 0xc3, 0x9b, 0xf9, 0xf3, 0x93, 0x01, 0x8c, + 0xc7, 0x39, 0x47, 0xe6, 0x4a, 0x8a, 0xb5, 0x85, 0xf8, 0xd8, 0x27, 0x6a, + 0xa4, 0x25, 0x1c, 0x5a, 0x79, 0x7d, 0x3e, 0x31, 0x3e, 0xb9, 0xda, 0x4a, + 0xf3, 0x39, 0xd6, 0x41, 0x72, 0x7e, 0xb6, 0x61, 0x30, 0xf6, 0xef, 0x54, + 0x6f, 0x61, 0xdc, 0xbf, 0x8b, 0xd2, 0x62, 0x1c, 0x7f, 0xae, 0x76, 0xd1, + 0x42, 0xae, 0x43, 0x1d, 0xdf, 0x2b, 0x72, 0xdc, 0x65, 0x1f, 0x23, 0xfc, + 0xb6, 0x19, 0x7f, 0x7b, 0x97, 0x71, 0x0a, 0x32, 0x55, 0xda, 0xa5, 0xe0, + 0x35, 0x97, 0xeb, 0x7a, 0x22, 0x03, 0xe7, 0xa6, 0xe8, 0x25, 0x96, 0xb7, + 0x23, 0x2f, 0xc3, 0x7f, 0xfc, 0x38, 0xf0, 0x26, 0x9f, 0xa2, 0x41, 0x3e, + 0x46, 0x5f, 0x24, 0xbf, 0xa8, 0x73, 0x8a, 0x05, 0x27, 0x44, 0x6d, 0x88, + 0xa4, 0xd1, 0x59, 0xd1, 0x8b, 0xee, 0x2d, 0xc1, 0x9b, 0xec, 0x94, 0x65, + 0x40, 0x1f, 0x81, 0x0f, 0x46, 0xe6, 0x60, 0x1d, 0x77, 0x7a, 0xde, 0xed, + 0x9b, 0x19, 0xa7, 0x48, 0x3f, 0xf0, 0x5e, 0xd2, 0xac, 0xea, 0x2f, 0x20, + 0xf8, 0xbd, 0xb9, 0x4f, 0xd7, 0x4b, 0xea, 0x63, 0x2d, 0x2b, 0xf4, 0x71, + 0x47, 0xcd, 0xef, 0x66, 0xcd, 0xef, 0xe5, 0x7c, 0x39, 0x96, 0x79, 0x2c, + 0xe7, 0x49, 0xf6, 0x28, 0x4a, 0x2e, 0x4b, 0xfc, 0x33, 0xf7, 0x8d, 0x99, + 0x8f, 0x2a, 0x1d, 0x3c, 0xb9, 0x36, 0x1a, 0xea, 0x31, 0x26, 0x8c, 0xe4, + 0xe4, 0x3f, 0x96, 0x22, 0x09, 0xe8, 0x45, 0x4f, 0xee, 0x51, 0xf9, 0xa7, + 0x3c, 0xaf, 0x54, 0x18, 0xaa, 0xdb, 0xec, 0x5a, 0x07, 0xad, 0x8b, 0x9e, + 0x5c, 0x42, 0xc7, 0xe0, 0xeb, 0x71, 0x9f, 0x94, 0xd9, 0x44, 0xe8, 0x73, + 0x0e, 0x1a, 0xdf, 0x1f, 0xba, 0xc4, 0xfb, 0x19, 0x5f, 0xfb, 0x69, 0xe9, + 0xa4, 0xe8, 0x71, 0x83, 0xb1, 0x5d, 0x34, 0x27, 0x74, 0x7e, 0xd6, 0x5f, + 0xaa, 0xec, 0xaa, 0x29, 0xcc, 0x33, 0x85, 0xd8, 0x8a, 0xe1, 0xfc, 0xbe, + 0x2f, 0x99, 0x97, 0xb1, 0xf2, 0x78, 0x4d, 0xac, 0x7c, 0x56, 0xc4, 0xca, + 0x11, 0x27, 0x07, 0x5c, 0x01, 0x4b, 0xaf, 0x9c, 0x16, 0xec, 0x63, 0x98, + 0x90, 0x1b, 0x7e, 0xee, 0xa2, 0xe0, 0x37, 0xe1, 0x98, 0x5f, 0xe6, 0x57, + 0xc7, 0x79, 0xc6, 0x06, 0x5d, 0x60, 0x7c, 0xb0, 0x27, 0x36, 0x58, 0x97, + 0x58, 0xc9, 0x7e, 0x99, 0xae, 0xe4, 0x9b, 0x58, 0xd7, 0x5b, 0xa0, 0x8d, + 0x3c, 0xb1, 0x4e, 0xd8, 0x4d, 0x0b, 0x61, 0xc6, 0xb1, 0x89, 0x36, 0xde, + 0x4f, 0xd6, 0x6b, 0x27, 0x98, 0xee, 0x78, 0xee, 0x2b, 0xb9, 0xd2, 0x8f, + 0xd2, 0xe1, 0x88, 0x15, 0x9d, 0xea, 0x60, 0xbb, 0xc5, 0xe4, 0x7f, 0x87, + 0xff, 0x77, 0x85, 0x00, 0x93, 0xc2, 0x2a, 0x7e, 0x67, 0x9d, 0x27, 0x53, + 0xfa, 0xd1, 0x1c, 0x8f, 0x99, 0x9b, 0x82, 0xfd, 0x03, 0x3b, 0xcf, 0xe1, + 0x7f, 0x39, 0x66, 0x65, 0x95, 0xf1, 0xfb, 0x62, 0x2a, 0x64, 0x08, 0xde, + 0xbe, 0xce, 0x3c, 0xfe, 0x02, 0xcd, 0xf1, 0x1c, 0xae, 0x10, 0xae, 0xb5, + 0x28, 0x19, 0xde, 0xc7, 0x78, 0xdf, 0xcd, 0x9f, 0xa8, 0xbf, 0x6a, 0xa7, + 0x85, 0xc9, 0x31, 0x55, 0x7f, 0xf5, 0xbd, 0x06, 0xf5, 0x57, 0xb8, 0x8e, + 0xe5, 0xfe, 0x62, 0xe9, 0xe6, 0x5c, 0xd8, 0xfd, 0x3c, 0x32, 0x92, 0xe1, + 0x4e, 0xa1, 0x23, 0xad, 0xac, 0xfa, 0xf8, 0xd9, 0x11, 0x2b, 0x39, 0xc5, + 0x73, 0xcc, 0xb9, 0xe7, 0x5d, 0xba, 0x19, 0x0b, 0x63, 0x9c, 0xbf, 0x66, + 0x1c, 0xdb, 0xca, 0x53, 0x72, 0x3d, 0x85, 0x5c, 0xe9, 0xe7, 0xd1, 0xb0, + 0x5e, 0x9f, 0xfb, 0x5a, 0xac, 0x03, 0xf4, 0xc4, 0x9f, 0x2b, 0x5d, 0xbe, + 0x2b, 0x59, 0xd8, 0xdf, 0x06, 0xe3, 0x39, 0x66, 0x34, 0x44, 0xa9, 0x15, + 0xa6, 0xef, 0x8b, 0x1d, 0xbe, 0x8d, 0xec, 0x95, 0x52, 0xb2, 0x2a, 0x97, + 0xa5, 0xda, 0xef, 0x2e, 0x6d, 0xae, 0x21, 0x72, 0x96, 0x20, 0x33, 0x21, + 0x2f, 0x53, 0x25, 0xbf, 0x03, 0xfd, 0x0e, 0xb6, 0xd0, 0x59, 0xe6, 0x57, + 0x32, 0x1f, 0x89, 0x79, 0x27, 0xf3, 0x2c, 0x49, 0x2f, 0xf1, 0xaa, 0xd7, + 0x0d, 0x48, 0x9c, 0x1d, 0xa9, 0xe4, 0x41, 0xba, 0xe2, 0xe9, 0x01, 0x57, + 0x3c, 0xdd, 0x74, 0xe5, 0x41, 0x06, 0x85, 0x3e, 0x56, 0xd1, 0xa1, 0x82, + 0x4a, 0x87, 0x82, 0xae, 0x25, 0x79, 0x59, 0xa1, 0xcc, 0xcb, 0x76, 0x6f, + 0xc1, 0xcb, 0xbc, 0x6c, 0xd3, 0x75, 0xc5, 0x37, 0xec, 0x30, 0xe4, 0xfc, + 0xe5, 0xe2, 0x34, 0xbd, 0xcd, 0x3c, 0xe2, 0xad, 0x62, 0x98, 0xf9, 0xc6, + 0x24, 0xf3, 0x8d, 0x09, 0xe6, 0x1b, 0x0e, 0xc3, 0xc0, 0xe2, 0xb5, 0x5f, + 0xf3, 0x5d, 0x59, 0x84, 0xbc, 0x98, 0xa2, 0xe7, 0x8b, 0xe0, 0xc1, 0x93, + 0xac, 0xf3, 0x5c, 0xf3, 0x6d, 0x2c, 0x76, 0x31, 0xbe, 0x4a, 0x3d, 0xa7, + 0xda, 0x8e, 0x41, 0xaf, 0x15, 0xf8, 0x87, 0xaf, 0x82, 0xcf, 0xbc, 0x91, + 0xa2, 0x4e, 0x86, 0x3d, 0xe0, 0xbc, 0x8e, 0xde, 0x14, 0xaf, 0x81, 0x96, + 0xd1, 0x13, 0xf8, 0xbb, 0xe3, 0x53, 0x3c, 0xf7, 0x4e, 0xdf, 0x02, 0xef, + 0xcb, 0xd3, 0xe1, 0x94, 0xd9, 0xcb, 0x38, 0x7f, 0xac, 0x82, 0xf3, 0xa9, + 0x34, 0xaf, 0xa0, 0x67, 0xb9, 0x9b, 0xc6, 0x0e, 0x44, 0xf7, 0xf6, 0x30, + 0x9d, 0x22, 0x37, 0xa2, 0xd2, 0xa7, 0xc7, 0x4f, 0x27, 0x83, 0x6d, 0xaa, + 0xbf, 0x8f, 0xc5, 0xf2, 0xf1, 0x03, 0xbe, 0xcf, 0x2d, 0x5f, 0x3a, 0xfb, + 0x2a, 0x3f, 0x03, 0xc7, 0x5f, 0x85, 0xff, 0x93, 0xed, 0x83, 0x56, 0xe1, + 0x3f, 0x2a, 0x88, 0xb1, 0x38, 0xb6, 0x27, 0x98, 0x97, 0x85, 0xd7, 0x0d, + 0x7b, 0x3a, 0x62, 0x30, 0xd1, 0x75, 0x99, 0xbc, 0xde, 0xd2, 0xa0, 0x8c, + 0xc1, 0xed, 0xdd, 0x2b, 0xf9, 0x06, 0xe3, 0x66, 0x30, 0x22, 0x6c, 0xb4, + 0xa6, 0x25, 0x29, 0x27, 0x0b, 0xbc, 0xcf, 0x2b, 0xe1, 0x09, 0xde, 0xe7, + 0x0e, 0x25, 0x23, 0x53, 0xfc, 0xbb, 0x90, 0xbf, 0x2c, 0x2b, 0x87, 0xd0, + 0xb3, 0xda, 0x14, 0xfd, 0x20, 0x66, 0xd1, 0x6f, 0xa7, 0x83, 0xef, 0x6b, + 0x33, 0xd6, 0x82, 0x4f, 0x7c, 0xe0, 0x4b, 0x66, 0xf1, 0x5c, 0xe0, 0x21, + 0x7f, 0xcf, 0x4f, 0xd1, 0x85, 0x8c, 0x9e, 0xc3, 0x80, 0x61, 0xbc, 0x84, + 0x79, 0xf8, 0x68, 0xb7, 0xf3, 0x43, 0x86, 0x17, 0x1f, 0xff, 0x71, 0xed, + 0x9c, 0x86, 0xd5, 0x9c, 0xd0, 0xd3, 0xb2, 0x05, 0x3d, 0x7c, 0x08, 0xbd, + 0x8f, 0x0a, 0xa2, 0xe7, 0x64, 0xb3, 0xb0, 0x4d, 0x0b, 0xc2, 0xc6, 0x28, + 0x85, 0x2a, 0x7d, 0x30, 0xef, 0xa9, 0x39, 0xf7, 0x13, 0x5f, 0x7a, 0xf1, + 0xa0, 0xd0, 0xc5, 0x46, 0x0e, 0xec, 0x55, 0xf5, 0xa7, 0x5d, 0xe2, 0xbe, + 0xc6, 0x32, 0x7e, 0x7b, 0x50, 0xfd, 0xf6, 0x49, 0xa1, 0x03, 0x23, 0x2f, + 0x2e, 0xb0, 0x24, 0xf0, 0x9c, 0xf7, 0xd7, 0x99, 0x60, 0x3c, 0x0f, 0xad, + 0xc0, 0x77, 0x2f, 0xe0, 0xa9, 0xe1, 0x01, 0x58, 0x00, 0xf7, 0x3b, 0x14, + 0xde, 0xdb, 0x56, 0xdc, 0xaf, 0xd7, 0xdd, 0x08, 0xce, 0xac, 0xd3, 0x64, + 0xb0, 0x56, 0xac, 0x69, 0x8f, 0x2f, 0x92, 0xb7, 0x8c, 0xf4, 0x22, 0x6c, + 0x1a, 0xd4, 0xb5, 0xdc, 0x85, 0xbc, 0x29, 0x9e, 0xc3, 0x1e, 0x8a, 0x24, + 0x30, 0x2f, 0x8c, 0xd3, 0x30, 0xf8, 0xb7, 0x1a, 0x58, 0xb8, 0xaf, 0xeb, + 0x56, 0xd7, 0xb5, 0x8a, 0xbd, 0x20, 0x03, 0xcf, 0xd1, 0xcf, 0xc6, 0x73, + 0xf1, 0x7c, 0x5c, 0x87, 0xfb, 0xc9, 0xfb, 0xf6, 0x31, 0x7f, 0x8e, 0x4e, + 0xc9, 0x7b, 0x19, 0x97, 0xe4, 0x6f, 0x7d, 0x8e, 0xf7, 0x7c, 0xe5, 0xfe, + 0xf9, 0x54, 0xbf, 0x1e, 0xec, 0x5f, 0x37, 0xe5, 0x85, 0x8f, 0x13, 0xbf, + 0x75, 0x8a, 0xdf, 0xa2, 0x4e, 0xa7, 0xd8, 0xd7, 0xf3, 0x7c, 0x3c, 0x9f, + 0xed, 0xf2, 0xc1, 0x36, 0x4f, 0x27, 0x3a, 0x7d, 0xf9, 0x3c, 0xd6, 0xdb, + 0xe9, 0x8b, 0x33, 0xee, 0xc7, 0xb2, 0xf1, 0xd2, 0x82, 0xe0, 0x31, 0xac, + 0xd3, 0xf6, 0xda, 0xe6, 0x49, 0xe3, 0x4f, 0x86, 0x64, 0x6f, 0x5b, 0x7c, + 0x67, 0xfa, 0xcb, 0x30, 0xfd, 0x65, 0x98, 0xfe, 0x32, 0x4c, 0x7f, 0x19, + 0xa6, 0x3f, 0xb6, 0x4b, 0xdf, 0x64, 0x99, 0xf1, 0x6d, 0x96, 0x19, 0x92, + 0x66, 0x23, 0xca, 0x8f, 0xa9, 0x69, 0xb6, 0xb6, 0x3e, 0x53, 0xd3, 0x28, + 0xe4, 0x34, 0xf9, 0x0e, 0x8f, 0x57, 0xd3, 0xea, 0x55, 0xa6, 0xd5, 0xa6, + 0x99, 0x7e, 0xba, 0x91, 0xc3, 0x9e, 0xd9, 0xd6, 0x79, 0xe6, 0xd1, 0x71, + 0x3f, 0x74, 0xaa, 0x00, 0xd3, 0x13, 0x74, 0x4a, 0x9b, 0xe1, 0xde, 0x4f, + 0x37, 0x99, 0x4f, 0xdf, 0xc8, 0x81, 0x76, 0xef, 0x52, 0xc7, 0x19, 0xa6, + 0x5d, 0xc8, 0xb9, 0x25, 0xdf, 0xd5, 0xac, 0xc1, 0xba, 0x57, 0xc0, 0x4c, + 0x12, 0xf8, 0xa8, 0xd0, 0xc7, 0x78, 0xdf, 0xd7, 0x99, 0xdf, 0xc3, 0x57, + 0x87, 0xbe, 0x5f, 0x79, 0x1f, 0xcb, 0x89, 0xd0, 0x15, 0xe6, 0xa3, 0xa7, + 0x73, 0x4b, 0x4c, 0xef, 0xbd, 0xf4, 0x85, 0x1c, 0xe4, 0x31, 0x60, 0xc4, + 0xc7, 0x79, 0x12, 0x3e, 0x30, 0x63, 0x06, 0x6b, 0x1f, 0x4b, 0x19, 0x02, + 0x4f, 0x9e, 0x01, 0x1c, 0x18, 0xf6, 0x67, 0xf6, 0xa2, 0x67, 0x7d, 0xc4, + 0x68, 0x56, 0x3e, 0x45, 0x7c, 0xc7, 0x78, 0x8c, 0x05, 0xdc, 0x70, 0xdc, + 0x28, 0xfe, 0x88, 0xf7, 0x42, 0x84, 0x19, 0x1e, 0xb5, 0x7c, 0xeb, 0x02, + 0x7a, 0x91, 0x02, 0x5e, 0xd3, 0x51, 0x3f, 0x6a, 0xc5, 0xe9, 0x39, 0xbc, + 0xff, 0xe0, 0x85, 0x22, 0xe6, 0xbd, 0x48, 0x0b, 0x41, 0xf0, 0x21, 0x3b, + 0x7c, 0x9d, 0x24, 0xec, 0x5a, 0x59, 0xbf, 0xfc, 0xbc, 0x37, 0x6f, 0xb3, + 0xa2, 0x42, 0x1f, 0x6e, 0x61, 0xfb, 0x06, 0xb0, 0x79, 0x8b, 0x71, 0x2d, + 0x0c, 0x9b, 0x5f, 0xf1, 0xb5, 0x37, 0x99, 0xe7, 0x60, 0xcf, 0x3a, 0x85, + 0x8c, 0xf1, 0xe2, 0x65, 0x1b, 0x8a, 0x97, 0x39, 0x2e, 0x5e, 0x96, 0x2e, + 0xf3, 0x32, 0xc6, 0x09, 0xc1, 0xc3, 0xc0, 0xa3, 0x66, 0x59, 0x4f, 0x94, + 0xdf, 0xa1, 0xff, 0xed, 0x16, 0x3c, 0x8b, 0x79, 0x3d, 0xdb, 0x0d, 0x85, + 0x62, 0xca, 0x77, 0x48, 0xf0, 0x0e, 0x8d, 0xd7, 0xff, 0xa3, 0xe8, 0xa1, + 0x55, 0xf0, 0x81, 0xf4, 0x2c, 0xf8, 0x95, 0xd7, 0xf8, 0xff, 0x02, 0x6c, + 0x79, 0xbc, 0x13, 0x7a, 0x8d, 0xf9, 0x58, 0x21, 0x0c, 0x9b, 0xb5, 0x43, + 0xd9, 0x36, 0xe8, 0xbb, 0xb5, 0x07, 0xb9, 0x96, 0x56, 0xb4, 0xcc, 0xc7, + 0x76, 0x2b, 0xbf, 0x05, 0xfc, 0x8c, 0xd8, 0xeb, 0x3a, 0x5d, 0xc0, 0x82, + 0x2e, 0xc0, 0x63, 0x03, 0x0c, 0x1f, 0xd1, 0x1b, 0x9c, 0xe8, 0x16, 0xc3, + 0x01, 0xfb, 0x7c, 0x0b, 0xfb, 0xcc, 0xba, 0x2c, 0x05, 0xe6, 0xa6, 0x02, + 0x03, 0x98, 0xdf, 0xc2, 0x6a, 0x85, 0x1f, 0x9e, 0xcf, 0x0c, 0x18, 0x85, + 0xac, 0x9c, 0xe3, 0xca, 0xb8, 0xe4, 0x79, 0x85, 0x3c, 0x7a, 0x7b, 0x89, + 0xb9, 0xf2, 0x1c, 0xf5, 0xfa, 0x04, 0xff, 0x52, 0x74, 0xbf, 0x1d, 0x5a, + 0x4b, 0x30, 0x5d, 0x61, 0x4f, 0x52, 0x2e, 0x9c, 0x79, 0x94, 0x9f, 0x8f, + 0x73, 0x8d, 0xd7, 0x71, 0xb3, 0xbc, 0x8e, 0x08, 0xaf, 0x03, 0x63, 0x6f, + 0xf9, 0x6e, 0xa8, 0x75, 0xdc, 0x28, 0xaf, 0x63, 0x56, 0xad, 0x83, 0xd2, + 0xc6, 0xcc, 0x6e, 0xa5, 0xc7, 0x6f, 0x79, 0xcf, 0xd6, 0x28, 0xeb, 0x27, + 0xe9, 0x55, 0xc0, 0xf3, 0x1e, 0x85, 0x2f, 0x6e, 0x7f, 0xa8, 0x7b, 0x6e, + 0xf6, 0xc4, 0x75, 0xfa, 0x5d, 0xba, 0x29, 0xf4, 0x93, 0x61, 0xd6, 0x4f, + 0x70, 0x9e, 0x16, 0xc0, 0x87, 0xd3, 0x41, 0xf4, 0x9b, 0x1d, 0x64, 0x98, + 0xb1, 0x5d, 0x35, 0xc5, 0x9f, 0xc2, 0x4f, 0x86, 0xfb, 0xe8, 0xeb, 0xbf, + 0x48, 0x37, 0x17, 0xc1, 0xab, 0xa1, 0x8f, 0xca, 0x9e, 0xb4, 0x37, 0xd7, + 0xa4, 0x9f, 0x36, 0xee, 0xe9, 0xa7, 0x85, 0x8f, 0x36, 0x0c, 0x7d, 0xdd, + 0x84, 0x3f, 0x37, 0x26, 0xde, 0x67, 0xc1, 0xc7, 0x45, 0xdc, 0xcb, 0x8b, + 0xef, 0x4c, 0xbb, 0x72, 0xdc, 0x90, 0x73, 0x92, 0x62, 0x3e, 0xe2, 0x98, + 0x4d, 0x86, 0xac, 0x9d, 0xb9, 0x5c, 0xd4, 0x3a, 0x51, 0x9c, 0xf7, 0xc8, + 0x09, 0x1b, 0x46, 0x44, 0xf8, 0x0c, 0x5a, 0x9d, 0x0e, 0x6a, 0x61, 0x39, + 0x79, 0x8a, 0xd0, 0x13, 0xcd, 0xb6, 0xe0, 0xcb, 0xbf, 0xc0, 0xb8, 0xb7, + 0x10, 0xb6, 0x43, 0x9f, 0x13, 0xf6, 0x25, 0xe4, 0x07, 0xde, 0xa7, 0x02, + 0x18, 0x63, 0x0e, 0xfc, 0x7d, 0x15, 0xfd, 0x30, 0xc3, 0xbc, 0x7e, 0xf8, + 0x81, 0x47, 0xad, 0x77, 0x58, 0xee, 0x5c, 0x10, 0xfe, 0x95, 0xb3, 0x94, + 0x66, 0x3a, 0x3c, 0x2c, 0xe8, 0xd0, 0x18, 0x66, 0x6a, 0x61, 0xfa, 0x41, + 0x8e, 0xc1, 0x98, 0xe8, 0xbf, 0x23, 0x6d, 0x16, 0x5e, 0xe5, 0x9a, 0xea, + 0x6b, 0x90, 0x00, 0x6f, 0xd8, 0xbe, 0x6f, 0x21, 0xf1, 0x91, 0x7d, 0x2a, + 0x6e, 0x5d, 0xab, 0xd6, 0x87, 0x0d, 0xfb, 0xcc, 0x12, 0x7d, 0x1f, 0x01, + 0x3b, 0xe1, 0x17, 0x34, 0x26, 0x19, 0x6e, 0xfa, 0xdd, 0x35, 0x6e, 0xfb, + 0xff, 0x29, 0x51, 0x9f, 0xff, 0x46, 0x51, 0xca, 0xd8, 0x34, 0xdb, 0xe6, + 0x0b, 0x07, 0xdc, 0x3a, 0x87, 0x9d, 0x8d, 0x09, 0x9f, 0xcc, 0x00, 0x45, + 0x97, 0x27, 0xe9, 0xb1, 0x0c, 0x78, 0x14, 0x5d, 0x8f, 0x3a, 0x78, 0xc3, + 0x06, 0x68, 0x79, 0x92, 0xe2, 0x45, 0xc0, 0xc8, 0x47, 0x0b, 0x2c, 0x05, + 0xd2, 0x59, 0xc4, 0xee, 0xf9, 0x7b, 0x1e, 0xef, 0x57, 0xf9, 0x15, 0xe5, + 0xf7, 0x1e, 0xa2, 0xd8, 0x32, 0xa5, 0x92, 0xe1, 0x87, 0x45, 0xcf, 0xea, + 0x64, 0x78, 0x5c, 0xf9, 0x68, 0x42, 0x7c, 0x1e, 0x7e, 0x2f, 0x8b, 0x1e, + 0xcd, 0xd8, 0xa9, 0x24, 0x49, 0xdf, 0x03, 0xf1, 0x1c, 0x0c, 0x96, 0xad, + 0xbb, 0x99, 0x57, 0x1c, 0x17, 0xfe, 0x07, 0xd6, 0x44, 0x16, 0x31, 0x1e, + 0xbe, 0x83, 0x5e, 0x82, 0xbd, 0x95, 0xcc, 0x3e, 0xa0, 0xc6, 0x96, 0xc8, + 0x64, 0x5c, 0x30, 0x7f, 0xc9, 0x49, 0x85, 0x8d, 0xca, 0xf5, 0xf0, 0x5d, + 0x1c, 0x17, 0xfa, 0xe1, 0x30, 0xdb, 0x30, 0x62, 0x5c, 0x69, 0x4e, 0xf8, + 0x21, 0xf8, 0x38, 0xff, 0xd3, 0x01, 0xfd, 0x6e, 0x03, 0x9c, 0x97, 0xfe, + 0x09, 0xbe, 0x67, 0x9e, 0xe7, 0x51, 0x95, 0x17, 0x3f, 0x44, 0x91, 0x1d, + 0xf8, 0x8b, 0x66, 0xef, 0xa8, 0xbf, 0x88, 0x61, 0xcd, 0xb2, 0xe5, 0x32, + 0xd3, 0xc6, 0xdb, 0x5b, 0xda, 0x71, 0xef, 0x6b, 0x19, 0xcd, 0xb0, 0x32, + 0xc5, 0xfb, 0x2f, 0xd0, 0xeb, 0x73, 0xa1, 0xf8, 0x29, 0xbc, 0x47, 0xc6, + 0x97, 0x10, 0x3a, 0x6f, 0x88, 0x75, 0x17, 0xe8, 0x30, 0xa3, 0x22, 0xbe, + 0x15, 0x79, 0xc2, 0x32, 0x16, 0xd6, 0xfa, 0xc9, 0x0f, 0xbf, 0x9a, 0xa3, + 0x73, 0x22, 0x5a, 0x45, 0xfe, 0xba, 0x8c, 0x2b, 0x42, 0xfe, 0x82, 0x07, + 0xfe, 0xc4, 0x97, 0x5c, 0xf3, 0xf7, 0xe9, 0x7c, 0xb7, 0x48, 0xb0, 0x9c, + 0x4f, 0xa3, 0x78, 0x8a, 0xc6, 0x3d, 0x1d, 0xb3, 0x70, 0xbf, 0xd7, 0x0a, + 0xb4, 0xeb, 0xd6, 0x19, 0xe0, 0x67, 0x12, 0x7b, 0x74, 0x01, 0x71, 0x5c, + 0xa3, 0x2a, 0x1e, 0xd1, 0xc2, 0xfb, 0x04, 0x3b, 0x0f, 0xfe, 0xbb, 0xcf, + 0xf2, 0x27, 0xe2, 0x0a, 0x27, 0x07, 0xa1, 0x27, 0xf5, 0x38, 0x8c, 0x33, + 0x53, 0x38, 0xee, 0x67, 0xbb, 0x4b, 0xeb, 0xb5, 0xd2, 0xa7, 0xc4, 0xb6, + 0x98, 0xda, 0x2f, 0xf8, 0x93, 0x46, 0x54, 0xbf, 0x01, 0x9b, 0xac, 0x5e, + 0xc0, 0xe9, 0xe3, 0xa2, 0xc7, 0xad, 0x62, 0x10, 0xdb, 0xc9, 0x59, 0xc2, + 0x3b, 0xb7, 0xd0, 0x77, 0xf3, 0x6e, 0xc0, 0x9e, 0xf7, 0xc8, 0x1d, 0xa3, + 0xf8, 0x94, 0x7a, 0xff, 0xcf, 0x9d, 0xda, 0xb7, 0x5d, 0x1e, 0xfb, 0xf6, + 0xbd, 0x41, 0x19, 0x03, 0xbb, 0x4b, 0x8d, 0xf1, 0xca, 0x53, 0xfd, 0xfb, + 0xa7, 0xe1, 0x4f, 0xaa, 0xd4, 0x51, 0x5c, 0x13, 0x7c, 0xa5, 0xde, 0xa7, + 0x1d, 0x62, 0x7e, 0x2a, 0xe9, 0xf8, 0xb8, 0x07, 0x1d, 0xf7, 0xce, 0x40, + 0x2f, 0xb9, 0x7d, 0x3a, 0x3e, 0xd6, 0x90, 0x8e, 0xff, 0x75, 0x50, 0xfa, + 0x54, 0xeb, 0xe9, 0x18, 0xb5, 0x3c, 0xc7, 0x8b, 0x8d, 0xfc, 0x57, 0xd8, + 0x07, 0xd4, 0xa4, 0xc3, 0xe7, 0x01, 0x58, 0x69, 0xbf, 0x07, 0xe2, 0x7e, + 0xc0, 0x47, 0xc4, 0x4e, 0xfe, 0x90, 0xe2, 0x8b, 0xb5, 0xb1, 0xd0, 0xcd, + 0xae, 0xf9, 0x96, 0xc7, 0x35, 0xd0, 0xc5, 0x41, 0x0b, 0x76, 0x48, 0xda, + 0xf4, 0x1a, 0x5e, 0xef, 0xf9, 0x0e, 0xe5, 0xec, 0x54, 0x9e, 0xe0, 0xa3, + 0x0e, 0xd2, 0x53, 0x88, 0x2b, 0x2b, 0x1f, 0xf0, 0xd1, 0x8c, 0x5c, 0xb7, + 0x79, 0x40, 0xe0, 0x03, 0xf4, 0xd5, 0x50, 0xc2, 0x9f, 0xe0, 0x3d, 0x95, + 0xfe, 0xdf, 0xe4, 0x6a, 0x48, 0xed, 0x13, 0x8f, 0xc5, 0xfd, 0x3c, 0xeb, + 0xfc, 0xb0, 0x3f, 0xf6, 0xd7, 0xd7, 0xcb, 0x79, 0xc5, 0x90, 0x05, 0x25, + 0xfa, 0x0f, 0x96, 0x73, 0xfe, 0x03, 0xa6, 0xe8, 0xb9, 0x70, 0xb9, 0x78, + 0x80, 0xf5, 0x47, 0xec, 0x21, 0x7c, 0x87, 0xda, 0xb7, 0xfb, 0xf6, 0x30, + 0x75, 0xed, 0x67, 0xa9, 0x6f, 0x90, 0xc3, 0x7a, 0xa3, 0x71, 0x00, 0xf9, + 0xe1, 0x16, 0x5f, 0x83, 0x5e, 0x51, 0x63, 0x56, 0x9c, 0x3a, 0xe0, 0x4f, + 0x40, 0x0f, 0x68, 0x2b, 0x5d, 0x45, 0x53, 0xb3, 0x82, 0xa6, 0xe2, 0x6b, + 0xb3, 0x8a, 0xa6, 0x66, 0x95, 0xff, 0x7c, 0x56, 0xd1, 0xd4, 0xac, 0xa2, + 0xa9, 0x59, 0x45, 0x53, 0xb3, 0x8c, 0xd7, 0xa3, 0xac, 0xaf, 0x42, 0xf7, + 0xd0, 0xfe, 0xcb, 0x2e, 0x4a, 0xe6, 0x70, 0x1e, 0xf2, 0xb8, 0x96, 0xae, + 0x7e, 0x6d, 0x58, 0xfb, 0x47, 0x0b, 0x32, 0xcf, 0x8e, 0x9f, 0x85, 0x3d, + 0x78, 0x98, 0xe1, 0x77, 0xcd, 0x37, 0xbf, 0x88, 0xb9, 0xfa, 0x28, 0x26, + 0x7a, 0xc0, 0x36, 0x51, 0xd4, 0xad, 0xe3, 0x9a, 0xa8, 0xeb, 0x92, 0xb6, + 0x5c, 0xaa, 0x61, 0x8d, 0x97, 0xc6, 0x8b, 0x69, 0xb5, 0x5f, 0xb5, 0x76, + 0x4e, 0x0b, 0x25, 0xb2, 0x80, 0x2b, 0x72, 0x21, 0x2d, 0xde, 0x1b, 0x01, + 0xa7, 0x94, 0xe9, 0x01, 0x83, 0xa3, 0x0a, 0x06, 0x4f, 0x8b, 0x35, 0x22, + 0x97, 0x10, 0x3e, 0xc8, 0xc6, 0x70, 0x48, 0x67, 0x46, 0xf9, 0x3e, 0x8c, + 0xfb, 0x07, 0x42, 0xcc, 0x83, 0xb6, 0x0b, 0x07, 0xf7, 0xda, 0x1b, 0xf1, + 0x9a, 0xed, 0xd6, 0xd3, 0x5c, 0x77, 0xc9, 0x8e, 0x90, 0x92, 0x1b, 0x52, + 0xef, 0xdd, 0xe5, 0xd8, 0x89, 0x14, 0xcf, 0xed, 0x2f, 0xc2, 0x7f, 0x39, + 0x44, 0x6d, 0x25, 0x3a, 0x12, 0x06, 0x3e, 0x77, 0xb1, 0x5d, 0xc9, 0x73, + 0x18, 0x2b, 0xd1, 0x85, 0xf0, 0x3e, 0xb6, 0x5d, 0xf6, 0xb3, 0x0e, 0x3a, + 0xca, 0xff, 0x4e, 0xc4, 0xef, 0xc3, 0xbc, 0x3a, 0xf8, 0xda, 0x7e, 0x32, + 0x7a, 0x52, 0x66, 0x2b, 0xeb, 0x07, 0x47, 0x2a, 0xf6, 0x88, 0x05, 0xff, + 0x1c, 0xeb, 0xb6, 0xc6, 0x5c, 0xb8, 0x5b, 0xd5, 0x9c, 0xc1, 0x87, 0x8d, + 0xf8, 0xd6, 0x3f, 0x97, 0x64, 0xaf, 0x80, 0x21, 0x75, 0xfc, 0xe3, 0x52, + 0x64, 0x08, 0xc7, 0x78, 0xe7, 0x90, 0x3d, 0x11, 0xf1, 0xfd, 0x58, 0xea, + 0xf2, 0x3e, 0xfb, 0x88, 0x7c, 0x3f, 0x80, 0x6d, 0x5a, 0x3e, 0x2f, 0xbc, + 0x97, 0x3a, 0x4f, 0x25, 0x5f, 0x15, 0x74, 0x50, 0xa2, 0x7f, 0x67, 0x9a, + 0x35, 0x09, 0xb1, 0x8c, 0x29, 0x51, 0x0b, 0x8d, 0x7c, 0xe5, 0xf9, 0x45, + 0x3d, 0x2f, 0x47, 0xed, 0xf5, 0xfd, 0xc8, 0x37, 0xcb, 0x16, 0x68, 0x73, + 0x99, 0x01, 0x3f, 0xda, 0xe8, 0xf2, 0x46, 0x4f, 0x50, 0xd4, 0x66, 0x77, + 0xb3, 0x8e, 0xa3, 0xf3, 0x92, 0xc7, 0xf8, 0xfe, 0x01, 0xf1, 0xbe, 0xb9, + 0xd8, 0x12, 0xc6, 0x35, 0xd3, 0xc8, 0x72, 0xe9, 0x21, 0xfe, 0x5d, 0xc4, + 0x11, 0x93, 0xd4, 0xaa, 0x62, 0x04, 0x1d, 0x2a, 0xae, 0x14, 0x62, 0x5a, + 0xaa, 0xd4, 0x1c, 0x8f, 0x94, 0x7d, 0x6d, 0xc0, 0xf1, 0x5a, 0x5f, 0xdb, + 0x73, 0x5b, 0xc8, 0x9b, 0xad, 0xf0, 0x1a, 0x39, 0xa5, 0x2d, 0xa4, 0x7c, + 0x88, 0xd6, 0x02, 0x6d, 0xb7, 0xb6, 0x6e, 0xc7, 0xd7, 0xb4, 0x36, 0xcf, + 0xac, 0x9f, 0x79, 0xc7, 0x69, 0x53, 0xf8, 0xd4, 0x4c, 0xf3, 0xb9, 0x36, + 0x96, 0xd9, 0xa8, 0x97, 0x02, 0xbc, 0xfc, 0x43, 0xa8, 0x37, 0x79, 0x32, + 0xd0, 0x4c, 0xab, 0xab, 0xc8, 0x79, 0x78, 0xfc, 0x2e, 0x99, 0xe7, 0xfb, + 0x08, 0xc3, 0x65, 0x3f, 0xcb, 0x37, 0x43, 0xc5, 0x70, 0x70, 0x0e, 0xbc, + 0x41, 0xf4, 0xfd, 0x0c, 0x3c, 0x3c, 0xde, 0xc6, 0x7a, 0xbd, 0x8c, 0x01, + 0x1c, 0xe4, 0x7b, 0x7f, 0x33, 0xf7, 0x08, 0xfc, 0x59, 0xe6, 0x61, 0xbe, + 0x7f, 0x8c, 0xf5, 0x81, 0x08, 0x35, 0xd3, 0xca, 0x6a, 0x33, 0xeb, 0xf5, + 0xcd, 0xac, 0x0f, 0x8c, 0x9a, 0x23, 0x3e, 0xf1, 0x2c, 0x51, 0xdb, 0xf2, + 0xe9, 0xc0, 0x7e, 0xc6, 0x41, 0x3c, 0xeb, 0x8b, 0xea, 0x59, 0xb5, 0xcf, + 0xb8, 0x55, 0xc2, 0xf1, 0x61, 0xff, 0xfa, 0x99, 0xab, 0x78, 0x2f, 0xd4, + 0xe2, 0x34, 0xeb, 0xbe, 0x41, 0xf1, 0x6e, 0x46, 0x63, 0x66, 0x86, 0xed, + 0x80, 0x30, 0x1f, 0x1f, 0xa1, 0x54, 0x31, 0x41, 0xbf, 0x57, 0x74, 0xfb, + 0x6a, 0x8f, 0xf0, 0x9c, 0x65, 0x6d, 0x7d, 0x0b, 0xcf, 0xeb, 0x7d, 0xa7, + 0x96, 0x67, 0xb4, 0x91, 0xff, 0x6b, 0x41, 0x6a, 0x7e, 0x11, 0xbe, 0x91, + 0x12, 0x65, 0xc3, 0xf6, 0x85, 0xeb, 0xe2, 0xbd, 0x1b, 0x16, 0xbd, 0x22, + 0xf2, 0x5b, 0xf9, 0x7a, 0xbe, 0xe7, 0x79, 0x8c, 0x7b, 0xc5, 0xa2, 0x2b, + 0x8e, 0x84, 0xf7, 0x9f, 0x05, 0x82, 0xe4, 0x7f, 0x1d, 0x39, 0x48, 0xd0, + 0xb5, 0xd6, 0xcf, 0x38, 0xfb, 0x98, 0x5f, 0xbf, 0x88, 0xeb, 0xf8, 0xf3, + 0x75, 0x1c, 0xb7, 0xf1, 0x3a, 0x21, 0x6f, 0x91, 0x77, 0x02, 0x3e, 0xb7, + 0x3f, 0x64, 0x0a, 0xfc, 0x3b, 0xc2, 0x38, 0xd5, 0x24, 0x7c, 0x81, 0xbd, + 0x18, 0xeb, 0x0c, 0xb2, 0x6e, 0xb0, 0x7e, 0x66, 0x7c, 0x1f, 0x8e, 0x23, + 0x3d, 0x7e, 0x86, 0x91, 0xc4, 0xa1, 0xb0, 0x78, 0xff, 0xa1, 0xeb, 0x2f, + 0x70, 0x70, 0x9c, 0x78, 0x3f, 0xa1, 0x3f, 0xf0, 0x7e, 0x9a, 0xe8, 0xb3, + 0xd4, 0x46, 0x71, 0x7e, 0x46, 0x2c, 0x27, 0xd7, 0x7d, 0xbe, 0xe8, 0x27, + 0xe9, 0x47, 0x6a, 0x1e, 0xd6, 0xef, 0x29, 0xa4, 0x7e, 0xdc, 0x5b, 0xd3, + 0x0a, 0xbe, 0x77, 0xd1, 0x8d, 0x5c, 0x07, 0xdd, 0x54, 0xb1, 0xa5, 0x1b, + 0xc2, 0xae, 0x62, 0x9e, 0x9c, 0xe8, 0xa2, 0xeb, 0xab, 0x4d, 0x44, 0xbd, + 0x6d, 0x22, 0xf6, 0x7b, 0x23, 0x97, 0xc7, 0xf3, 0x87, 0xa5, 0xdf, 0xa5, + 0x82, 0x23, 0x37, 0x3c, 0x70, 0xe4, 0x3d, 0x81, 0x23, 0xef, 0x6d, 0x81, + 0x23, 0x7b, 0x95, 0x2d, 0xd1, 0x46, 0xcd, 0x0a, 0x3f, 0x5e, 0x63, 0xfc, + 0x78, 0x81, 0xf1, 0xe3, 0x50, 0x03, 0xfc, 0x30, 0x6a, 0xf0, 0xe3, 0xb0, + 0xc0, 0x8f, 0x9f, 0x6d, 0x8a, 0x1f, 0x87, 0xfc, 0x9b, 0xf9, 0x82, 0x34, + 0x6e, 0x0e, 0xd0, 0x4a, 0xce, 0xa1, 0xd5, 0x45, 0x9b, 0x2d, 0x7b, 0xd8, + 0xe6, 0x88, 0x19, 0xce, 0x88, 0x7a, 0x97, 0x82, 0xc0, 0x2b, 0x96, 0xe3, + 0x33, 0xa8, 0x69, 0xaa, 0xdb, 0x03, 0x12, 0xef, 0xa5, 0x14, 0xf0, 0x97, + 0x7b, 0x12, 0xcb, 0xac, 0x9f, 0xf9, 0x73, 0xde, 0xc7, 0x2b, 0x6b, 0x81, + 0x00, 0x7e, 0xf3, 0xcf, 0x04, 0x69, 0x63, 0x8d, 0xed, 0x54, 0xc6, 0xb1, + 0xab, 0xb9, 0x21, 0xba, 0x92, 0x1b, 0xa0, 0x8d, 0xdc, 0x30, 0xbd, 0x93, + 0xc3, 0x33, 0x00, 0x73, 0x3e, 0x16, 0x30, 0x37, 0xe8, 0x60, 0x90, 0xc7, + 0xac, 0x0e, 0xd0, 0xfa, 0xaa, 0xc6, 0x57, 0xe0, 0x2a, 0xf6, 0x3f, 0xd2, + 0x23, 0xeb, 0xd0, 0xea, 0x71, 0x20, 0x56, 0x85, 0x03, 0xf2, 0x1a, 0xec, + 0xfd, 0x42, 0x7d, 0x0d, 0x6d, 0xab, 0x39, 0x83, 0x1c, 0xb8, 0x36, 0xb6, + 0xc9, 0x6d, 0xe1, 0x73, 0x3d, 0xe8, 0x87, 0x4e, 0x6b, 0xdc, 0x4d, 0x5d, + 0xbc, 0x07, 0x0e, 0xf2, 0x87, 0x86, 0x59, 0x3f, 0xed, 0x16, 0xfa, 0x68, + 0xd4, 0x09, 0x84, 0x62, 0x54, 0x3a, 0x6b, 0x38, 0xe8, 0x93, 0xf8, 0x08, + 0xdf, 0xcf, 0x50, 0x7e, 0x9e, 0x4e, 0x17, 0x3e, 0xd5, 0xea, 0x9e, 0x88, + 0xd1, 0x9e, 0xe0, 0x39, 0x43, 0x4e, 0x56, 0xe2, 0x22, 0x54, 0x8e, 0x8b, + 0xb4, 0xf2, 0xba, 0x25, 0x2d, 0xcd, 0x39, 0x3c, 0xae, 0xc8, 0xe3, 0x8a, + 0x88, 0xa9, 0xf1, 0xf9, 0x55, 0xc4, 0x73, 0x87, 0x68, 0x63, 0x11, 0x34, + 0x07, 0xff, 0x44, 0x25, 0x86, 0xba, 0xb1, 0x86, 0xf3, 0xf0, 0x51, 0x54, + 0x62, 0xa8, 0x1b, 0x2a, 0x86, 0xba, 0xb1, 0x36, 0x2d, 0xf8, 0xf0, 0x42, + 0x8e, 0x79, 0x40, 0xce, 0xaf, 0xf2, 0x07, 0xf7, 0xa9, 0x77, 0xf6, 0x9c, + 0x10, 0x3e, 0xe4, 0x1e, 0x67, 0x73, 0x18, 0x1e, 0xac, 0x83, 0xe1, 0xb4, + 0xd0, 0x83, 0xe2, 0x7c, 0xcf, 0x58, 0xee, 0x04, 0xc3, 0x73, 0x96, 0x69, + 0x69, 0xb7, 0xa2, 0x25, 0x1d, 0x93, 0xed, 0x26, 0xf5, 0xfe, 0x1f, 0xa1, + 0xeb, 0x4b, 0xfe, 0x33, 0x54, 0xc3, 0x7f, 0x28, 0x10, 0x1d, 0x97, 0xd7, + 0xa7, 0x8b, 0xaf, 0x0c, 0x6b, 0xff, 0x5b, 0x9a, 0xef, 0xbb, 0x90, 0xdb, + 0x49, 0x4c, 0x97, 0xe5, 0xa6, 0x67, 0xce, 0xe0, 0x76, 0x9f, 0xad, 0x71, + 0xe1, 0xc4, 0x6d, 0xe0, 0x93, 0xbc, 0x47, 0x05, 0x9f, 0xfe, 0x77, 0x16, + 0xc0, 0xb2, 0x93, 0x05, 0x98, 0x57, 0x84, 0x80, 0xf5, 0x03, 0x03, 0xb4, + 0x8e, 0x39, 0x00, 0x1e, 0x53, 0x68, 0x02, 0xe6, 0x19, 0xa7, 0xf5, 0x40, + 0xfb, 0xfb, 0x95, 0xc1, 0xeb, 0x5d, 0x1b, 0xa0, 0x67, 0x4f, 0x2d, 0xea, + 0x79, 0x2c, 0x07, 0xca, 0xa3, 0x4e, 0x2a, 0x0c, 0x24, 0xe6, 0x27, 0x90, + 0xff, 0x80, 0xfe, 0x00, 0xf9, 0x11, 0x98, 0x9f, 0x9c, 0x81, 0x72, 0xa0, + 0x35, 0x53, 0xcd, 0x6b, 0x40, 0xfa, 0x40, 0x61, 0x08, 0x2a, 0x53, 0x41, + 0x63, 0x1d, 0x40, 0xf6, 0x12, 0x21, 0x68, 0xd8, 0x01, 0x69, 0x20, 0xbb, + 0x79, 0x8a, 0x08, 0x98, 0x9f, 0x14, 0x20, 0xc4, 0xd0, 0x00, 0xcf, 0x4f, + 0xec, 0x40, 0x97, 0xc2, 0xdc, 0xf4, 0xff, 0xff, 0x31, 0x15, 0x16, 0x60, + 0xda, 0x03, 0xad, 0xf9, 0xfc, 0xfd, 0xff, 0x80, 0x08, 0x0b, 0x43, 0x0b, + 0x7c, 0xed, 0x9e, 0xb0, 0x3c, 0xa8, 0x9c, 0x5b, 0x00, 0x64, 0xb5, 0xc1, + 0xeb, 0x6d, 0x16, 0xf0, 0x7d, 0xc4, 0x0b, 0x18, 0x7e, 0x01, 0xcb, 0x95, + 0xff, 0xff, 0x97, 0xc2, 0xd5, 0x82, 0x00, 0x00, 0xd4, 0xc2, 0xcb, 0x42, + 0x60, 0x7c, 0x00, 0x00, 0x00 }; +static u32 bnx2_COM_b09FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_COM_b09FwRodata[(0x88/4) + 1] = { + 0x08001ad8, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14, 0x08001b14, + 0x08001a24, 0x08001b14, 0x08001a98, 0x08001b14, 0x080019ac, 0x08001b14, + 0x08001b14, 0x08001b14, 0x080019b8, 0x0, 0x08002a2c, 0x08002a7c, + 0x08002aac, 0x08002adc, 0x08002b0c, 0x0, 0x08005fac, 0x08005fac, + 0x08005fac, 0x08005fac, 0x08005fac, 0x08005fd8, 0x08005fd8, 0x08006018, + 0x08006024, 0x08006024, 0x08005fac, 0x0, 0x0 }; +static u32 bnx2_COM_b09FwBss[(0x88/4) + 1] = { 0x0 }; +static u32 bnx2_COM_b09FwSbss[(0x5c/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_com_fw_09 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x080000b0, + + .text_addr = 0x08000000, + .text_len = 0x7c5c, + .text_index = 0x0, + .gz_text = bnx2_COM_b09FwText, + .gz_text_len = sizeof(bnx2_COM_b09FwText), + + .data_addr = 0x08007d00, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_COM_b09FwData, + + .sbss_addr = 0x08007d00, + .sbss_len = 0x5c, + .sbss_index = 0x0, + .sbss = bnx2_COM_b09FwSbss, + + .bss_addr = 0x08007d60, + .bss_len = 0x88, + .bss_index = 0x0, + .bss = bnx2_COM_b09FwBss, + + .rodata_addr = 0x08007c60, + .rodata_len = 0x88, + .rodata_index = 0x0, + .rodata = bnx2_COM_b09FwRodata, +}; + -- cgit v1.2.3 From fc2a0bca102bab668badf2e5bfc3012441dd051f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:12:55 -0800 Subject: [BNX2]: New firmware to support 5709 (part 2). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2_fw2.h | 1259 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1259 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h index b6f4b20c70f1..66ff441bf2d4 100644 --- a/drivers/net/bnx2_fw2.h +++ b/drivers/net/bnx2_fw2.h @@ -1076,3 +1076,1262 @@ static struct fw_info bnx2_com_fw_09 = { .rodata = bnx2_COM_b09FwRodata, }; +static u8 bnx2_CP_b09FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x8e, 0xfc, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xbd, 0x7d, 0x0d, 0x74, + 0x5c, 0x57, 0x7d, 0xe7, 0xff, 0xdd, 0x79, 0x92, 0xc6, 0xb2, 0x2c, 0x3f, + 0xcb, 0x63, 0x65, 0x22, 0x0b, 0x7b, 0x46, 0x7a, 0xb2, 0x95, 0x58, 0x64, + 0xc7, 0xae, 0x00, 0x6d, 0x3b, 0x85, 0xe9, 0x48, 0xb2, 0x9d, 0x0f, 0x8a, + 0x4c, 0x44, 0x4f, 0x5a, 0xe8, 0x22, 0xc6, 0x76, 0x48, 0x80, 0xb2, 0x4e, + 0x09, 0x69, 0x80, 0x04, 0x0f, 0x23, 0xf9, 0x83, 0x74, 0xec, 0x51, 0x12, + 0xc5, 0x76, 0x4f, 0x73, 0x58, 0x55, 0x92, 0x1d, 0x43, 0xa7, 0x1e, 0x27, + 0x71, 0x68, 0xf6, 0x6c, 0x68, 0xb4, 0x4a, 0xe2, 0xa6, 0x3d, 0xd9, 0xd6, + 0xf4, 0x84, 0x6e, 0xda, 0x43, 0x77, 0x85, 0x71, 0x88, 0x4b, 0xb3, 0x4b, + 0xf8, 0x68, 0x61, 0xa1, 0xe5, 0xed, 0xef, 0x77, 0xef, 0x7d, 0xd2, 0xe8, + 0xc3, 0x09, 0xa1, 0xbb, 0xf5, 0x39, 0xcf, 0x6f, 0xde, 0xfd, 0xfc, 0xdf, + 0xff, 0xfd, 0x7f, 0xdf, 0x0f, 0xad, 0x17, 0xa9, 0x17, 0xfb, 0x6f, 0x15, + 0x9e, 0x6d, 0x89, 0x7d, 0xbb, 0xb7, 0x5e, 0xd7, 0x73, 0x1d, 0x7e, 0x6e, + 0x75, 0x57, 0x46, 0x95, 0xbc, 0x89, 0x7f, 0x89, 0x9f, 0xa1, 0x4c, 0x44, + 0xc4, 0x0b, 0xfb, 0xe2, 0x23, 0x51, 0x95, 0x1e, 0xfc, 0x64, 0xd6, 0x97, + 0x68, 0x24, 0x7d, 0xf6, 0xb3, 0xbb, 0x7d, 0x91, 0x4c, 0x79, 0x4b, 0xa2, + 0x57, 0xfe, 0x25, 0xc8, 0xc7, 0x5c, 0x61, 0xfa, 0x5b, 0xd2, 0xff, 0xfc, + 0x9f, 0xbe, 0xf2, 0x8e, 0xe4, 0x6b, 0xe3, 0x11, 0x89, 0x7a, 0xe9, 0x8f, + 0x89, 0xb7, 0x49, 0xa2, 0xad, 0xe9, 0x81, 0x4f, 0x3e, 0xbc, 0xf9, 0x6f, + 0x44, 0x1a, 0xc3, 0xb6, 0x2e, 0x07, 0x5f, 0xd9, 0x2c, 0xf9, 0x96, 0x74, + 0x7c, 0xc8, 0x4d, 0x7b, 0xf2, 0x74, 0x45, 0x06, 0x0a, 0xc5, 0xa8, 0x44, + 0xd2, 0x1d, 0x2f, 0xf5, 0x46, 0xf6, 0x07, 0x11, 0xdf, 0xf7, 0x7a, 0xa5, + 0xa1, 0x27, 0xdb, 0x8d, 0xf4, 0xf2, 0x56, 0x51, 0x7e, 0x54, 0xb2, 0x15, + 0x69, 0x50, 0xbe, 0x8f, 0x77, 0xbd, 0xa8, 0x74, 0xd2, 0xcb, 0x46, 0x5c, + 0x29, 0x54, 0x2e, 0xac, 0x30, 0x6d, 0x96, 0xec, 0xfb, 0x6f, 0xa2, 0xe6, + 0x8d, 0x36, 0x4b, 0x51, 0x99, 0x8d, 0xc4, 0x05, 0xfd, 0x00, 0xe6, 0x06, + 0x19, 0x2e, 0x25, 0x24, 0x5b, 0x64, 0xbf, 0xae, 0xe4, 0x3c, 0xf6, 0xd9, + 0x80, 0xfa, 0x2b, 0x9d, 0xe5, 0xcb, 0xb3, 0xec, 0x4b, 0x28, 0x9b, 0x40, + 0xb9, 0x56, 0x79, 0xbc, 0x12, 0x97, 0xc7, 0x2a, 0x31, 0x79, 0xb4, 0x72, + 0x87, 0x64, 0x50, 0xf7, 0x6c, 0x05, 0x7d, 0x97, 0x6a, 0xa5, 0x77, 0xac, + 0x5e, 0xb2, 0x63, 0xed, 0xf1, 0x9c, 0x04, 0xc1, 0x27, 0x52, 0x1f, 0x95, + 0xa1, 0x26, 0x94, 0x2f, 0x31, 0x2f, 0xbe, 0x20, 0x2f, 0x97, 0xda, 0xe2, + 0xe5, 0x94, 0x23, 0x99, 0xc1, 0x64, 0x7c, 0x48, 0xf1, 0xbb, 0x46, 0xb2, + 0x5d, 0xf8, 0x1e, 0x70, 0x25, 0xe2, 0x07, 0xc1, 0x1d, 0xa9, 0x26, 0xc0, + 0x91, 0x4c, 0x24, 0x14, 0xeb, 0xb2, 0x5e, 0x32, 0x9f, 0x50, 0x51, 0xc9, + 0x57, 0xae, 0x93, 0x44, 0x53, 0x10, 0xbc, 0x37, 0xe5, 0x21, 0x5d, 0xa4, + 0xb7, 0x28, 0xfb, 0x54, 0xda, 0x47, 0x9b, 0x92, 0x52, 0xe9, 0xb5, 0x18, + 0xc7, 0x16, 0xe0, 0xa9, 0x56, 0x32, 0x31, 0xc9, 0xa8, 0xb4, 0x24, 0x54, + 0x7a, 0x05, 0xd2, 0x1c, 0xa9, 0xf1, 0xa7, 0x2c, 0x9d, 0xac, 0xc6, 0xb7, + 0x0c, 0xa8, 0x74, 0xd3, 0xa2, 0xf4, 0x64, 0x42, 0xd4, 0x8f, 0xea, 0xd0, + 0x67, 0x67, 0x46, 0x31, 0x0d, 0x6f, 0x9d, 0x76, 0xfd, 0x32, 0x69, 0x1f, + 0x74, 0x16, 0xa6, 0x3d, 0xb5, 0x8a, 0xb0, 0x8a, 0xe2, 0xef, 0x28, 0xe0, + 0x6a, 0x41, 0xff, 0xed, 0x5e, 0x0d, 0xc6, 0x35, 0x90, 0x4a, 0x7a, 0xfd, + 0xea, 0xc5, 0x40, 0x9a, 0x09, 0x33, 0xf3, 0x14, 0xf2, 0x50, 0x34, 0x9d, + 0xc2, 0xbc, 0xb9, 0x72, 0x08, 0x63, 0xbb, 0x38, 0x96, 0xf4, 0xda, 0x14, + 0xde, 0x53, 0xfc, 0xdd, 0x34, 0x14, 0x49, 0x07, 0x41, 0x36, 0x35, 0x2e, + 0xb9, 0x72, 0xd2, 0x9b, 0x05, 0x70, 0xbd, 0x63, 0x71, 0x8c, 0x1f, 0xe3, + 0x88, 0x65, 0x92, 0x6b, 0xa4, 0xcb, 0xce, 0xcf, 0x5f, 0xa2, 0xef, 0x76, + 0xef, 0x0e, 0xd5, 0xee, 0xa5, 0x54, 0xd2, 0x9b, 0x90, 0x3f, 0xc4, 0x77, + 0x10, 0xec, 0x4a, 0x25, 0xe3, 0x79, 0xcc, 0xdd, 0xa5, 0x62, 0x4c, 0x5e, + 0x2e, 0x26, 0x41, 0xa9, 0xc9, 0xce, 0x49, 0xd9, 0x92, 0x9a, 0x04, 0xdc, + 0x05, 0x3c, 0x07, 0x99, 0x57, 0x46, 0x5e, 0x99, 0x75, 0x83, 0xe0, 0xe6, + 0xd4, 0x89, 0x60, 0xa8, 0xd9, 0xd0, 0xfe, 0xd3, 0x25, 0xcc, 0x2b, 0xe6, + 0xe9, 0xb1, 0x12, 0xe6, 0xb5, 0x84, 0x39, 0xd5, 0xf3, 0xdf, 0x89, 0xf9, + 0x27, 0x8d, 0x90, 0x3e, 0xb6, 0x59, 0x7a, 0x7d, 0xb7, 0x7d, 0x8b, 0x64, + 0x4b, 0x8e, 0x64, 0x53, 0x3f, 0x09, 0x32, 0x9a, 0x27, 0xc4, 0xe9, 0x2d, + 0x91, 0x26, 0x6b, 0x00, 0x2b, 0x3f, 0x7f, 0xdd, 0x96, 0x8b, 0x3a, 0x18, + 0x06, 0xe7, 0x83, 0xf9, 0x51, 0xe5, 0xd7, 0xd9, 0xfc, 0x90, 0xf6, 0xf9, + 0x0f, 0x74, 0xe7, 0xcf, 0x97, 0xcb, 0x92, 0x36, 0x2b, 0x22, 0xb9, 0x07, + 0x03, 0xe9, 0x4d, 0x01, 0x5f, 0x6c, 0xd3, 0x4b, 0x89, 0xae, 0xeb, 0xb1, + 0x8c, 0x2e, 0x8b, 0x7f, 0x3f, 0xae, 0x41, 0x1f, 0x4e, 0x5f, 0x69, 0xbe, + 0x6e, 0x5f, 0xe9, 0x85, 0x98, 0x85, 0x0f, 0xdf, 0x3d, 0x4e, 0xb6, 0xf2, + 0x77, 0x76, 0x8e, 0xc3, 0x71, 0x74, 0x2d, 0x43, 0xe3, 0x2e, 0xf8, 0xc1, + 0x93, 0x5c, 0xb1, 0x07, 0xfd, 0xc6, 0xf0, 0x0e, 0x82, 0x91, 0x54, 0x26, + 0xe9, 0x4a, 0x1a, 0xdf, 0x03, 0x98, 0xaf, 0x0e, 0xe0, 0x4f, 0xdc, 0xec, + 0xe6, 0x94, 0xf4, 0x55, 0x40, 0x7b, 0x95, 0x37, 0x96, 0x14, 0x7a, 0x0c, + 0xa9, 0x7f, 0xb1, 0xb8, 0x61, 0x3f, 0x7c, 0xbb, 0x32, 0x02, 0xfa, 0x28, + 0x8c, 0xf9, 0x32, 0x5c, 0x9c, 0xf6, 0x94, 0x24, 0x41, 0xbb, 0x69, 0xe9, + 0xad, 0xf8, 0x52, 0x28, 0xe2, 0x5d, 0x6a, 0x07, 0xfd, 0xba, 0x92, 0x89, + 0x9b, 0x39, 0x29, 0x14, 0x7f, 0x09, 0xe3, 0x02, 0x8e, 0x7d, 0xfe, 0xee, + 0xb1, 0xb0, 0x80, 0xf7, 0xbb, 0x53, 0x1a, 0x3f, 0x6f, 0x0e, 0x06, 0xf6, + 0x8d, 0x31, 0x60, 0x9c, 0x85, 0xb2, 0x8b, 0x77, 0x0c, 0xef, 0x90, 0x16, + 0xe3, 0x80, 0xa9, 0x55, 0x86, 0x41, 0x8b, 0xbd, 0x82, 0xdf, 0x53, 0x84, + 0x91, 0xfd, 0xb6, 0xe8, 0xdf, 0xc3, 0x63, 0x1b, 0xf4, 0x77, 0x6e, 0xa0, + 0x45, 0xf2, 0x53, 0xe1, 0x58, 0x28, 0x0f, 0x28, 0x03, 0x92, 0x87, 0x45, + 0x28, 0x13, 0x82, 0xe0, 0xc1, 0x14, 0xe5, 0x42, 0x10, 0x3c, 0x96, 0xa2, + 0x9c, 0x38, 0x07, 0xfe, 0xa7, 0x6c, 0x20, 0xaf, 0xae, 0x55, 0x9c, 0x83, + 0x6c, 0x11, 0x7d, 0x40, 0x4e, 0xe4, 0xba, 0x4e, 0x40, 0x6e, 0x50, 0xae, + 0x5c, 0xf8, 0x44, 0xd6, 0xcf, 0xc7, 0x23, 0x1a, 0x0f, 0x98, 0x6f, 0xc8, + 0xbc, 0x8c, 0x86, 0xbc, 0x4d, 0x0a, 0x5d, 0xa3, 0xb6, 0xcc, 0x65, 0x5d, + 0xc6, 0x5d, 0x52, 0xe6, 0x76, 0x65, 0xf8, 0xae, 0x15, 0xf3, 0xb1, 0x42, + 0x11, 0x4f, 0x6d, 0x9b, 0xf8, 0x2d, 0xd1, 0x9a, 0xf4, 0x97, 0x90, 0x37, + 0x7d, 0xd7, 0x49, 0x7f, 0xb9, 0xbc, 0x59, 0x77, 0x69, 0xde, 0x88, 0xb8, + 0x7e, 0xb2, 0x73, 0x97, 0x9a, 0x01, 0x3d, 0x05, 0xc1, 0xc9, 0x54, 0x98, + 0xfe, 0x8f, 0xee, 0xd2, 0x3e, 0x12, 0x35, 0x4b, 0xd3, 0xee, 0x5d, 0x26, + 0xed, 0xc4, 0x32, 0x69, 0x1b, 0x6a, 0x97, 0xa6, 0xbd, 0x7f, 0x99, 0xb4, + 0xfb, 0x97, 0x49, 0xfb, 0x5f, 0xcb, 0xa4, 0x7d, 0x67, 0x99, 0xb4, 0xef, + 0x2d, 0x93, 0xd6, 0x52, 0xb7, 0x34, 0xcd, 0x05, 0x3f, 0x6d, 0x92, 0x42, + 0xec, 0x73, 0x1c, 0xbb, 0xc5, 0xcd, 0xfe, 0xc8, 0x52, 0xdc, 0xd4, 0xa0, + 0x5c, 0xeb, 0xa2, 0x72, 0x53, 0xcb, 0x94, 0xab, 0x45, 0xb9, 0xa6, 0x45, + 0xe5, 0x92, 0xcb, 0xe0, 0xba, 0x4e, 0xeb, 0xaf, 0x85, 0xe5, 0x0a, 0xcb, + 0x94, 0x63, 0xfa, 0x1e, 0xdb, 0xcf, 0x16, 0x68, 0x99, 0xd7, 0x9b, 0xaf, + 0x5a, 0x91, 0x66, 0xa6, 0xb7, 0x42, 0x47, 0xac, 0x50, 0x86, 0xdf, 0x29, + 0x5b, 0x98, 0xe6, 0x81, 0xee, 0xa3, 0xa0, 0x3b, 0xca, 0x47, 0xf0, 0x91, + 0x4f, 0xfe, 0x5d, 0x25, 0x43, 0xb1, 0x2d, 0xde, 0x2f, 0xa8, 0x06, 0xd0, + 0x58, 0xd2, 0x4b, 0x28, 0xf2, 0x97, 0xe4, 0x23, 0x69, 0x3f, 0xdf, 0x2b, + 0x2a, 0xa6, 0x24, 0x90, 0xbe, 0x94, 0x6a, 0x52, 0xb2, 0x1f, 0xfc, 0x93, + 0x81, 0x4e, 0xda, 0x15, 0xf4, 0x6a, 0x1e, 0x32, 0x65, 0xaf, 0x2c, 0x2b, + 0x7d, 0x39, 0x48, 0x19, 0x97, 0xce, 0xdc, 0x95, 0xf5, 0xa7, 0x7b, 0x6a, + 0x41, 0xb3, 0x17, 0x51, 0x67, 0x07, 0x6a, 0xee, 0x2d, 0xbb, 0xd2, 0x57, + 0xee, 0x04, 0x2f, 0x38, 0x72, 0xde, 0x5f, 0x2d, 0xe7, 0x53, 0x28, 0x5b, + 0x89, 0xc8, 0x4c, 0xcc, 0x91, 0x19, 0x7c, 0x67, 0x53, 0xc8, 0xab, 0x84, + 0xbc, 0xd5, 0x29, 0x07, 0x4a, 0xbe, 0x1c, 0x2e, 0xfd, 0x92, 0x0a, 0xf5, + 0x56, 0x7f, 0x6a, 0xa5, 0x9c, 0xf6, 0x4c, 0xdb, 0x3b, 0xfc, 0x69, 0x68, + 0x4c, 0x57, 0x2e, 0xfa, 0xc9, 0xf8, 0x8c, 0xe6, 0x89, 0x1f, 0x06, 0x7d, + 0x68, 0x67, 0xc2, 0x4f, 0x7a, 0x7f, 0x8a, 0xef, 0xa1, 0x32, 0xed, 0x90, + 0xf9, 0xb6, 0x86, 0xd1, 0xd6, 0xa1, 0xd2, 0x2a, 0xf9, 0xb0, 0xad, 0xbf, + 0xdd, 0x9f, 0xee, 0x04, 0xcf, 0x79, 0xa7, 0x28, 0x23, 0x8a, 0x80, 0x6b, + 0x10, 0xbc, 0x8d, 0xba, 0xcf, 0x69, 0x39, 0x05, 0xbb, 0xa5, 0xb8, 0x1a, + 0x72, 0xf7, 0x1f, 0x83, 0x0f, 0xc7, 0x58, 0x9e, 0x69, 0xd4, 0x25, 0x32, + 0xaa, 0xd2, 0x90, 0x09, 0xdd, 0x94, 0x85, 0x09, 0xc8, 0x41, 0xc8, 0x96, + 0xd2, 0x4f, 0x83, 0x8c, 0x5b, 0x2d, 0xdf, 0x24, 0x3f, 0x5f, 0x86, 0x69, + 0x09, 0x23, 0x2f, 0x4b, 0xb3, 0x73, 0xb2, 0x22, 0x0f, 0xf9, 0xf2, 0x74, + 0x85, 0x72, 0xe1, 0x7a, 0xf0, 0x68, 0xab, 0xf4, 0x15, 0x93, 0xf9, 0x8c, + 0x6c, 0xc2, 0xfc, 0x7d, 0x1e, 0x73, 0xea, 0xe2, 0xb9, 0xaf, 0x5e, 0x1a, + 0x53, 0xd0, 0xcd, 0x4c, 0x47, 0xa3, 0xcd, 0x51, 0xc8, 0xa8, 0xdf, 0x03, + 0x1e, 0x86, 0x39, 0xe7, 0xf1, 0x6c, 0xc4, 0x19, 0xa0, 0x3d, 0x32, 0x40, + 0xfd, 0x50, 0x66, 0xdb, 0x84, 0x37, 0x6e, 0x7f, 0x47, 0xb5, 0x8c, 0x31, + 0xbf, 0x1b, 0xf0, 0x3b, 0x61, 0x7f, 0x7b, 0xf8, 0xed, 0xdb, 0xdf, 0x31, + 0xfc, 0xee, 0xb4, 0xbf, 0xa1, 0x5b, 0x8b, 0x5d, 0xfa, 0xf7, 0x48, 0x69, + 0xfb, 0x76, 0xe5, 0x5f, 0x27, 0xb9, 0xa9, 0x56, 0x39, 0x50, 0xf4, 0xad, + 0x6c, 0xc1, 0x23, 0x4f, 0x3a, 0x66, 0x9c, 0x80, 0x9b, 0xb2, 0xb3, 0x94, + 0x77, 0x06, 0x08, 0x3f, 0x68, 0xa0, 0xb7, 0xb8, 0xc5, 0x5b, 0x23, 0xa4, + 0x81, 0x11, 0xa7, 0xb7, 0xe2, 0x64, 0x60, 0xaf, 0xc5, 0x87, 0xe5, 0x30, + 0x7e, 0x8b, 0x17, 0x49, 0x3f, 0x89, 0xb7, 0xc1, 0x01, 0xf5, 0xce, 0x70, + 0x89, 0xf2, 0xd2, 0xc7, 0xd8, 0x13, 0x72, 0x6e, 0x81, 0x0d, 0x45, 0x5c, + 0x28, 0xc9, 0x8d, 0x25, 0x4f, 0xe4, 0x25, 0x99, 0x1f, 0x07, 0x43, 0xec, + 0x4a, 0xb9, 0xf2, 0xde, 0x14, 0x68, 0xf7, 0x3a, 0x47, 0xb6, 0x5f, 0xe7, + 0xc2, 0xe6, 0xf1, 0xc7, 0xb7, 0x83, 0xfe, 0x31, 0xcf, 0x9a, 0x1e, 0xd4, + 0x19, 0x81, 0x9d, 0x08, 0x6c, 0x9f, 0xe9, 0xea, 0x1b, 0x2e, 0xe6, 0x3e, + 0xa6, 0xd2, 0xfb, 0x3e, 0x95, 0xed, 0xbe, 0x46, 0x72, 0x83, 0x0a, 0x38, + 0x6a, 0x1e, 0x82, 0x1e, 0xc4, 0xb8, 0x82, 0x00, 0xf4, 0x0c, 0x79, 0x7e, + 0xf3, 0xcd, 0x91, 0x74, 0x8d, 0xf4, 0x0e, 0x36, 0xa3, 0x0e, 0xf3, 0x88, + 0xaf, 0xaf, 0xa2, 0x9d, 0x64, 0xa2, 0x4f, 0xe4, 0x9e, 0x91, 0xee, 0x59, + 0x67, 0x78, 0xf4, 0x37, 0xc0, 0x93, 0x5b, 0x51, 0xff, 0x01, 0xd4, 0x7f, + 0xcd, 0x29, 0x8c, 0xfd, 0xc8, 0x19, 0x1e, 0xfb, 0x9e, 0x33, 0x32, 0xb6, + 0x61, 0x43, 0x7f, 0xcf, 0x86, 0x0d, 0xbb, 0x7b, 0x5c, 0x99, 0x00, 0x8f, + 0x65, 0xbc, 0x0d, 0x1b, 0x46, 0x7a, 0xba, 0x80, 0x83, 0x2d, 0x5e, 0x9f, + 0xf8, 0xde, 0x76, 0x01, 0xff, 0xc4, 0xd8, 0x67, 0x14, 0xf9, 0x49, 0xe4, + 0xb3, 0x7e, 0x5c, 0xe7, 0xf7, 0xca, 0x96, 0x78, 0x93, 0xb0, 0xff, 0x88, + 0x2d, 0x53, 0x13, 0x91, 0xfa, 0x07, 0xec, 0xfc, 0x66, 0x9c, 0x1a, 0x9f, + 0xe9, 0x1c, 0x0b, 0xd3, 0x39, 0xb7, 0x7f, 0x67, 0x6d, 0xd5, 0xd5, 0x48, + 0xe7, 0x37, 0x71, 0x46, 0xbc, 0xd0, 0xc6, 0xa8, 0xd1, 0xb6, 0x61, 0xae, + 0x48, 0x9a, 0x71, 0x65, 0x4f, 0xd1, 0x41, 0x1d, 0xd0, 0xc5, 0x19, 0xfb, + 0x1c, 0x05, 0x6c, 0x83, 0x68, 0xeb, 0xe8, 0x21, 0xd4, 0xa3, 0xcc, 0x48, + 0x76, 0x8a, 0xfa, 0x00, 0xca, 0x6c, 0xf1, 0xd6, 0x0a, 0x6d, 0x89, 0x3b, + 0x25, 0x57, 0x22, 0x7f, 0x77, 0x00, 0x9e, 0xa8, 0x24, 0x9a, 0xf1, 0x5d, + 0x81, 0x4d, 0xf1, 0x60, 0x8d, 0x58, 0xdb, 0x45, 0xe6, 0x6d, 0x91, 0x3b, + 0x94, 0xc0, 0xde, 0x18, 0x9a, 0x5c, 0x8f, 0x72, 0x0e, 0xf0, 0x42, 0xfb, + 0x03, 0xb4, 0x36, 0x99, 0x91, 0xec, 0x26, 0xf0, 0xc9, 0xa4, 0x87, 0x6f, + 0xc0, 0x35, 0xf9, 0x16, 0xbc, 0x23, 0xfa, 0xdb, 0xc0, 0x09, 0xbc, 0xa6, + 0x22, 0x56, 0x67, 0x75, 0xa1, 0xef, 0xf7, 0x48, 0x76, 0x34, 0x4e, 0x5b, + 0x62, 0x75, 0xd6, 0xcf, 0x40, 0xd7, 0x2b, 0x28, 0x41, 0x8c, 0x61, 0xd2, + 0x81, 0x3c, 0xa9, 0x95, 0xdd, 0x8f, 0xe0, 0xf7, 0x83, 0xc6, 0xe6, 0xdd, + 0x3d, 0xc9, 0x7e, 0x1a, 0x00, 0x13, 0x6c, 0x90, 0x47, 0x60, 0x9b, 0x3e, + 0x02, 0x1b, 0xe4, 0x91, 0x66, 0x3c, 0x1c, 0x1b, 0xdb, 0x9f, 0x59, 0x03, + 0x31, 0xa9, 0xbf, 0x73, 0xa4, 0x57, 0xd8, 0xea, 0xb9, 0x62, 0xca, 0x94, + 0x2f, 0x76, 0xeb, 0xb7, 0xa1, 0xeb, 0x1e, 0xfb, 0x3b, 0xae, 0xf9, 0x3a, + 0xdf, 0x04, 0x9a, 0xaf, 0x74, 0x69, 0x99, 0x93, 0xf5, 0xf1, 0x86, 0xcd, + 0x99, 0x69, 0xe2, 0x18, 0xe3, 0x36, 0x2d, 0xae, 0xd3, 0x12, 0x4d, 0xd6, + 0xde, 0x28, 0x59, 0x5b, 0x03, 0xb8, 0x19, 0x6a, 0x06, 0xc4, 0x94, 0xcf, + 0x12, 0xe2, 0x93, 0x32, 0x00, 0xf4, 0x0b, 0x9b, 0xe2, 0xdc, 0x15, 0xe5, + 0xdf, 0xac, 0xb6, 0xb1, 0xce, 0x56, 0x48, 0xc7, 0xa4, 0xed, 0x20, 0xb8, + 0x3f, 0x55, 0x87, 0xf6, 0xc9, 0xf3, 0xb0, 0x40, 0x8e, 0x02, 0x26, 0x60, + 0xa2, 0xc6, 0x3f, 0xab, 0x69, 0xa0, 0xd6, 0x27, 0x0d, 0x57, 0xf3, 0x97, + 0xe8, 0xf1, 0x9e, 0x05, 0x8f, 0xc1, 0xbe, 0x81, 0xfd, 0xd6, 0x01, 0xdb, + 0x98, 0x7d, 0x1c, 0xe6, 0xb7, 0xa7, 0xc0, 0x53, 0xd9, 0x39, 0x9e, 0x12, + 0x99, 0x28, 0x12, 0x37, 0xa1, 0x5d, 0xc7, 0x79, 0x26, 0x7e, 0x32, 0x18, + 0x33, 0xdf, 0x7d, 0x16, 0x4f, 0x3b, 0x2d, 0x9e, 0x6e, 0xb2, 0xef, 0x11, + 0xbc, 0x69, 0xe3, 0x0d, 0xe0, 0xcd, 0xf9, 0x19, 0xc4, 0x9b, 0xbc, 0x75, + 0x0b, 0xde, 0x28, 0x5b, 0xca, 0xc8, 0x6e, 0x6d, 0x87, 0x45, 0xe4, 0x57, + 0xb4, 0x6c, 0xfb, 0x02, 0xe6, 0xb2, 0x48, 0xfa, 0x95, 0x7c, 0x2c, 0x02, + 0x9c, 0x14, 0xf0, 0xfb, 0x4e, 0xd7, 0xd0, 0x2a, 0x71, 0xb2, 0xc0, 0x57, + 0xaa, 0x82, 0x29, 0x66, 0xe5, 0x5c, 0x42, 0xdb, 0xfa, 0xb9, 0xe2, 0x07, + 0x34, 0x5c, 0xb7, 0x42, 0xde, 0xe5, 0x45, 0x35, 0x43, 0x37, 0x80, 0x16, + 0x54, 0x0c, 0x9a, 0x2b, 0x78, 0x06, 0x7a, 0x29, 0x37, 0x49, 0xdb, 0xb8, + 0x8d, 0x7e, 0x49, 0x34, 0xd7, 0xd5, 0x48, 0x3a, 0x52, 0x0a, 0xf6, 0x17, + 0xbe, 0x55, 0xae, 0x4b, 0xd3, 0xa9, 0xa3, 0xfc, 0x98, 0xb6, 0x7f, 0x5d, + 0x1f, 0xd2, 0xd6, 0xf8, 0xbd, 0xae, 0xf2, 0xd7, 0x2e, 0x4e, 0x4b, 0x50, + 0x0f, 0xa3, 0x5e, 0x22, 0xd7, 0xd5, 0x4c, 0x1e, 0xf3, 0x40, 0xbf, 0x19, + 0xe5, 0x6b, 0xdf, 0x27, 0xaf, 0xba, 0x57, 0x2f, 0x2a, 0xaf, 0xdf, 0x8e, + 0xfd, 0x76, 0xed, 0xdb, 0xb3, 0xef, 0x84, 0x7d, 0xe7, 0xdd, 0x6e, 0xbe, + 0x1d, 0x71, 0xd3, 0x7c, 0x83, 0x92, 0xd3, 0x6c, 0x43, 0xf3, 0x95, 0x95, + 0x33, 0x1d, 0x5e, 0x41, 0xc8, 0x57, 0x9f, 0x93, 0x5b, 0x27, 0x8d, 0xfc, + 0xdd, 0x0e, 0x19, 0x04, 0xff, 0xcc, 0x9b, 0x11, 0xc0, 0x3f, 0x98, 0x96, + 0x5b, 0x2b, 0xc4, 0xdb, 0xef, 0x02, 0x7f, 0x60, 0xe2, 0x7a, 0xea, 0x74, + 0xca, 0xdd, 0x3b, 0x61, 0xf7, 0xa2, 0x7c, 0x91, 0x38, 0x1f, 0xd2, 0x73, + 0x53, 0x28, 0xee, 0xd1, 0x73, 0x73, 0xb0, 0x38, 0x03, 0xfc, 0xdc, 0x06, + 0xba, 0x0f, 0x82, 0x99, 0x54, 0x01, 0x94, 0xf3, 0x11, 0xfc, 0x86, 0x1d, + 0x50, 0xfc, 0x18, 0xf2, 0x1b, 0xa5, 0x30, 0x4a, 0x9e, 0x73, 0x2d, 0x0f, + 0xbf, 0x13, 0xfc, 0x14, 0x45, 0xbb, 0x48, 0xeb, 0xe6, 0xef, 0x9f, 0x20, + 0x0f, 0xef, 0x49, 0x4c, 0x62, 0x33, 0x6d, 0x1d, 0xf6, 0xcd, 0xb9, 0xe3, + 0x9c, 0xc5, 0xb4, 0x2c, 0x3f, 0x3b, 0x37, 0x6f, 0x97, 0xe7, 0xe8, 0x36, + 0x4f, 0x1f, 0x8f, 0xf9, 0x1a, 0x56, 0xd2, 0xfd, 0xb7, 0xb4, 0x5c, 0x72, + 0x8f, 0xce, 0xac, 0x30, 0xef, 0xc5, 0x75, 0x39, 0xe7, 0xd5, 0x34, 0x48, + 0xbf, 0x25, 0xd9, 0x93, 0x07, 0x3f, 0x61, 0x9c, 0xd2, 0xa7, 0x7d, 0x1d, + 0xd2, 0x04, 0x69, 0x60, 0xdc, 0xd2, 0xe6, 0x94, 0xa5, 0xcd, 0x27, 0xf1, + 0xc6, 0x53, 0xba, 0x60, 0x69, 0xf3, 0x29, 0xbc, 0xf1, 0x94, 0x5e, 0x9c, + 0xe3, 0xe3, 0x5e, 0xf8, 0x72, 0xdb, 0xa1, 0xdf, 0x76, 0x57, 0x40, 0xbf, + 0xe0, 0xbb, 0x1c, 0x7c, 0x80, 0x5c, 0x69, 0x1f, 0xde, 0xec, 0x67, 0xa3, + 0x6d, 0x3f, 0x23, 0x7b, 0x4a, 0x01, 0xc6, 0x78, 0x37, 0xc6, 0xfb, 0x39, + 0xbc, 0x3f, 0xa3, 0xe5, 0x8c, 0xf2, 0x0f, 0x5b, 0x79, 0xf5, 0x79, 0xbc, + 0xdb, 0xe3, 0x07, 0xa5, 0xdd, 0x8b, 0xc8, 0x34, 0xda, 0xfa, 0xba, 0xec, + 0xa9, 0xcc, 0xe2, 0xb9, 0x84, 0xe7, 0x55, 0x3c, 0x97, 0xd1, 0xde, 0x0b, + 0x48, 0x5f, 0x29, 0xd3, 0x5e, 0x3d, 0xca, 0xbf, 0x86, 0xdf, 0xcf, 0xcb, + 0xd0, 0x23, 0x2f, 0xe1, 0xf9, 0x01, 0xf2, 0x9f, 0x45, 0xfd, 0x60, 0xf5, + 0x8c, 0x4f, 0x19, 0xf6, 0x9c, 0x6d, 0x3b, 0xe5, 0xe4, 0x2a, 0xa0, 0xe9, + 0xd2, 0x00, 0xfa, 0xde, 0xa3, 0x79, 0xa6, 0x0f, 0x32, 0x3f, 0x07, 0x19, + 0x37, 0xa4, 0x61, 0x6a, 0x07, 0x7c, 0x79, 0xcc, 0x05, 0xde, 0x93, 0xb5, + 0x32, 0x1b, 0xa3, 0x1d, 0x79, 0x93, 0x2e, 0x9f, 0x2b, 0x35, 0x69, 0xbb, + 0x7a, 0x7c, 0x09, 0xff, 0xd0, 0xef, 0x0a, 0xe5, 0x81, 0x91, 0xc6, 0x13, + 0x45, 0xca, 0x02, 0xe8, 0x9f, 0xe2, 0x08, 0xde, 0xb5, 0x5a, 0x26, 0x14, + 0x24, 0x94, 0x07, 0xac, 0x47, 0x99, 0x50, 0x2d, 0x77, 0x28, 0x6b, 0x28, + 0x7b, 0x28, 0x4b, 0xcc, 0x7c, 0xec, 0x7e, 0x90, 0x32, 0x1c, 0xb4, 0x10, + 0xa3, 0xfd, 0xe1, 0x19, 0x1f, 0x64, 0xec, 0x3e, 0x2b, 0x4f, 0x47, 0xf5, + 0x5c, 0xec, 0x29, 0xaa, 0x98, 0x2b, 0xa7, 0x91, 0x86, 0xe7, 0xf8, 0xc3, + 0x78, 0x7f, 0x49, 0xf6, 0xe0, 0xc9, 0x1d, 0xff, 0x02, 0x7e, 0x73, 0x6e, + 0xca, 0x28, 0x87, 0xa7, 0x74, 0x02, 0x6f, 0x3c, 0xa5, 0x31, 0x2b, 0x47, + 0xc6, 0xad, 0x1c, 0xe1, 0x9c, 0xde, 0x04, 0x3c, 0x70, 0x7c, 0x4a, 0xc7, + 0x17, 0xc0, 0xcf, 0x4e, 0x6e, 0xf2, 0x5d, 0xd6, 0x8f, 0x6d, 0x14, 0xc3, + 0x83, 0x78, 0x3a, 0xc9, 0xcf, 0x0d, 0xda, 0x0e, 0xce, 0x69, 0xda, 0xfd, + 0x2b, 0xd7, 0xf0, 0x62, 0xcc, 0xe8, 0x14, 0xaf, 0x59, 0x34, 0xef, 0xcf, + 0xe1, 0x31, 0x63, 0xf1, 0xc8, 0xdf, 0xca, 0xfe, 0x86, 0xdc, 0x82, 0x4d, + 0x9b, 0xf5, 0x7d, 0xcc, 0x03, 0xc6, 0x72, 0x7c, 0x14, 0x7d, 0x3b, 0xb2, + 0xdb, 0xa7, 0x0c, 0x67, 0x0c, 0x81, 0xe3, 0x63, 0xbb, 0x48, 0xd7, 0x38, + 0x48, 0xc9, 0xbc, 0x6f, 0x7e, 0x13, 0xe6, 0x2c, 0x23, 0x7b, 0x4b, 0xf7, + 0x6a, 0x5f, 0xb9, 0xf6, 0x68, 0x93, 0xf5, 0x73, 0xc2, 0x72, 0xa0, 0xd5, + 0x18, 0x6d, 0x9b, 0x2f, 0xc5, 0x0c, 0xcd, 0xf3, 0x37, 0xe5, 0x73, 0xb5, + 0xbc, 0x37, 0x76, 0x4d, 0x61, 0x81, 0xac, 0xa3, 0x6d, 0x81, 0x39, 0x2b, + 0x57, 0xe3, 0x9d, 0xbe, 0x3b, 0xf9, 0x8a, 0xfc, 0x74, 0x10, 0x3c, 0xf1, + 0x5d, 0xcb, 0xfb, 0xf4, 0x35, 0xd8, 0xe7, 0x62, 0x7e, 0xf2, 0x60, 0xfb, + 0xba, 0x72, 0x0a, 0xb6, 0xdb, 0xf6, 0xb9, 0x36, 0xae, 0x06, 0x3c, 0x51, + 0x79, 0xa4, 0xd8, 0x20, 0x93, 0x45, 0xd5, 0x1c, 0xb1, 0xb2, 0x33, 0x22, + 0x09, 0x4d, 0xdf, 0xb4, 0xef, 0x7a, 0xc7, 0x22, 0x96, 0xee, 0xd6, 0xd5, + 0x48, 0xfd, 0xef, 0x42, 0xc7, 0xa6, 0xa1, 0x63, 0x1b, 0xa1, 0x83, 0x17, + 0xcb, 0x88, 0x35, 0x35, 0x4b, 0x65, 0x04, 0xeb, 0x24, 0xe1, 0x75, 0x1f, + 0x44, 0xbd, 0x90, 0xfe, 0xa2, 0x9a, 0xd6, 0x72, 0x92, 0x77, 0xb6, 0x57, + 0x46, 0x9c, 0x1d, 0x95, 0xc5, 0x3a, 0x68, 0x8b, 0xe7, 0x8a, 0x81, 0xf5, + 0x91, 0x22, 0x6d, 0xd4, 0x64, 0x2a, 0x0b, 0x9c, 0xec, 0x00, 0xcc, 0xcf, + 0x8c, 0xc2, 0x4f, 0xa7, 0x5c, 0x06, 0xcc, 0xa7, 0x01, 0xf3, 0xc4, 0xa8, + 0x13, 0xda, 0x06, 0xc2, 0xa0, 0xc8, 0xc4, 0x58, 0x97, 0xcc, 0x4c, 0x91, + 0x0e, 0x21, 0x03, 0x46, 0x31, 0x9f, 0xa9, 0x15, 0xb0, 0x03, 0xd8, 0x3f, + 0xe4, 0xf6, 0x58, 0x8b, 0xce, 0x33, 0xfa, 0xbc, 0x55, 0x66, 0xca, 0x69, + 0x0b, 0xdb, 0xe1, 0x2a, 0xd8, 0x56, 0xcc, 0xc1, 0xb6, 0x03, 0xb0, 0xed, + 0x5c, 0x16, 0xb6, 0xe5, 0x74, 0x71, 0x1b, 0x6c, 0x1a, 0xa3, 0x8b, 0x0d, + 0x5e, 0x9b, 0x2d, 0x3d, 0xbc, 0xdf, 0xda, 0xbb, 0xb4, 0x89, 0x7e, 0x0a, + 0x78, 0x48, 0x63, 0xf8, 0x3d, 0x79, 0x2f, 0x65, 0x19, 0xd2, 0xf9, 0xbd, + 0x07, 0x65, 0xf0, 0x3d, 0xf9, 0x67, 0x2b, 0x4c, 0xd9, 0xbb, 0x2d, 0x2c, + 0xb4, 0x13, 0x32, 0xb0, 0x89, 0xfb, 0x9c, 0xec, 0x24, 0x61, 0xf8, 0x8f, + 0x80, 0x17, 0x79, 0x95, 0xea, 0x36, 0xf9, 0x66, 0xbb, 0xd7, 0xda, 0x76, + 0xd8, 0x76, 0x38, 0x96, 0x95, 0x56, 0xcf, 0x87, 0xf4, 0x15, 0xda, 0xd7, + 0x23, 0x4e, 0x66, 0xc9, 0xb8, 0xaa, 0x69, 0x8e, 0xf2, 0xd6, 0x95, 0x7e, + 0xd0, 0x49, 0xff, 0x02, 0x5a, 0x33, 0x72, 0xc3, 0xd0, 0xf1, 0x0a, 0x3b, + 0xbe, 0x1a, 0xc3, 0x37, 0xa9, 0x28, 0xf4, 0x21, 0xe5, 0xcd, 0x0e, 0xe3, + 0x9b, 0xcb, 0x43, 0x80, 0x35, 0xfc, 0x3e, 0xa8, 0x6d, 0xce, 0xa7, 0x4b, + 0x94, 0x49, 0xf3, 0xb4, 0x68, 0x7c, 0x97, 0x56, 0xf4, 0x55, 0x6d, 0xaf, + 0xbb, 0x32, 0x60, 0xe6, 0xfc, 0x30, 0xe7, 0x9c, 0xbe, 0x48, 0xfb, 0x03, + 0x03, 0x96, 0xbf, 0x92, 0xa3, 0x79, 0x79, 0xbb, 0x1d, 0xfb, 0x1f, 0x2e, + 0x33, 0x77, 0x8d, 0x73, 0x73, 0x37, 0x50, 0x59, 0x3c, 0x46, 0x91, 0xb6, + 0x07, 0x58, 0xcf, 0x85, 0x8d, 0x94, 0x92, 0x5a, 0x9f, 0xf2, 0x93, 0xb6, + 0x12, 0xd2, 0x27, 0xb6, 0x78, 0x4d, 0xf0, 0x01, 0x9e, 0x5e, 0x62, 0x77, + 0x25, 0xac, 0xdc, 0xa4, 0x1f, 0x1c, 0xf6, 0x91, 0xb7, 0x72, 0x32, 0x8f, + 0xf6, 0x47, 0x9c, 0xfe, 0xca, 0x72, 0xf2, 0x32, 0x94, 0x93, 0x1c, 0x8f, + 0x23, 0x77, 0x3c, 0x48, 0x1e, 0x7d, 0xbf, 0xb6, 0xaf, 0xb7, 0x6e, 0xab, + 0x01, 0xfe, 0x08, 0xc7, 0xcc, 0x1a, 0xa2, 0x33, 0xf7, 0x08, 0x6c, 0x22, + 0x3b, 0x6f, 0xbb, 0xe7, 0xe6, 0x5f, 0xd3, 0x05, 0x7e, 0x33, 0x8e, 0x6a, + 0x68, 0xa4, 0xc6, 0x77, 0x34, 0x2d, 0xd4, 0x2e, 0xb1, 0x65, 0x39, 0x06, + 0xda, 0xb3, 0xb5, 0xc6, 0x16, 0x2c, 0xd1, 0xfe, 0xa4, 0xec, 0xa2, 0xfd, + 0xf9, 0x43, 0xe0, 0x88, 0xe3, 0xe9, 0xb2, 0x69, 0xb4, 0x53, 0x17, 0x8f, + 0x6f, 0xb1, 0xff, 0x48, 0x38, 0x09, 0xb7, 0xa1, 0xad, 0x84, 0x22, 0x6c, + 0x81, 0x0c, 0x80, 0x97, 0x39, 0x07, 0x8a, 0xb6, 0xeb, 0xb6, 0xbf, 0xa8, + 0x31, 0x31, 0xe4, 0xd5, 0xb5, 0x52, 0xcf, 0x3e, 0xc9, 0x7f, 0x7c, 0xaf, + 0xd2, 0xf6, 0xef, 0x52, 0x59, 0x56, 0xad, 0x7b, 0xae, 0x9e, 0xc3, 0x5f, + 0xff, 0x82, 0x39, 0x0a, 0xf1, 0x17, 0xd2, 0x45, 0x35, 0x0e, 0x49, 0x13, + 0x86, 0x16, 0x0c, 0x2d, 0x6e, 0xb4, 0xfa, 0x26, 0xa4, 0xbd, 0xab, 0x40, + 0x7b, 0xf7, 0x81, 0xc6, 0x28, 0xc3, 0x19, 0x97, 0x5b, 0x8b, 0xef, 0x23, + 0xf8, 0x0e, 0xf9, 0xe4, 0x4a, 0x32, 0x9c, 0xf2, 0x9b, 0x75, 0xb2, 0x56, + 0xee, 0x87, 0x7e, 0x2e, 0xeb, 0x70, 0xdc, 0x94, 0xff, 0xff, 0x15, 0xed, + 0xac, 0xad, 0x35, 0xf6, 0xca, 0x8d, 0xb5, 0x94, 0xaf, 0x6b, 0xe4, 0x60, + 0x55, 0xda, 0x95, 0xe4, 0x77, 0xf5, 0x98, 0xd7, 0xff, 0x3f, 0x18, 0x73, + 0x7c, 0xd1, 0x98, 0x3d, 0x3b, 0xe6, 0x77, 0x21, 0xbf, 0xc9, 0xf8, 0x38, + 0x1e, 0xf9, 0x2e, 0x1c, 0xb3, 0xc5, 0x85, 0x1e, 0x57, 0xb5, 0x9c, 0x08, + 0x65, 0x04, 0xc7, 0x35, 0x60, 0xc7, 0xf0, 0xb9, 0xaa, 0x71, 0x0d, 0xbc, + 0x89, 0x71, 0xb5, 0x2e, 0x18, 0xd7, 0xf6, 0x2b, 0x8e, 0x6b, 0x39, 0x1e, + 0x27, 0x2f, 0x87, 0xe3, 0x8b, 0xca, 0xae, 0x22, 0xc7, 0xd8, 0x8f, 0x31, + 0x1e, 0xd4, 0xfe, 0x80, 0x19, 0x63, 0xda, 0x8e, 0x51, 0x54, 0xdb, 0xb6, + 0x7f, 0x8f, 0xdf, 0xd5, 0xe3, 0xa3, 0xee, 0xff, 0x3e, 0x68, 0xba, 0x4e, + 0xb2, 0x5d, 0x75, 0x56, 0xfe, 0xdf, 0x24, 0x1f, 0x2e, 0x71, 0xae, 0x93, + 0x19, 0x91, 0x51, 0xe8, 0xe0, 0xff, 0x5c, 0xcb, 0xd8, 0xfd, 0xf6, 0x94, + 0xd5, 0x63, 0xd0, 0x17, 0x3b, 0x60, 0xf3, 0xf5, 0x17, 0x55, 0x77, 0x44, + 0x82, 0xe0, 0xb6, 0xd4, 0xa7, 0xd1, 0xf7, 0x7e, 0xed, 0xab, 0x2e, 0x8d, + 0x9b, 0x3f, 0x57, 0x2b, 0x3e, 0xed, 0x0d, 0xea, 0x73, 0xe8, 0xbb, 0xe3, + 0xb4, 0xc1, 0xb2, 0xb0, 0x93, 0x33, 0xf1, 0x88, 0xb6, 0xc5, 0xa8, 0x13, + 0x93, 0xf1, 0x8c, 0xa4, 0xd1, 0x5f, 0x26, 0xae, 0x84, 0x7d, 0xc0, 0x56, + 0x83, 0x0d, 0xf9, 0xe1, 0xca, 0x3e, 0x3c, 0x0f, 0xcb, 0xad, 0xb0, 0x77, + 0x6e, 0x7d, 0xe4, 0x0b, 0x72, 0x1b, 0x6c, 0x9d, 0xdb, 0x1e, 0x19, 0x93, + 0xbd, 0xb0, 0x6d, 0xf6, 0xc2, 0xce, 0xd9, 0x5b, 0xa1, 0xed, 0x39, 0x8e, + 0xb2, 0xad, 0x55, 0xb4, 0x46, 0x1b, 0x87, 0xe3, 0x23, 0xee, 0x0f, 0x72, + 0x0e, 0x52, 0x09, 0xf5, 0x8a, 0x9e, 0x97, 0xa6, 0x05, 0x69, 0xaf, 0x27, + 0xab, 0x42, 0xfd, 0xb4, 0xca, 0xc6, 0x8d, 0x8c, 0x0d, 0x78, 0x65, 0xda, + 0x22, 0x8d, 0x78, 0xc0, 0x33, 0xf1, 0x47, 0xda, 0xaa, 0x1e, 0x7f, 0x63, + 0x9d, 0xf8, 0x2b, 0xeb, 0xa4, 0xfe, 0x73, 0x90, 0xaf, 0xd5, 0x34, 0xc5, + 0xb7, 0x67, 0x75, 0x0d, 0x69, 0x8b, 0x32, 0x38, 0xa4, 0x87, 0x8d, 0xaf, + 0x23, 0x7f, 0xaf, 0x48, 0x4f, 0xfb, 0xb9, 0x2e, 0xb3, 0xbb, 0x5b, 0x56, + 0x33, 0x1e, 0x90, 0xad, 0xcc, 0xc7, 0x04, 0x94, 0x5f, 0x1d, 0x13, 0xa0, + 0x9f, 0xf5, 0x01, 0xe0, 0xec, 0x16, 0x3c, 0xfb, 0x64, 0x88, 0x71, 0x87, + 0x4a, 0x68, 0x97, 0x7f, 0xd5, 0xda, 0xe5, 0x21, 0x1c, 0x09, 0xc0, 0x61, + 0xe4, 0xf3, 0x52, 0x3d, 0xb7, 0x50, 0x7f, 0xe7, 0xe7, 0x6c, 0xda, 0x84, + 0xec, 0x2a, 0x71, 0xdc, 0x94, 0xc1, 0xc4, 0x4d, 0xb5, 0x0c, 0x8e, 0x5b, + 0x3b, 0x0a, 0x65, 0xb4, 0xfc, 0x5c, 0x2a, 0x3b, 0x29, 0xf7, 0x18, 0x9f, + 0x7f, 0x20, 0x45, 0x5a, 0x7f, 0xb7, 0x64, 0xe6, 0xe2, 0xf3, 0x02, 0x7a, + 0x93, 0x54, 0x24, 0xad, 0xd7, 0xd3, 0xbc, 0x09, 0xd9, 0x21, 0xbd, 0x31, + 0xc6, 0x3a, 0x19, 0xcf, 0xf3, 0xf3, 0x13, 0xb0, 0x1f, 0x86, 0x4b, 0x0a, + 0x16, 0x7c, 0xad, 0x0c, 0x79, 0x81, 0x6c, 0x4f, 0x39, 0x3a, 0x76, 0x6c, + 0x74, 0x6d, 0xa9, 0xce, 0xd8, 0xae, 0x8e, 0x8e, 0xff, 0xce, 0x80, 0xfa, + 0x66, 0xb4, 0x7d, 0xab, 0xb4, 0xfe, 0x9d, 0xd6, 0x65, 0x46, 0xeb, 0xc2, + 0x38, 0xe6, 0x8c, 0x17, 0xb1, 0xe5, 0xaa, 0xd3, 0xa7, 0xea, 0x42, 0x5b, + 0xb0, 0x50, 0x09, 0xd3, 0x9e, 0x5c, 0x26, 0xed, 0x85, 0x65, 0xd2, 0xfe, + 0x76, 0x99, 0x34, 0x13, 0x17, 0xec, 0x2f, 0x5e, 0x46, 0xde, 0x88, 0xe6, + 0x55, 0x69, 0x36, 0xf6, 0x75, 0x7e, 0xae, 0xcc, 0x2a, 0xeb, 0x97, 0x31, + 0x46, 0x6c, 0x62, 0xc3, 0x39, 0x1d, 0x1b, 0xde, 0xe2, 0x6d, 0x53, 0x8c, + 0x75, 0x11, 0x17, 0x09, 0xd9, 0xab, 0xf1, 0x42, 0x9c, 0x7c, 0x85, 0x31, + 0xe0, 0x3c, 0xd7, 0x5a, 0x13, 0xea, 0x4a, 0xb4, 0x3d, 0x6f, 0x9b, 0x98, + 0x79, 0x8b, 0xe9, 0x75, 0xd5, 0x3e, 0xd8, 0x0a, 0xfd, 0xc5, 0x26, 0xd9, + 0x3e, 0x96, 0x58, 0x41, 0xbd, 0xb5, 0x63, 0xcc, 0xf8, 0x83, 0x7b, 0xc1, + 0x57, 0x19, 0x21, 0x8c, 0xc9, 0x94, 0x08, 0x6d, 0xe2, 0xa5, 0xb6, 0xf0, + 0xeb, 0xb7, 0xd7, 0x7b, 0x85, 0xf6, 0x1c, 0xd8, 0x0e, 0x3f, 0x6b, 0x7b, + 0xf5, 0xd2, 0x37, 0x16, 0xe2, 0x4a, 0xfd, 0x9c, 0xf5, 0x22, 0x57, 0xa8, + 0xa7, 0xed, 0x12, 0x79, 0x66, 0x4e, 0x16, 0x6f, 0x84, 0xcd, 0x24, 0x41, + 0xb6, 0x5b, 0x5a, 0x23, 0xa2, 0x63, 0x3c, 0x29, 0x23, 0x9b, 0x3b, 0xb8, + 0xb6, 0x03, 0xfa, 0x37, 0xb6, 0x8a, 0x89, 0x9b, 0x86, 0x76, 0xca, 0x72, + 0xb4, 0x7b, 0xbd, 0xa5, 0x5d, 0xae, 0xa9, 0xee, 0xa0, 0xcc, 0xc5, 0x9c, + 0x18, 0x3a, 0xde, 0x5e, 0x94, 0x44, 0x48, 0xc7, 0x33, 0xf0, 0x8b, 0xab, + 0xe9, 0x78, 0x46, 0x52, 0x9a, 0x8e, 0x6b, 0x17, 0xd0, 0x71, 0xab, 0xa5, + 0xe3, 0x77, 0x44, 0x0d, 0x5d, 0x28, 0xad, 0xa7, 0x48, 0xa7, 0x86, 0x8e, + 0x1d, 0x4d, 0xc7, 0x33, 0x78, 0xbb, 0x7e, 0x8f, 0x2d, 0x13, 0xb1, 0x69, + 0xfc, 0x1d, 0xa6, 0x51, 0x2e, 0xfe, 0x66, 0xd4, 0xe8, 0xa5, 0x14, 0xe8, + 0x28, 0x4c, 0xff, 0x60, 0xd4, 0xd0, 0x67, 0x75, 0x9a, 0x89, 0x8f, 0xf4, + 0x17, 0xdf, 0x13, 0x5d, 0x48, 0x9f, 0x29, 0xd0, 0x67, 0x58, 0xe6, 0xf5, + 0xe8, 0xb3, 0xde, 0xae, 0x5b, 0x44, 0xf5, 0xba, 0x7b, 0x26, 0x66, 0x68, + 0xf5, 0x56, 0x3d, 0x76, 0x8e, 0xfb, 0xd9, 0x9f, 0x81, 0x56, 0xcd, 0xdc, + 0x9c, 0x9f, 0xf7, 0xb7, 0x19, 0x8b, 0x4a, 0x98, 0x18, 0x36, 0xe3, 0xa4, + 0x57, 0xb2, 0x1d, 0x8d, 0x7c, 0xaa, 0xd1, 0xf2, 0xa9, 0x71, 0x48, 0xa5, + 0xab, 0x65, 0x76, 0x37, 0x74, 0x05, 0x6d, 0x6c, 0x2d, 0xa7, 0x91, 0xd7, + 0x9a, 0xc8, 0x16, 0xff, 0xd9, 0xee, 0x5f, 0xe0, 0xba, 0x80, 0x0c, 0x39, + 0x48, 0x6b, 0x2b, 0x9b, 0x71, 0x29, 0xbf, 0x11, 0xdf, 0xdd, 0xd2, 0x56, + 0x56, 0x72, 0xfb, 0x58, 0x83, 0xec, 0x2b, 0xba, 0xf2, 0x51, 0xd4, 0xff, + 0x48, 0xd1, 0x83, 0x3f, 0x3e, 0x1e, 0xa5, 0x5d, 0xb8, 0xb7, 0xc8, 0xf5, + 0x49, 0xc7, 0xac, 0x19, 0x2d, 0x58, 0xf3, 0x8c, 0x48, 0x5b, 0x47, 0x01, + 0x9e, 0x8a, 0xb8, 0x3b, 0x01, 0x47, 0x5d, 0x3a, 0x2d, 0xaf, 0x74, 0x0f, + 0x38, 0xda, 0x97, 0x70, 0x7a, 0xe4, 0xc6, 0x4a, 0x5a, 0x6e, 0xa8, 0x98, + 0x75, 0xd2, 0xf9, 0x75, 0xd0, 0xa4, 0x37, 0x0d, 0x9d, 0x93, 0xf1, 0x82, + 0xe0, 0x3c, 0xe4, 0xb7, 0x3a, 0xe2, 0x4a, 0xb4, 0x23, 0x19, 0x9f, 0x16, + 0xf3, 0x7d, 0xb1, 0xfc, 0xe3, 0x60, 0x28, 0xe6, 0xca, 0x2b, 0x3e, 0xc7, + 0xd5, 0x23, 0xd7, 0x97, 0xab, 0xfb, 0xe3, 0x5a, 0xe9, 0x13, 0x51, 0xae, + 0x4d, 0x64, 0x2b, 0xe5, 0x28, 0xe3, 0xe7, 0x22, 0x79, 0x69, 0x7b, 0x2b, + 0x7c, 0x37, 0x48, 0xeb, 0xb6, 0xb7, 0x82, 0x56, 0x62, 0xd0, 0xf3, 0x5b, + 0x01, 0xd7, 0x56, 0xc6, 0xbb, 0x18, 0xe7, 0xe2, 0xf7, 0x5f, 0xa2, 0x5f, + 0xd6, 0xfd, 0x5d, 0xbd, 0x66, 0x25, 0x8a, 0x73, 0x6e, 0xf8, 0x65, 0x79, + 0x5d, 0xd3, 0x38, 0x14, 0x4d, 0x8b, 0x13, 0x7d, 0x5b, 0x5c, 0x56, 0xf8, + 0xd5, 0xfd, 0x73, 0xed, 0x57, 0x14, 0x70, 0xe8, 0xee, 0xd8, 0xdc, 0x23, + 0x7d, 0x18, 0x5f, 0xff, 0x92, 0xf1, 0xed, 0x17, 0xc6, 0x54, 0x2f, 0x16, + 0x39, 0x86, 0xf9, 0x71, 0xa9, 0x3f, 0x32, 0xe3, 0x8a, 0x76, 0x2c, 0x1e, + 0x8f, 0xae, 0xaf, 0x4e, 0x01, 0x96, 0xe7, 0xf4, 0x1e, 0x81, 0x20, 0xb8, + 0xa6, 0xe3, 0x62, 0x90, 0x58, 0x97, 0xec, 0x9c, 0x9e, 0x5f, 0xd3, 0x19, + 0x8a, 0xa4, 0x33, 0x1a, 0xff, 0xf8, 0x4e, 0xe4, 0xca, 0xdd, 0x98, 0x3b, + 0x71, 0x73, 0x5d, 0xae, 0xe6, 0x8d, 0x9c, 0xdf, 0x6d, 0xd7, 0xad, 0x42, + 0xbf, 0x29, 0x08, 0x94, 0xbf, 0x58, 0x56, 0x50, 0x47, 0x61, 0xec, 0xb2, + 0xdb, 0xee, 0x4b, 0x49, 0x31, 0x6e, 0x38, 0xe4, 0xa6, 0xa3, 0x89, 0x42, + 0xb9, 0x0b, 0xbf, 0x1b, 0xf0, 0xfe, 0x45, 0xd8, 0x28, 0x3d, 0xb0, 0x61, + 0x24, 0xa6, 0x8c, 0x3c, 0x00, 0xfd, 0x76, 0xe4, 0x95, 0x22, 0x3f, 0x7a, + 0x89, 0xe1, 0x72, 0x2c, 0x31, 0x5a, 0xde, 0xcb, 0xfa, 0x28, 0x7b, 0xa5, + 0xf8, 0x1d, 0xfb, 0x62, 0x1f, 0xf4, 0x79, 0x7f, 0x96, 0x3e, 0x5c, 0xdb, + 0x36, 0xdb, 0x0c, 0xf1, 0xe2, 0xd2, 0x0d, 0xc7, 0xbf, 0x6e, 0xeb, 0x8f, + 0x70, 0x7c, 0x7b, 0x2d, 0xdc, 0x8b, 0xfb, 0x7d, 0x49, 0xdb, 0x2c, 0x8f, + 0x55, 0x68, 0x27, 0x72, 0x4d, 0x27, 0x79, 0x62, 0x5c, 0x08, 0x47, 0x10, + 0x5c, 0x48, 0x19, 0x7d, 0xfd, 0x74, 0x85, 0xeb, 0x1a, 0x41, 0xf0, 0x5d, + 0xda, 0xc2, 0x83, 0x25, 0xf4, 0x17, 0xe2, 0x60, 0x63, 0xde, 0x85, 0x2c, + 0x1c, 0xe9, 0x26, 0x7e, 0x05, 0x5e, 0x69, 0x87, 0xb7, 0x4b, 0xa2, 0x89, + 0xdf, 0x2e, 0x37, 0x24, 0x3e, 0x51, 0xf6, 0x80, 0x67, 0x8e, 0x3b, 0x96, + 0xd8, 0x63, 0xc7, 0xcc, 0xfd, 0x20, 0xaf, 0xbf, 0x4f, 0xe3, 0xa5, 0x05, + 0x3e, 0x12, 0x61, 0x9a, 0x87, 0x85, 0xb0, 0x25, 0x2c, 0x6e, 0x82, 0xe0, + 0xfb, 0x29, 0xf6, 0xd9, 0xcd, 0xfd, 0x00, 0x23, 0xe8, 0x37, 0xbf, 0x56, + 0x11, 0x0f, 0xd1, 0xc4, 0x1d, 0xe8, 0xfb, 0xb7, 0xd1, 0xf7, 0xbe, 0x32, + 0xfb, 0x83, 0x7c, 0xc0, 0xd8, 0x47, 0x2a, 0x21, 0xbc, 0xcb, 0xf5, 0x1d, + 0xce, 0x79, 0xa7, 0xb5, 0xeb, 0xc2, 0x6f, 0x8d, 0x48, 0x4f, 0xc1, 0x97, + 0xcb, 0x56, 0x66, 0xd6, 0xb8, 0xf2, 0x2e, 0xc8, 0xda, 0x40, 0x4e, 0x42, + 0x86, 0xcd, 0x68, 0xba, 0xc9, 0xae, 0xe7, 0xff, 0x11, 0xf9, 0xe4, 0x0a, + 0xc6, 0x94, 0x7b, 0x7d, 0xda, 0xab, 0xb3, 0xc1, 0x8c, 0x4f, 0x99, 0xbc, + 0x4a, 0xc6, 0xbd, 0x7c, 0x27, 0xf4, 0x03, 0xd2, 0x1a, 0xe9, 0x63, 0x27, + 0xb2, 0x91, 0x64, 0x62, 0x58, 0xb8, 0xc7, 0x89, 0xfb, 0x13, 0xb8, 0xef, + 0x87, 0xf2, 0xc0, 0x85, 0x9c, 0xe3, 0x1c, 0x9a, 0xfe, 0x86, 0xcb, 0xf3, + 0x65, 0x0f, 0x08, 0xd7, 0x09, 0x93, 0xf1, 0xbd, 0xda, 0x26, 0x01, 0xd5, + 0x15, 0x59, 0x76, 0x33, 0x2c, 0x12, 0xbf, 0xaa, 0xbc, 0xde, 0x73, 0x05, + 0x3e, 0x67, 0x1c, 0x21, 0x1a, 0xcd, 0x16, 0xe5, 0xb5, 0x48, 0xb7, 0xbc, + 0x96, 0x4d, 0xd5, 0x4b, 0xaf, 0x96, 0xf9, 0xcc, 0xd3, 0xe9, 0xb3, 0x26, + 0xdd, 0x85, 0x2e, 0xe1, 0x9c, 0xf4, 0x40, 0x46, 0x4f, 0x00, 0x6e, 0xe2, + 0xb0, 0x87, 0x32, 0x89, 0xf3, 0xa7, 0x54, 0x3a, 0x16, 0xcd, 0x95, 0xa5, + 0x2f, 0x57, 0xb4, 0xb1, 0x9e, 0x01, 0x8e, 0x7f, 0x95, 0xc5, 0x43, 0xa3, + 0xb8, 0x80, 0xad, 0x2f, 0x92, 0x70, 0xe0, 0x2b, 0x43, 0xd7, 0x3f, 0xba, + 0x4a, 0x1a, 0x89, 0x9b, 0x1e, 0xf0, 0x52, 0x0d, 0x74, 0xd1, 0xfd, 0xcd, + 0x5c, 0x37, 0xd5, 0x36, 0x64, 0xec, 0x63, 0xbf, 0xac, 0xd2, 0x7f, 0x1b, + 0x57, 0xe9, 0x51, 0x2b, 0x2f, 0xa3, 0x7d, 0x94, 0x97, 0x4f, 0x97, 0x08, + 0x8f, 0x78, 0x11, 0x3f, 0xd1, 0xd7, 0x5b, 0x16, 0x15, 0x49, 0x7b, 0xd1, + 0xde, 0xf2, 0x42, 0xfa, 0x7f, 0xba, 0xf2, 0x61, 0x6b, 0x0b, 0x56, 0xc7, + 0x54, 0xab, 0xf3, 0xc8, 0x83, 0xcb, 0xe5, 0x11, 0x26, 0x89, 0xae, 0x48, + 0x5f, 0xf8, 0x54, 0x7b, 0x47, 0xde, 0xab, 0x15, 0xe2, 0x39, 0x80, 0xdc, + 0x06, 0xae, 0xcb, 0x5c, 0xaf, 0xde, 0x8f, 0x79, 0xfb, 0x3f, 0x41, 0x26, + 0xc6, 0x7c, 0x4f, 0xea, 0xe0, 0xdb, 0xbe, 0x0c, 0xdd, 0xf9, 0x8a, 0x7f, + 0xe1, 0x53, 0x9d, 0x1d, 0x41, 0xf0, 0xac, 0x9f, 0x4f, 0xb8, 0x90, 0x1f, + 0x87, 0x2d, 0xbe, 0x87, 0x81, 0xef, 0x89, 0x39, 0x7c, 0x27, 0xe4, 0x62, + 0xd7, 0xf7, 0x03, 0xae, 0xf5, 0x0d, 0x97, 0x6f, 0xbd, 0x55, 0xa5, 0x3f, + 0xfe, 0xa1, 0x6c, 0x37, 0xfb, 0x1b, 0x91, 0xc3, 0x95, 0x9b, 0x88, 0xbf, + 0x28, 0xc6, 0x7a, 0x4f, 0x9f, 0x6f, 0xfa, 0xed, 0x5b, 0xd0, 0x2f, 0xe9, + 0xe5, 0x47, 0xac, 0x8b, 0x32, 0xd5, 0x75, 0x33, 0xa0, 0xcb, 0xbc, 0xad, + 0x3b, 0x70, 0x85, 0xba, 0xde, 0x15, 0xea, 0x1e, 0x46, 0xdd, 0x3d, 0xb6, + 0xee, 0x85, 0xcf, 0xbc, 0xb9, 0x7e, 0x07, 0xb8, 0xc7, 0x0e, 0x3e, 0x80, + 0xb8, 0x11, 0xff, 0x36, 0xfc, 0xbe, 0x85, 0xed, 0x28, 0xda, 0xf7, 0x23, + 0x95, 0x21, 0x19, 0xae, 0xec, 0xc4, 0x33, 0x88, 0xb4, 0x3e, 0x3c, 0xfb, + 0xf0, 0x3b, 0x8d, 0x47, 0xa2, 0x6e, 0xfa, 0xc2, 0x5d, 0xc3, 0x7e, 0x88, + 0x57, 0xae, 0xcd, 0xb3, 0x0f, 0xd8, 0x17, 0x5d, 0x3f, 0x41, 0x1f, 0x61, + 0xfa, 0x07, 0x50, 0x67, 0x1a, 0x69, 0x2b, 0x69, 0x7b, 0x62, 0xae, 0xab, + 0xeb, 0x54, 0xc3, 0x36, 0x1d, 0xce, 0x05, 0xf2, 0x0d, 0x8d, 0xf6, 0x16, + 0x43, 0x18, 0xef, 0x44, 0x1b, 0xe3, 0x57, 0x29, 0xff, 0x1e, 0xc2, 0x15, + 0x57, 0xfe, 0xc7, 0xf0, 0x7e, 0x2d, 0xd8, 0x9d, 0x62, 0x4c, 0x9e, 0xf3, + 0x7e, 0xdd, 0xaa, 0xa5, 0x7b, 0x9f, 0x42, 0x1a, 0xe8, 0x84, 0x4e, 0x69, + 0xb0, 0x74, 0x5a, 0x80, 0xe5, 0x43, 0x1a, 0xe5, 0x98, 0x17, 0x97, 0x4d, + 0x76, 0xe6, 0xa5, 0x07, 0xba, 0x8c, 0xb2, 0xf6, 0xd3, 0xf5, 0x26, 0x0e, + 0x03, 0xcb, 0xd1, 0xef, 0x04, 0x3d, 0x37, 0x88, 0x87, 0xfa, 0x03, 0x11, + 0x0f, 0x34, 0x18, 0xd6, 0x4f, 0x7a, 0x03, 0x11, 0x8e, 0x19, 0x1c, 0x5f, + 0xe6, 0xba, 0x34, 0x6d, 0x6b, 0xd6, 0x0f, 0x6d, 0x1c, 0xfe, 0x7b, 0x59, + 0xc4, 0x67, 0x1a, 0xdb, 0x0b, 0xde, 0x55, 0xe3, 0x2f, 0x59, 0x63, 0xc1, + 0x38, 0xf3, 0x49, 0x68, 0x30, 0xaf, 0x4f, 0xcb, 0xe9, 0xfc, 0x35, 0x35, + 0xd2, 0xe0, 0xf5, 0xeb, 0xdf, 0x2c, 0xd3, 0xe0, 0x81, 0x4f, 0x17, 0x95, + 0x61, 0x1a, 0xf3, 0x0a, 0x6b, 0x94, 0xde, 0xab, 0xa4, 0xf7, 0x28, 0xc9, + 0x83, 0xa9, 0x64, 0x62, 0x48, 0x25, 0xbd, 0x71, 0xd9, 0x0f, 0xb9, 0x43, + 0x39, 0x39, 0x73, 0x7f, 0x44, 0xb8, 0x9f, 0xef, 0x5d, 0x92, 0xf5, 0x29, + 0x3f, 0x0b, 0x9f, 0x57, 0x94, 0x75, 0x95, 0x97, 0x1a, 0xcc, 0xd8, 0xb8, + 0x0f, 0x01, 0x70, 0x36, 0xd1, 0x86, 0xbb, 0xb5, 0x81, 0x3c, 0x94, 0x50, + 0x11, 0xd9, 0x45, 0x3f, 0x5f, 0x7d, 0xb1, 0x5e, 0xea, 0xa7, 0xd7, 0x78, + 0x52, 0xd1, 0xe9, 0x66, 0x7f, 0x60, 0xb2, 0x73, 0x48, 0x89, 0x1e, 0x7b, + 0x46, 0xbd, 0x91, 0xcc, 0x9e, 0xb5, 0xfa, 0x23, 0x90, 0xc7, 0xb4, 0xbe, + 0x98, 0xf9, 0xbc, 0x2b, 0x17, 0x82, 0xb6, 0x4d, 0x17, 0xda, 0xb3, 0x5d, + 0xb4, 0x73, 0x57, 0xd9, 0xfd, 0x95, 0x8c, 0x63, 0xbd, 0x4b, 0x9e, 0xf3, + 0x0b, 0x18, 0xf7, 0x7e, 0xb9, 0xe0, 0xb3, 0xbf, 0x99, 0xcf, 0x79, 0xc2, + 0x74, 0xc2, 0x6e, 0xfa, 0x13, 0xf5, 0xa7, 0x80, 0x87, 0x7d, 0x52, 0x07, + 0x5f, 0xc9, 0xee, 0x4b, 0x0e, 0xe4, 0x45, 0xcf, 0x4b, 0x8f, 0xa0, 0xad, + 0x15, 0x3e, 0xf8, 0x10, 0x76, 0x73, 0xcd, 0x91, 0xab, 0x21, 0x77, 0x1d, + 0xbd, 0xc7, 0x02, 0x93, 0xe1, 0x4d, 0x61, 0xde, 0x33, 0x03, 0x2c, 0x57, + 0x2f, 0xd3, 0x31, 0xf2, 0xba, 0xe6, 0x97, 0x4f, 0x65, 0xfd, 0x76, 0x4f, + 0x39, 0xc3, 0x8c, 0x31, 0x00, 0xaf, 0xa4, 0xcd, 0x54, 0x6c, 0xbb, 0xcf, + 0xb6, 0x58, 0xe6, 0x2a, 0xf9, 0xf6, 0xc0, 0x85, 0x7f, 0x78, 0xd6, 0xff, + 0x7b, 0xc0, 0x91, 0x81, 0x4c, 0xe0, 0xf3, 0x6a, 0x90, 0x8f, 0x31, 0xa6, + 0xf5, 0xbf, 0xeb, 0xad, 0x9d, 0xac, 0x79, 0x7f, 0x58, 0xef, 0x93, 0x79, + 0xfe, 0x33, 0x59, 0xae, 0x77, 0xc0, 0x36, 0xc9, 0x69, 0xb9, 0x18, 0xfd, + 0x69, 0x0e, 0xf0, 0x14, 0x2a, 0xb4, 0x43, 0xfe, 0x06, 0x76, 0x88, 0xd6, + 0x93, 0xf2, 0xed, 0x41, 0xe6, 0xb1, 0xdd, 0xec, 0xd5, 0xae, 0xd6, 0x0b, + 0x21, 0x2c, 0xc9, 0xce, 0x1c, 0xf2, 0x47, 0xb4, 0x1d, 0xef, 0xc9, 0xac, + 0xe7, 0xea, 0x7d, 0x27, 0xf9, 0xc1, 0x20, 0x78, 0xc5, 0x77, 0xe5, 0xa4, + 0x86, 0xf9, 0x05, 0xf4, 0xe1, 0xc8, 0xc4, 0x80, 0xfb, 0xd3, 0x93, 0x3e, + 0xc7, 0xc7, 0x3c, 0xae, 0x2b, 0x6d, 0x8e, 0x1b, 0xf8, 0x68, 0x9b, 0x7e, + 0x2f, 0x98, 0x8d, 0x71, 0xdd, 0x02, 0x3c, 0x5d, 0x6a, 0xf7, 0x6e, 0x90, + 0xdb, 0xe6, 0x6c, 0x9a, 0x69, 0x31, 0x36, 0xa3, 0xd1, 0x69, 0x17, 0xfe, + 0x61, 0xc4, 0xbf, 0xb0, 0xba, 0x80, 0xb9, 0x81, 0x0e, 0x5b, 0x0c, 0x4b, + 0x8a, 0xb0, 0x0c, 0x6b, 0x58, 0x62, 0xc0, 0xa5, 0x0b, 0xd9, 0x77, 0x9b, + 0x1c, 0x02, 0xde, 0x87, 0x06, 0x45, 0x9e, 0x85, 0x4d, 0x76, 0xbe, 0x0a, + 0x9e, 0x19, 0xc0, 0x73, 0xde, 0xe7, 0x5e, 0x00, 0xe6, 0xf9, 0xde, 0xb0, + 0x70, 0x2f, 0x00, 0x71, 0xd8, 0x81, 0xdf, 0x22, 0x33, 0xd0, 0xbf, 0x27, + 0xfd, 0xd7, 0x82, 0xf1, 0x18, 0x75, 0x23, 0xda, 0x99, 0xdb, 0x1b, 0x14, + 0xc8, 0xe7, 0x53, 0xd4, 0x43, 0xb5, 0xd2, 0xb6, 0x8e, 0x7e, 0x88, 0x91, + 0x9f, 0x37, 0xf8, 0x19, 0xf4, 0xf5, 0x5b, 0x2b, 0xa5, 0x3e, 0x2f, 0xfd, + 0x1d, 0x75, 0xc8, 0x73, 0x6d, 0xde, 0x80, 0xce, 0xeb, 0xef, 0x38, 0x8c, + 0xfc, 0x8f, 0xaf, 0x64, 0xbc, 0xdb, 0xf5, 0xd7, 0x4b, 0xdb, 0x1a, 0xe6, + 0x55, 0xf3, 0xe0, 0xab, 0xdc, 0x83, 0x69, 0x75, 0x38, 0x64, 0x59, 0x29, + 0xef, 0x71, 0xa7, 0xdd, 0x21, 0xcc, 0xc5, 0x6e, 0x9f, 0xb2, 0xed, 0xbf, + 0xa3, 0x6e, 0x4a, 0x6e, 0xf4, 0x07, 0x91, 0x37, 0x8d, 0xbc, 0xc3, 0x36, + 0x6f, 0xd0, 0xe6, 0x6d, 0x43, 0xde, 0x3e, 0xe0, 0xef, 0x6e, 0x9d, 0x9e, + 0xe5, 0x6f, 0x53, 0xc7, 0x5b, 0xd9, 0x71, 0xe1, 0x33, 0x37, 0xf8, 0x84, + 0x0b, 0x79, 0x25, 0xae, 0x8b, 0xde, 0x26, 0x79, 0x2f, 0x79, 0x0b, 0x7b, + 0xfd, 0x66, 0xb1, 0x0e, 0xb2, 0x89, 0x7b, 0x80, 0x69, 0xb3, 0x6e, 0xf1, + 0x5e, 0x96, 0xff, 0x40, 0xba, 0xeb, 0xc9, 0x38, 0x5f, 0x5b, 0xc9, 0xb8, + 0xd8, 0x88, 0x4f, 0xfb, 0x3a, 0x90, 0x9c, 0x5e, 0x3f, 0xa1, 0x7f, 0x5b, + 0x44, 0x3a, 0xe9, 0x41, 0x35, 0x45, 0xf4, 0x3e, 0x2d, 0x7e, 0x47, 0x61, + 0xf7, 0x06, 0x42, 0x9f, 0x8f, 0x36, 0x5d, 0xc6, 0xe3, 0xda, 0x50, 0x98, + 0xe7, 0x21, 0x4f, 0x6d, 0x8a, 0xc0, 0x26, 0xaa, 0xf5, 0x1d, 0x1d, 0xa3, + 0x2e, 0xe8, 0x75, 0x00, 0xc6, 0xdf, 0x32, 0xf0, 0x63, 0x02, 0xe9, 0x47, + 0xdf, 0xa4, 0xfd, 0x68, 0x87, 0xef, 0x1d, 0x10, 0xee, 0x67, 0x65, 0x7a, + 0xbb, 0xf7, 0x6d, 0x99, 0xa7, 0xf3, 0x19, 0x49, 0x66, 0x94, 0x03, 0xff, + 0x75, 0xab, 0x23, 0xf5, 0xb0, 0x3d, 0x6e, 0x30, 0xfa, 0xcd, 0xe3, 0x9e, + 0xc4, 0x8b, 0xda, 0x56, 0x6b, 0xb4, 0xf3, 0x91, 0x05, 0x6e, 0xb8, 0x1f, + 0x7c, 0xe0, 0x9e, 0xdd, 0x7e, 0x21, 0x09, 0x6a, 0xd4, 0xba, 0x71, 0x18, + 0xb4, 0x91, 0x4d, 0x19, 0xdd, 0x78, 0xc3, 0x9c, 0x6e, 0xfc, 0xf3, 0x95, + 0xe4, 0x89, 0xe1, 0x72, 0x1c, 0x75, 0xf5, 0x3a, 0x4a, 0x82, 0x75, 0x6b, + 0x31, 0x9f, 0xe7, 0xfd, 0xec, 0x35, 0xa0, 0x2f, 0xc8, 0xe1, 0x64, 0xe7, + 0x29, 0xd4, 0x2d, 0xa0, 0xee, 0xe4, 0x5c, 0x5d, 0x47, 0x46, 0x7c, 0xbd, + 0xef, 0x59, 0x26, 0xcb, 0x21, 0x1d, 0x26, 0xe3, 0xb7, 0x6a, 0x5e, 0xe0, + 0x7e, 0x30, 0x37, 0x71, 0x9f, 0x6c, 0xd6, 0xb4, 0xdd, 0x27, 0xdc, 0x27, + 0xc5, 0xb6, 0xef, 0x0b, 0xda, 0xd6, 0x10, 0xbe, 0x12, 0xde, 0xa4, 0x8d, + 0x31, 0xbc, 0xc3, 0xf9, 0x37, 0xf3, 0x3e, 0xe4, 0x10, 0xdf, 0xbf, 0x1f, + 0xe4, 0x07, 0x39, 0x2f, 0xfc, 0x9e, 0xa7, 0xb9, 0x11, 0xd0, 0x5c, 0xc4, + 0x7f, 0xbb, 0x0c, 0xeb, 0x3d, 0x10, 0x29, 0x99, 0xd0, 0xf1, 0xcc, 0x0b, + 0xc1, 0x23, 0x0b, 0xe4, 0xf8, 0x47, 0x94, 0xa1, 0x21, 0xfe, 0x2e, 0x24, + 0xea, 0x64, 0x66, 0x4d, 0x9d, 0xde, 0xf1, 0x41, 0x7c, 0x8c, 0xde, 0x73, + 0x3b, 0xf8, 0xf5, 0xfa, 0xb9, 0xb1, 0x00, 0xdf, 0xc0, 0xe3, 0x4e, 0x63, + 0xeb, 0x63, 0x1c, 0x19, 0xed, 0xbf, 0x67, 0x8b, 0x4a, 0xef, 0x0b, 0xa2, + 0x8e, 0x3f, 0x00, 0x9d, 0x6a, 0xf6, 0xa4, 0xe0, 0x5d, 0xe1, 0xbc, 0x29, + 0xed, 0x73, 0x1c, 0x04, 0x0f, 0x1f, 0xf4, 0xb3, 0x6b, 0x6a, 0x75, 0xdb, + 0x49, 0xef, 0x7a, 0x6d, 0x13, 0x6e, 0x94, 0x99, 0x14, 0xdb, 0x23, 0x5e, + 0xfe, 0x47, 0x30, 0xe4, 0xcd, 0xa0, 0x7f, 0x43, 0xff, 0x59, 0x5f, 0xb5, + 0xd4, 0x49, 0xf5, 0x3e, 0x53, 0xe2, 0xc9, 0x85, 0xbd, 0xd2, 0x01, 0xfc, + 0x18, 0x78, 0x73, 0xe5, 0xb7, 0x49, 0x21, 0xe6, 0xda, 0xb1, 0x45, 0xb4, + 0x2f, 0x37, 0x91, 0xaa, 0x83, 0x2d, 0xf8, 0x17, 0xc1, 0xe4, 0x82, 0x31, + 0x1e, 0xac, 0x1a, 0xe3, 0x4c, 0x02, 0xd8, 0x68, 0x89, 0xcc, 0xc9, 0x01, + 0xf6, 0x65, 0x64, 0x52, 0x38, 0xc6, 0x3a, 0x8c, 0x71, 0xc7, 0xdc, 0x18, + 0x0f, 0x2f, 0x1a, 0xe3, 0x61, 0x8c, 0x11, 0xf6, 0x42, 0x29, 0xd3, 0xe9, + 0xce, 0xcf, 0xfb, 0xd5, 0x35, 0x73, 0xf3, 0x29, 0xdc, 0xeb, 0x84, 0xf1, + 0xd3, 0xa6, 0xd8, 0x08, 0x78, 0x74, 0x5b, 0x90, 0x71, 0x0e, 0x64, 0x5b, + 0x76, 0x4d, 0x8d, 0x1d, 0xff, 0x76, 0x96, 0x2b, 0x1b, 0x1c, 0x9c, 0x4c, + 0xb9, 0x9d, 0x8f, 0xa0, 0xbf, 0xbd, 0x76, 0x5c, 0xbd, 0xe5, 0xab, 0x31, + 0xae, 0x0b, 0xdf, 0xc1, 0x18, 0xe0, 0xb3, 0x9d, 0xa0, 0x0f, 0x9c, 0x18, + 0x92, 0x05, 0xb2, 0xeb, 0x33, 0xf3, 0x72, 0xd4, 0xc0, 0x4c, 0xdb, 0xba, + 0x30, 0x07, 0xf3, 0xdd, 0x8b, 0x60, 0xbe, 0x1b, 0x30, 0xef, 0xb3, 0xf3, + 0xb2, 0xaf, 0x6a, 0xcf, 0x62, 0x48, 0x47, 0xfc, 0xfd, 0xbc, 0xf5, 0x45, + 0x3e, 0x20, 0xf7, 0x97, 0x3a, 0xe5, 0xcb, 0x95, 0xe4, 0x59, 0xc6, 0xd1, + 0xcf, 0x55, 0x92, 0xe3, 0x22, 0x5d, 0xf2, 0xc7, 0xb0, 0x73, 0xae, 0x82, + 0x6f, 0xf1, 0x34, 0xfc, 0xd7, 0x3f, 0xa9, 0xf8, 0xf2, 0xc4, 0xdc, 0x7e, + 0x38, 0xea, 0xba, 0xb4, 0x9c, 0x84, 0x4f, 0xbb, 0xed, 0x68, 0x1b, 0xf7, + 0x2a, 0x11, 0xbe, 0xbb, 0xa8, 0x73, 0xda, 0x94, 0xe6, 0xc5, 0xef, 0x62, + 0xbc, 0xa7, 0xa9, 0x6b, 0xd6, 0xfa, 0xbe, 0x77, 0xb3, 0x5a, 0x47, 0x99, + 0x90, 0xff, 0x5a, 0xe4, 0x03, 0xf5, 0x26, 0xc6, 0x92, 0xf1, 0x9a, 0xc9, + 0x1b, 0xdb, 0x3a, 0x12, 0x7d, 0x42, 0x5b, 0x82, 0xfe, 0x36, 0x6c, 0xa1, + 0xd2, 0xe6, 0xf8, 0x5a, 0xa1, 0x4c, 0xa2, 0x5d, 0x94, 0x96, 0x09, 0xc0, + 0x3e, 0x06, 0x89, 0x50, 0x68, 0xf6, 0x47, 0x7b, 0xd5, 0x44, 0x03, 0x79, + 0x70, 0xdb, 0x19, 0xd0, 0xd7, 0x36, 0x8c, 0xa9, 0x2b, 0x79, 0x76, 0x46, + 0x65, 0x4e, 0xac, 0x95, 0x57, 0x82, 0xa1, 0x66, 0x47, 0x9e, 0xd8, 0xc4, + 0x3c, 0x2d, 0xb7, 0x3f, 0xd5, 0x0b, 0xf9, 0xd4, 0xce, 0x73, 0x0b, 0x03, + 0xf2, 0x2f, 0x77, 0x80, 0x06, 0x7f, 0xb8, 0xe9, 0x6b, 0xc1, 0x6c, 0xb3, + 0x2b, 0x5b, 0x37, 0x25, 0xbd, 0xbc, 0xc2, 0x78, 0x4a, 0x18, 0x4f, 0x09, + 0xe3, 0xe3, 0x98, 0x4b, 0x18, 0xd7, 0x15, 0xf7, 0x4a, 0xf5, 0x2c, 0x88, + 0xcb, 0x1a, 0x3f, 0x2d, 0x93, 0x77, 0x65, 0x83, 0xdd, 0x2b, 0x35, 0x5c, + 0x1f, 0xae, 0xb1, 0x65, 0x64, 0x3c, 0x28, 0xf8, 0x7f, 0x70, 0x55, 0xb6, + 0x2b, 0xb6, 0x58, 0xe7, 0xdc, 0x35, 0xaf, 0x73, 0x44, 0x9e, 0x33, 0xf3, + 0x86, 0x39, 0xf3, 0xbd, 0x49, 0x6e, 0x86, 0x87, 0x0e, 0xdc, 0xaa, 0xf7, + 0x3c, 0x77, 0xe0, 0x9b, 0x36, 0xd5, 0xa7, 0xf5, 0x3a, 0xe2, 0x4c, 0xf9, + 0x1e, 0x3b, 0x77, 0xf7, 0x68, 0x3d, 0xbb, 0x75, 0xd3, 0xa5, 0x80, 0xfb, + 0xdc, 0xbc, 0x4d, 0xcb, 0xc5, 0x22, 0x68, 0xef, 0xd5, 0x69, 0xde, 0xe7, + 0x7a, 0x76, 0x41, 0x9f, 0x13, 0x01, 0xde, 0xe6, 0xe2, 0x62, 0xf5, 0x48, + 0xa3, 0xbe, 0xf8, 0x69, 0x83, 0x59, 0x47, 0xa5, 0x6c, 0x58, 0x83, 0x34, + 0xd7, 0xec, 0x05, 0x5e, 0x90, 0xf7, 0xdf, 0xea, 0xcd, 0x9e, 0x8f, 0xea, + 0xb2, 0xe0, 0x31, 0xbd, 0x2f, 0x84, 0xfb, 0x03, 0x7f, 0x79, 0xa5, 0xb1, + 0x4d, 0xc3, 0x7c, 0xa6, 0xff, 0x38, 0x98, 0xd0, 0x31, 0x36, 0xf6, 0xf5, + 0x43, 0xfc, 0x5e, 0xbc, 0x5f, 0x24, 0xb4, 0x5d, 0xeb, 0x40, 0xf7, 0xda, + 0x5f, 0x16, 0x94, 0x89, 0xe7, 0x25, 0x22, 0x13, 0x55, 0x30, 0x4e, 0x10, + 0xee, 0x52, 0xd7, 0xaa, 0xf9, 0xd8, 0xdd, 0x6a, 0xa4, 0x11, 0xc6, 0x75, + 0x8b, 0xf2, 0xc8, 0x1b, 0xad, 0x2b, 0x49, 0x37, 0xd3, 0xc2, 0xb4, 0xf9, + 0x31, 0xcd, 0x68, 0xfb, 0xb9, 0x6d, 0x95, 0xde, 0xfb, 0xc4, 0x35, 0x46, + 0xc6, 0x08, 0x63, 0x26, 0xdf, 0xf5, 0xff, 0x56, 0xd7, 0x19, 0x9a, 0xab, + 0xa3, 0xe7, 0x02, 0xf9, 0x6e, 0x55, 0x5e, 0x35, 0xdc, 0xd4, 0x5f, 0x43, + 0x9d, 0x75, 0xd0, 0x89, 0x17, 0x53, 0xab, 0xc3, 0xbd, 0xf0, 0xb0, 0x21, + 0xb2, 0xd7, 0xd4, 0x5a, 0x99, 0x3f, 0x81, 0x79, 0x7d, 0x26, 0x65, 0x78, + 0x51, 0xf3, 0x61, 0xf1, 0x36, 0xf8, 0xeb, 0xa1, 0xde, 0xa0, 0x9c, 0x26, + 0x6f, 0x22, 0xad, 0x42, 0x9f, 0xe0, 0xc2, 0xea, 0x99, 0xae, 0x57, 0x03, + 0xee, 0xb3, 0x7c, 0x45, 0xdb, 0x51, 0x43, 0xb2, 0xb0, 0xed, 0xd1, 0x7b, + 0x5e, 0xbf, 0xed, 0xa1, 0x65, 0xda, 0x1e, 0xb2, 0x6d, 0x8b, 0x6b, 0xda, + 0x8e, 0x5e, 0xa1, 0xed, 0x81, 0x37, 0x68, 0x7b, 0x70, 0x99, 0xb6, 0x07, + 0xc3, 0xb6, 0x95, 0x69, 0xdb, 0x0b, 0xdb, 0x4e, 0x2c, 0xc2, 0xc9, 0x67, + 0x5e, 0xbf, 0xed, 0x7d, 0xcb, 0xb4, 0xbd, 0x6f, 0x11, 0xdc, 0xc4, 0x49, + 0x2d, 0x74, 0xff, 0x3d, 0xda, 0xe6, 0xac, 0x03, 0xdf, 0x5c, 0x84, 0xfc, + 0x36, 0xfe, 0xc8, 0x85, 0xbb, 0x66, 0xcb, 0xe0, 0x2b, 0xf8, 0xd7, 0x99, + 0x72, 0x03, 0x9e, 0x71, 0xd8, 0x33, 0x28, 0x07, 0x7b, 0xbc, 0x26, 0x1d, + 0xc8, 0xc9, 0x6e, 0x96, 0xcd, 0xc7, 0x6b, 0xe7, 0xf4, 0xc6, 0x3d, 0xe8, + 0x8f, 0x6d, 0xfb, 0x5e, 0xbf, 0xbc, 0xa6, 0xfb, 0xcb, 0x95, 0xe9, 0x8f, + 0x21, 0xbd, 0x42, 0x1f, 0x97, 0xf5, 0x42, 0x19, 0x58, 0x67, 0xd7, 0x3e, + 0x68, 0x6b, 0x32, 0x0e, 0xa7, 0xed, 0x51, 0x29, 0x94, 0x7f, 0x12, 0x4c, + 0x83, 0x2e, 0x46, 0xe6, 0x74, 0xc8, 0x93, 0xab, 0x68, 0xb3, 0x8f, 0x53, + 0xb3, 0x54, 0xc5, 0xa0, 0x46, 0x7c, 0xa6, 0xfd, 0x98, 0x6d, 0xc2, 0x0e, + 0x0c, 0xcb, 0x32, 0x6e, 0x6c, 0x62, 0x4e, 0x67, 0x21, 0x33, 0xcd, 0x9e, + 0x0e, 0xfa, 0x2a, 0x4f, 0x81, 0x97, 0xf7, 0x43, 0x76, 0x24, 0xf3, 0x22, + 0x3d, 0x8d, 0xe6, 0xac, 0x45, 0x4c, 0x72, 0x5d, 0xbf, 0x69, 0xf1, 0xb8, + 0xef, 0xce, 0xe5, 0xcf, 0x59, 0x40, 0x3e, 0x38, 0x94, 0x91, 0xd7, 0x37, + 0x9a, 0x75, 0xbb, 0xb7, 0x36, 0x32, 0x1e, 0xa3, 0x36, 0x75, 0xaf, 0xd6, + 0xf2, 0xc7, 0x09, 0xbf, 0xbf, 0xb2, 0xe8, 0x3b, 0xac, 0xf7, 0x93, 0xd5, + 0x0b, 0xeb, 0x85, 0xe9, 0x70, 0x4d, 0x16, 0xa4, 0x1f, 0x58, 0xb3, 0xb0, + 0x7e, 0xac, 0x69, 0xe1, 0xf7, 0xe0, 0xa2, 0xef, 0xcf, 0x2c, 0xfa, 0x7e, + 0x61, 0xd1, 0xf7, 0x75, 0x6b, 0x17, 0x95, 0x5f, 0xf4, 0xfd, 0xe5, 0xb5, + 0xcb, 0xc3, 0xfb, 0x57, 0x6b, 0x17, 0xc2, 0xf5, 0x94, 0x5e, 0x73, 0x1d, + 0xaf, 0xb8, 0xb2, 0xbd, 0x88, 0x7c, 0xe7, 0xd6, 0x18, 0xf2, 0xe1, 0xcb, + 0x54, 0xe7, 0x73, 0x8d, 0xe3, 0x1d, 0xb1, 0x85, 0xed, 0xcd, 0xd7, 0xdb, + 0x31, 0x5f, 0x2f, 0x35, 0x5f, 0xcf, 0xf8, 0x23, 0x13, 0x15, 0xe6, 0x31, + 0x3d, 0x6c, 0xd7, 0xd4, 0x1d, 0x29, 0x79, 0xfa, 0x3c, 0xc2, 0x80, 0x3e, + 0x8f, 0x90, 0x80, 0x6f, 0xf4, 0x94, 0x8e, 0xeb, 0xaf, 0x51, 0x48, 0xaf, + 0x34, 0xea, 0xd8, 0xbe, 0xe8, 0x33, 0x09, 0x03, 0xb0, 0xb9, 0x78, 0x0e, + 0x21, 0x90, 0x9d, 0x29, 0xf3, 0x36, 0xe7, 0x12, 0x0e, 0x07, 0xbd, 0x5e, + 0x10, 0x0c, 0xfb, 0x67, 0xad, 0x2c, 0xc7, 0xbb, 0x62, 0xea, 0xd0, 0xd7, + 0x7c, 0x14, 0xfa, 0x66, 0xde, 0xc7, 0x7c, 0x8a, 0xf6, 0x3a, 0x68, 0xa6, + 0x1b, 0x7a, 0x37, 0xf9, 0xa4, 0x68, 0xdd, 0xd1, 0x05, 0x9d, 0xeb, 0xdd, + 0xfb, 0x3e, 0xd8, 0x3a, 0x5f, 0x06, 0xad, 0x1f, 0x4b, 0xf5, 0x68, 0xff, + 0xff, 0x1c, 0x74, 0x31, 0xe3, 0x84, 0x8f, 0x69, 0xda, 0x22, 0x8d, 0x35, + 0xe8, 0xb3, 0x50, 0x27, 0x53, 0x4e, 0x34, 0xdb, 0x75, 0xde, 0xc4, 0xcd, + 0x53, 0xed, 0xde, 0x73, 0xe0, 0xb5, 0x7e, 0x7f, 0x03, 0x6c, 0x66, 0xd1, + 0x3a, 0xbf, 0x50, 0x5a, 0x6f, 0x6d, 0x83, 0x66, 0x19, 0x77, 0xb9, 0x56, + 0x93, 0xec, 0x19, 0x32, 0x3e, 0x66, 0x3c, 0xa1, 0x18, 0x23, 0xe6, 0xfa, + 0x05, 0xcf, 0x39, 0x70, 0x9d, 0x9b, 0xf1, 0x90, 0xf1, 0x7b, 0x47, 0xfc, + 0xbc, 0x17, 0xb1, 0x67, 0x23, 0xb2, 0x45, 0x43, 0x9b, 0x7b, 0xb4, 0xad, + 0x1a, 0x05, 0x3f, 0x7d, 0x0f, 0x74, 0xcf, 0xba, 0xa4, 0xfd, 0xef, 0x04, + 0x93, 0xae, 0x89, 0x4f, 0x29, 0xd4, 0xcb, 0x6a, 0x5c, 0x3d, 0x25, 0x07, + 0x4a, 0xe4, 0xff, 0xa8, 0x96, 0xe5, 0xbb, 0x53, 0x94, 0x07, 0x51, 0xe0, + 0x71, 0x0a, 0xf8, 0x6b, 0x90, 0xdd, 0x5d, 0x45, 0x94, 0x89, 0xc8, 0xd0, + 0x40, 0x03, 0x78, 0x8f, 0x76, 0x09, 0xdf, 0x2e, 0xca, 0x7b, 0x32, 0x55, + 0x1c, 0xd7, 0x7b, 0x9e, 0x1f, 0x43, 0xdd, 0xc7, 0xf1, 0x4c, 0x14, 0xcb, + 0xa8, 0xf3, 0xb0, 0x2e, 0x3f, 0x31, 0xca, 0x73, 0x22, 0x02, 0x7b, 0xff, + 0x49, 0x29, 0x4c, 0xb6, 0xc1, 0x2f, 0x99, 0x1e, 0x77, 0xe7, 0xe2, 0xe4, + 0xff, 0xa5, 0x91, 0xeb, 0xcc, 0x85, 0xeb, 0xb8, 0x27, 0x47, 0xdc, 0x81, + 0xcd, 0xaa, 0xb3, 0x49, 0xaf, 0xf9, 0xf4, 0x48, 0x3f, 0x6c, 0x8a, 0x9b, + 0x2b, 0xcf, 0xc4, 0xcc, 0xda, 0xc0, 0x82, 0xf5, 0x86, 0xc3, 0xc4, 0x8a, + 0x3a, 0xea, 0xf2, 0xdc, 0xa7, 0x4c, 0x9c, 0x81, 0xf6, 0x39, 0x1a, 0xae, + 0xe7, 0x30, 0xcd, 0x93, 0xb6, 0xeb, 0x00, 0xd7, 0x99, 0x7f, 0xd2, 0xf2, + 0xf5, 0x89, 0x4d, 0x61, 0x5f, 0xf9, 0x60, 0x6c, 0x53, 0x5e, 0x3e, 0x81, + 0x27, 0x77, 0x5d, 0x72, 0x34, 0xab, 0xd8, 0xef, 0x37, 0x02, 0xc6, 0x02, + 0x54, 0xba, 0x55, 0xf2, 0x4d, 0xd5, 0xfd, 0x33, 0xad, 0xc3, 0x2b, 0xa8, + 0xd7, 0x83, 0x63, 0x26, 0x11, 0x03, 0x0e, 0xf2, 0x6f, 0x08, 0xcf, 0x16, + 0xcf, 0x57, 0xcb, 0xc1, 0x73, 0xc2, 0xae, 0xd7, 0x70, 0x0d, 0x66, 0x05, + 0xf0, 0xd2, 0x80, 0xf4, 0x09, 0x19, 0x39, 0xfe, 0x3b, 0x31, 0xee, 0x17, + 0xaa, 0xd1, 0x7e, 0xf5, 0x7d, 0xf5, 0x26, 0x06, 0xf2, 0x2c, 0xca, 0x30, + 0x7f, 0x1c, 0x75, 0x92, 0xf9, 0x6c, 0x64, 0xad, 0x0c, 0xe9, 0x7e, 0x83, + 0x48, 0xdb, 0xb6, 0x7a, 0xbd, 0x4f, 0x5f, 0xce, 0x30, 0x6e, 0x11, 0xd6, + 0x7d, 0x56, 0xef, 0x83, 0x73, 0xd3, 0xc9, 0x7c, 0x5f, 0x84, 0xf2, 0xa9, + 0x53, 0x7a, 0xb9, 0xce, 0x73, 0x66, 0x5c, 0xd3, 0x76, 0xfb, 0x26, 0x9e, + 0x07, 0xdd, 0x02, 0xfb, 0xef, 0x3b, 0x80, 0x89, 0x30, 0x9e, 0x40, 0x3a, + 0x7c, 0xc2, 0xd7, 0x85, 0x61, 0xfa, 0x4d, 0xc2, 0x30, 0xfd, 0x26, 0x61, + 0x20, 0x2e, 0x00, 0x47, 0xa5, 0x7d, 0x75, 0x68, 0x53, 0x5c, 0x85, 0x71, + 0x1c, 0x2c, 0x4d, 0xc3, 0xbf, 0xd5, 0x31, 0x94, 0xce, 0x69, 0x45, 0x9e, + 0xf7, 0xc0, 0x73, 0xe0, 0xad, 0x12, 0x78, 0x0f, 0xb6, 0xe1, 0x97, 0x61, + 0x1b, 0x3e, 0x01, 0xdb, 0xf0, 0x1c, 0x6c, 0xc3, 0xc7, 0x31, 0x37, 0x8f, + 0x2d, 0xe0, 0xd5, 0x8c, 0xe6, 0xd5, 0x42, 0xe9, 0x02, 0x78, 0xb5, 0xeb, + 0x0a, 0xfc, 0xe8, 0xc2, 0xc6, 0xa7, 0x0d, 0xed, 0xc0, 0x96, 0xff, 0xb8, + 0xf6, 0x8b, 0x1f, 0x4c, 0x8d, 0xb1, 0x0e, 0x68, 0x38, 0x49, 0x9f, 0x16, + 0xf2, 0x3f, 0x99, 0x07, 0xef, 0x61, 0xac, 0x8e, 0xa3, 0xae, 0x5b, 0x23, + 0xd4, 0x1f, 0xee, 0x36, 0xee, 0xef, 0xe6, 0x58, 0x13, 0x8b, 0xf0, 0x64, + 0xf8, 0x73, 0x8f, 0x4f, 0x3d, 0x42, 0xbe, 0x4c, 0x7c, 0x76, 0xc4, 0xaf, + 0xe6, 0xc5, 0x1d, 0x1c, 0x5f, 0xe0, 0x6d, 0x5a, 0xae, 0xee, 0x7c, 0xf9, + 0x35, 0x73, 0xe5, 0x75, 0xff, 0xa3, 0xe4, 0x37, 0xe8, 0x6e, 0xe2, 0x3e, + 0x91, 0x8d, 0x6c, 0xb0, 0xb8, 0xdf, 0x2f, 0x6d, 0xdb, 0x60, 0xaf, 0x0f, + 0x82, 0x7e, 0xa7, 0x02, 0xf1, 0xb7, 0x85, 0x6d, 0xce, 0xb7, 0xe3, 0xd9, + 0x76, 0x76, 0xc3, 0x96, 0xed, 0xdb, 0xc4, 0xb5, 0x5e, 0xd8, 0xf2, 0xa9, + 0x70, 0x3e, 0x60, 0xf9, 0xea, 0x39, 0xa7, 0x0c, 0xa5, 0xec, 0x6c, 0xb0, + 0xf1, 0x7e, 0xb6, 0x77, 0x61, 0xd1, 0x3c, 0x5d, 0x0a, 0x78, 0xce, 0x76, + 0xc4, 0x1f, 0xab, 0xa2, 0x95, 0xbf, 0xb2, 0xb4, 0xa2, 0x16, 0x8d, 0xe3, + 0x9c, 0xa5, 0x95, 0x10, 0xde, 0x58, 0x48, 0x2b, 0x75, 0x21, 0xad, 0xe4, + 0xc7, 0x43, 0x5a, 0x61, 0xdd, 0x73, 0x21, 0xad, 0x24, 0xaa, 0x69, 0x25, + 0x3f, 0xee, 0xe0, 0x59, 0x0c, 0x07, 0xe9, 0x85, 0xed, 0x90, 0x5e, 0x00, + 0x4b, 0xa5, 0x32, 0x47, 0x2f, 0x31, 0xb4, 0x73, 0xa8, 0xa4, 0x34, 0xad, + 0x0c, 0xa9, 0x50, 0x47, 0x78, 0x98, 0x73, 0xcc, 0xfd, 0x15, 0x69, 0x24, + 0x65, 0x69, 0x64, 0xfe, 0x2c, 0xd1, 0x22, 0xda, 0x00, 0xee, 0x79, 0x5e, + 0x60, 0xb3, 0xa6, 0x8d, 0xfb, 0x53, 0x2f, 0xa0, 0xec, 0x28, 0x68, 0x23, + 0xc4, 0xc1, 0x03, 0x16, 0x07, 0x8b, 0xe7, 0xf2, 0xb4, 0xc5, 0xc1, 0xa8, + 0xc5, 0x81, 0xe6, 0x97, 0x3c, 0xe7, 0x4c, 0x69, 0x1c, 0xd4, 0x69, 0x1c, + 0x88, 0x0a, 0xeb, 0x9e, 0x5e, 0x06, 0x07, 0x2c, 0x33, 0xaa, 0xc7, 0x1f, + 0xc1, 0xf8, 0xf7, 0x61, 0xfc, 0x4a, 0x8f, 0x9f, 0xf3, 0xc0, 0xf1, 0x03, + 0x96, 0xca, 0x77, 0xe6, 0xc6, 0xdf, 0x84, 0x36, 0x0e, 0x6a, 0xdb, 0x99, + 0xf1, 0x54, 0xea, 0x46, 0x33, 0xfe, 0xc7, 0x2a, 0xe6, 0x8c, 0xc9, 0x63, + 0x4b, 0xf4, 0xd8, 0x0b, 0x96, 0x37, 0x7c, 0xbd, 0xce, 0xc6, 0x73, 0x6d, + 0xe7, 0xa0, 0xbb, 0xc6, 0x52, 0x09, 0x7b, 0xe6, 0xd4, 0xd8, 0x43, 0x5f, + 0x4d, 0x91, 0x77, 0x3e, 0xaa, 0xf7, 0xfa, 0x9d, 0xa5, 0x5d, 0x54, 0x6a, + 0x92, 0xbe, 0xb1, 0x6a, 0xb8, 0x09, 0x6f, 0x3e, 0x50, 0x3e, 0x63, 0x37, + 0xfb, 0xa1, 0x3b, 0x4c, 0xdc, 0x1a, 0xb4, 0x84, 0xf4, 0x64, 0xbe, 0x37, + 0x52, 0x27, 0xea, 0x81, 0x0f, 0x60, 0xcc, 0x2e, 0x7c, 0xcc, 0x76, 0x6f, + 0x9b, 0xa2, 0xae, 0xbb, 0xba, 0x4a, 0xd7, 0x35, 0x5b, 0x5d, 0xb7, 0x86, + 0xba, 0x0e, 0x70, 0x3f, 0x25, 0x87, 0x4b, 0x9c, 0xbf, 0x7c, 0xa2, 0x4e, + 0xc7, 0x40, 0x1d, 0x1b, 0xe7, 0x4b, 0xc6, 0x0f, 0x6b, 0x5a, 0xa6, 0xce, + 0x4a, 0xea, 0xb8, 0xe4, 0x4c, 0xd7, 0x3f, 0xd9, 0x75, 0x10, 0xea, 0xb5, + 0xef, 0x07, 0x7f, 0xb0, 0x8c, 0x5e, 0x83, 0xfe, 0xd1, 0xf6, 0x59, 0x0d, + 0x64, 0xad, 0x9c, 0x6a, 0xc6, 0xb3, 0x9a, 0xe7, 0xc1, 0x3a, 0x3b, 0x54, + 0xbd, 0xd4, 0x9c, 0x6a, 0x94, 0x3d, 0x63, 0x7a, 0xdd, 0x5c, 0xd4, 0x29, + 0xe0, 0xff, 0x14, 0xcf, 0x14, 0x88, 0x3e, 0x03, 0x95, 0x1b, 0x85, 0x3f, + 0x33, 0xf1, 0x94, 0xd9, 0x1b, 0x38, 0x56, 0xa3, 0x7f, 0xd3, 0xc6, 0x28, + 0xa4, 0x32, 0xfa, 0xec, 0xd0, 0x1e, 0xb4, 0xd9, 0xbe, 0xa9, 0x16, 0x63, + 0x8e, 0xa1, 0x2e, 0xf7, 0x16, 0xaa, 0x36, 0x57, 0x6a, 0xc5, 0x9d, 0x88, + 0xea, 0xf3, 0x4b, 0x3c, 0x7f, 0x9f, 0xed, 0x69, 0x42, 0x5e, 0x44, 0xaf, + 0x15, 0xd4, 0x9c, 0x9a, 0x3f, 0xa7, 0xae, 0x8e, 0x8a, 0x5d, 0xc3, 0x4f, + 0x6b, 0xbd, 0x12, 0x39, 0x4a, 0x9d, 0xc3, 0xfd, 0x55, 0x3d, 0x98, 0xf7, + 0xe5, 0xf4, 0x8d, 0x31, 0x62, 0xb3, 0x98, 0x3f, 0x75, 0x86, 0x67, 0x8d, + 0x5b, 0xf1, 0x0e, 0xdb, 0x0b, 0xf5, 0x08, 0x74, 0xdf, 0xdb, 0x3f, 0xe1, + 0x49, 0x3d, 0xf0, 0x3d, 0xa1, 0x80, 0x6b, 0x57, 0xd3, 0x42, 0x5e, 0x85, + 0xb1, 0x69, 0x43, 0x0f, 0x8f, 0xbf, 0x21, 0x3f, 0x90, 0x26, 0x3a, 0x6d, + 0x6c, 0xc1, 0xb7, 0x31, 0x7e, 0xd2, 0xb6, 0xa1, 0x87, 0x47, 0x53, 0x19, + 0xc5, 0xbd, 0x51, 0x66, 0x1d, 0x94, 0xb4, 0x41, 0x9a, 0x4f, 0xe8, 0xf5, + 0xd1, 0x8c, 0xbc, 0x2c, 0x99, 0xa6, 0x76, 0xd8, 0x5d, 0xff, 0xb6, 0x73, + 0x6c, 0xee, 0x2e, 0xd0, 0x34, 0x07, 0xdd, 0xc4, 0x7d, 0xca, 0x9d, 0xf2, + 0x5e, 0x9e, 0x57, 0x98, 0x70, 0xa0, 0x94, 0x9f, 0xd2, 0x7b, 0xbf, 0x77, + 0x14, 0x57, 0xcb, 0xad, 0xa9, 0xa8, 0x5d, 0xe7, 0xac, 0x05, 0x1d, 0x40, + 0x50, 0x9f, 0xaa, 0xc5, 0x13, 0x75, 0x38, 0x7f, 0x17, 0x53, 0x99, 0xa4, + 0x22, 0xb3, 0xc3, 0xe7, 0x9f, 0x91, 0x2d, 0xde, 0x1e, 0x7d, 0xce, 0x4e, + 0x9c, 0xba, 0x53, 0x7f, 0xe9, 0xd1, 0x06, 0x25, 0xfd, 0xcc, 0xf8, 0xb5, + 0x7a, 0x5d, 0xab, 0x3f, 0x15, 0x04, 0x39, 0xcc, 0x5f, 0x41, 0x4c, 0xfc, + 0x6c, 0xc2, 0x67, 0x1a, 0xfd, 0xda, 0x06, 0xa7, 0xf6, 0x4c, 0xa3, 0x63, + 0x68, 0x45, 0x22, 0x2a, 0x5d, 0xef, 0xd4, 0x9c, 0xba, 0x93, 0x73, 0x06, + 0xba, 0xf2, 0x1c, 0x43, 0x57, 0x31, 0x67, 0x9e, 0xae, 0xd6, 0xd9, 0xdf, + 0x2a, 0x5d, 0x27, 0x99, 0x64, 0x1d, 0xc6, 0xdb, 0x5b, 0x0c, 0x61, 0x3c, + 0x0c, 0xb8, 0x08, 0xcf, 0xdd, 0x18, 0xc3, 0x30, 0x9e, 0x3c, 0x60, 0x01, + 0xb3, 0x9f, 0x2a, 0x00, 0xe6, 0x83, 0x78, 0x18, 0x27, 0x6b, 0x76, 0x22, + 0x13, 0xd5, 0xf0, 0x12, 0xc6, 0x1f, 0x5b, 0x78, 0x5f, 0x0f, 0x56, 0x4f, + 0x66, 0xba, 0x8b, 0x80, 0x87, 0x70, 0xde, 0x07, 0x18, 0x69, 0x97, 0x8e, + 0xe2, 0xdb, 0x03, 0x7c, 0x63, 0x16, 0x26, 0xd0, 0xe3, 0xd8, 0x43, 0xf3, + 0xbf, 0x8b, 0xb4, 0x93, 0x8f, 0xd9, 0xef, 0xd6, 0x45, 0x32, 0xe0, 0x15, + 0x87, 0x78, 0x1e, 0x29, 0xbd, 0xe6, 0xc0, 0x0e, 0x00, 0xdf, 0xbf, 0xe4, + 0x44, 0xce, 0xc4, 0xe5, 0x50, 0x91, 0x31, 0x84, 0xe3, 0x0e, 0xe7, 0x41, + 0xf9, 0x57, 0xa1, 0x4c, 0x5c, 0xc9, 0xc4, 0xd5, 0x78, 0xde, 0x82, 0x67, + 0x03, 0x9e, 0x8d, 0x78, 0xd6, 0xe3, 0x69, 0xc5, 0xf3, 0x2d, 0x94, 0x53, + 0xb1, 0x3a, 0xe1, 0x7e, 0xd5, 0x16, 0xa5, 0x34, 0x1f, 0x71, 0xcf, 0xc2, + 0x65, 0xc0, 0xe5, 0x2b, 0xd0, 0x3b, 0x1e, 0x9e, 0xf1, 0xf8, 0x3a, 0xfa, + 0x98, 0xc5, 0xd3, 0xa9, 0xe4, 0x4c, 0x17, 0x9e, 0x14, 0x9e, 0x6e, 0x3c, + 0x3d, 0x78, 0xd2, 0x78, 0x5e, 0x75, 0x0c, 0xcf, 0x5d, 0x02, 0xbe, 0x42, + 0x1e, 0x01, 0xce, 0x17, 0xf0, 0x9c, 0xe7, 0xbc, 0x09, 0x9e, 0x73, 0x2c, + 0xcf, 0x39, 0xf3, 0x3c, 0x57, 0xeb, 0xa8, 0x63, 0xf5, 0x4e, 0xe4, 0x18, + 0x7d, 0x85, 0x5a, 0xc7, 0xf0, 0x7f, 0x44, 0x7a, 0x07, 0x41, 0x4b, 0xc7, + 0x30, 0x67, 0xc7, 0x48, 0x57, 0x2e, 0xd2, 0xc7, 0x16, 0xf5, 0x3b, 0xfa, + 0x26, 0xfa, 0x3d, 0x61, 0xfb, 0x7d, 0xb8, 0xaa, 0xdf, 0x83, 0x68, 0xfb, + 0x3e, 0xdb, 0xef, 0xc1, 0xaa, 0x7e, 0x41, 0x2b, 0xc7, 0xf2, 0x78, 0x48, + 0x17, 0x23, 0x48, 0x0f, 0x65, 0xc2, 0xdd, 0x6b, 0xa4, 0xbe, 0x46, 0x9f, + 0x27, 0x8d, 0xf9, 0x35, 0x73, 0xba, 0x31, 0x53, 0xa5, 0x1f, 0x7e, 0x16, + 0xfd, 0x38, 0x5c, 0xa2, 0x8d, 0x38, 0x5d, 0x25, 0x17, 0xe8, 0xfb, 0x04, + 0x72, 0x5c, 0xfb, 0x39, 0xf4, 0x79, 0xe8, 0xff, 0x2c, 0xb6, 0xad, 0x3e, + 0xae, 0xf7, 0xe7, 0xde, 0x55, 0x6c, 0x95, 0x4f, 0x14, 0x69, 0x13, 0x92, + 0x5e, 0x82, 0x60, 0xcf, 0x36, 0xda, 0xa7, 0xf9, 0x60, 0x9d, 0x9f, 0xd4, + 0xb1, 0xb5, 0x4f, 0x2e, 0xd5, 0x19, 0xa3, 0xbd, 0xf0, 0xcd, 0xb3, 0x47, + 0x3f, 0x08, 0x9d, 0x51, 0x03, 0xb8, 0x9f, 0xd2, 0x77, 0x80, 0xec, 0x1a, + 0x55, 0x23, 0x6b, 0x25, 0x2e, 0x37, 0x17, 0x6b, 0x61, 0xf7, 0x30, 0x56, + 0x5e, 0x2f, 0xed, 0xdb, 0xa2, 0xe6, 0x6c, 0x8d, 0x17, 0xc3, 0x6f, 0xcf, + 0x9c, 0xf5, 0x89, 0xc5, 0x91, 0x1f, 0x69, 0xa2, 0x1c, 0x8c, 0xf9, 0xef, + 0xd4, 0xfb, 0x26, 0xdb, 0xb6, 0xd1, 0x6e, 0xb9, 0x41, 0xeb, 0x70, 0x77, + 0x89, 0x9d, 0xa4, 0x5a, 0x3c, 0x99, 0xb7, 0xd1, 0x76, 0x17, 0x93, 0x09, + 0xc2, 0xf5, 0x90, 0x70, 0x3f, 0xc1, 0x7e, 0x29, 0xa4, 0x1a, 0x25, 0x92, + 0xe6, 0xba, 0x5c, 0xb2, 0x93, 0xb6, 0xd1, 0xc4, 0x98, 0x67, 0xcf, 0x9e, + 0xac, 0x96, 0x0b, 0xba, 0x9f, 0x5a, 0x0d, 0xa3, 0x39, 0x8f, 0xc6, 0x35, + 0x2f, 0x9e, 0x81, 0x72, 0xf1, 0x6e, 0xd0, 0x7a, 0x67, 0xa2, 0xcc, 0xb3, + 0x4e, 0xf0, 0x97, 0xca, 0x31, 0x7d, 0xc6, 0xd4, 0x7b, 0x3b, 0xfc, 0xd8, + 0xf2, 0x06, 0xd9, 0x3d, 0xb6, 0x82, 0xeb, 0x28, 0xb1, 0xb5, 0xd0, 0x1f, + 0xac, 0xd3, 0xb6, 0x0d, 0xfe, 0xdf, 0xf8, 0x46, 0x79, 0x7c, 0x9c, 0x6d, + 0xb7, 0xc8, 0xe4, 0x94, 0x38, 0xde, 0xdb, 0x57, 0xa2, 0x8c, 0xc7, 0xf1, + 0x08, 0xf7, 0x3c, 0xb5, 0x6d, 0x13, 0xe5, 0xbd, 0xdd, 0x95, 0xf3, 0xdd, + 0x11, 0xbd, 0x26, 0xe3, 0x82, 0x4e, 0xd8, 0xde, 0xf9, 0xee, 0x56, 0x39, + 0x3b, 0x05, 0x9a, 0x80, 0xdc, 0xef, 0x3b, 0x45, 0x98, 0x44, 0xb6, 0x4f, + 0xc0, 0x5e, 0x90, 0x76, 0x3c, 0xa0, 0x0f, 0xc8, 0xef, 0x5b, 0xbb, 0xd9, + 0x17, 0xf4, 0x12, 0x74, 0x5c, 0xdb, 0x36, 0x23, 0x0b, 0x32, 0x13, 0x35, + 0x48, 0x67, 0xbb, 0xf0, 0x0f, 0x07, 0xd9, 0x4e, 0x58, 0x57, 0x61, 0x4c, + 0xb5, 0x9a, 0x5e, 0x66, 0x17, 0xe9, 0x8f, 0x73, 0x3f, 0x97, 0xfd, 0xcd, + 0x36, 0x3a, 0x41, 0x2b, 0xbe, 0xde, 0xc3, 0x63, 0x6c, 0x2b, 0xce, 0x09, + 0x6d, 0x22, 0xda, 0x55, 0xd7, 0x6a, 0xfb, 0x62, 0xb2, 0xc2, 0x19, 0xe4, + 0xda, 0x48, 0x38, 0x47, 0x71, 0x39, 0x59, 0x9a, 0x9b, 0xa7, 0x0d, 0x35, + 0x0b, 0xe7, 0x89, 0xb4, 0x92, 0x1a, 0xb2, 0xb6, 0xc7, 0x8c, 0x3c, 0x0f, + 0xbb, 0xac, 0x53, 0xcf, 0xd9, 0x0c, 0x6c, 0x59, 0x3b, 0x67, 0xda, 0x9e, + 0x2d, 0x84, 0x73, 0x36, 0x00, 0x8d, 0x53, 0xbe, 0x41, 0xcf, 0x99, 0x07, + 0xba, 0xc9, 0x03, 0xef, 0x79, 0xcc, 0x53, 0x1e, 0x73, 0x94, 0x2f, 0xb7, + 0xc8, 0xc4, 0x71, 0xd5, 0x5a, 0x23, 0x92, 0xd8, 0xed, 0xb7, 0xc8, 0xf0, + 0x14, 0x63, 0x05, 0x1b, 0x60, 0x83, 0x6d, 0xc4, 0xd3, 0x8a, 0x6f, 0xd6, + 0xe3, 0x1d, 0x1f, 0x0a, 0x75, 0xeb, 0x96, 0xd8, 0x59, 0x67, 0xd1, 0xf7, + 0xd3, 0xc0, 0xc3, 0xa3, 0xc0, 0xc3, 0x3c, 0xef, 0xbc, 0x50, 0x15, 0x5f, + 0xe2, 0x58, 0xb5, 0x0e, 0xc5, 0x78, 0x63, 0x7a, 0x3e, 0x75, 0x9c, 0xa9, + 0x54, 0xfb, 0x66, 0xec, 0xa9, 0x38, 0xed, 0xa9, 0xdc, 0xa8, 0x67, 0xce, + 0x60, 0x0d, 0xc0, 0x77, 0xf2, 0xf7, 0x69, 0x5a, 0x1f, 0x1a, 0x27, 0x5c, + 0xd1, 0x10, 0xae, 0x05, 0x73, 0xc6, 0x33, 0xb3, 0x4b, 0xe3, 0x18, 0x2f, + 0xcc, 0xed, 0x11, 0x87, 0x2e, 0x97, 0xd1, 0x14, 0xe3, 0x24, 0xad, 0xcb, + 0xc0, 0xf4, 0x94, 0xb6, 0x61, 0x45, 0x9d, 0x96, 0x03, 0x25, 0x9e, 0xb7, + 0xe5, 0x1a, 0xcc, 0xef, 0x31, 0x7e, 0xd4, 0x39, 0x21, 0xc7, 0xd0, 0x37, + 0xd7, 0xc5, 0x95, 0x8d, 0xcf, 0xac, 0xb2, 0x7b, 0xf2, 0xaa, 0x63, 0x34, + 0x66, 0xdd, 0x7c, 0xe1, 0xd9, 0x93, 0xe4, 0xc0, 0xac, 0x5e, 0x77, 0xe5, + 0x9a, 0xa1, 0x8c, 0x46, 0xa0, 0xfd, 0x76, 0x77, 0x27, 0x7b, 0xcc, 0x59, + 0xc3, 0x84, 0xf4, 0x97, 0xcc, 0xf8, 0x2f, 0xea, 0x7d, 0x93, 0x66, 0x7f, + 0xb8, 0xd9, 0x53, 0xb9, 0x5f, 0x2e, 0xa6, 0xa2, 0x55, 0x73, 0x5b, 0x27, + 0xc3, 0xc0, 0x85, 0x5e, 0xcb, 0x84, 0x5d, 0x9c, 0xeb, 0x7e, 0xbc, 0x89, + 0x67, 0xd1, 0xa2, 0x98, 0x9f, 0xc2, 0x38, 0xcf, 0xa7, 0xb3, 0xdd, 0x2b, + 0xb5, 0x45, 0x31, 0xcb, 0xb3, 0x4e, 0x90, 0x95, 0x6f, 0xdd, 0x12, 0xaf, + 0xd7, 0xf9, 0x2b, 0xec, 0x99, 0x16, 0xd8, 0x0d, 0xbb, 0x02, 0xf9, 0x33, + 0xe8, 0xc9, 0xd3, 0x76, 0x4c, 0x09, 0x1d, 0x93, 0x92, 0xe0, 0x7c, 0x2a, + 0x6e, 0xe3, 0xce, 0x1c, 0xcb, 0x98, 0xa5, 0x6f, 0x63, 0xff, 0xcc, 0xdb, + 0xd0, 0x5d, 0x9a, 0xd6, 0x1f, 0xd7, 0xb2, 0xb0, 0xcb, 0xda, 0xce, 0x3a, + 0x8e, 0x73, 0x42, 0xf4, 0x1e, 0xac, 0xd0, 0x37, 0xea, 0xa8, 0xf2, 0x0b, + 0x8c, 0x2f, 0x57, 0x18, 0x5b, 0x4e, 0x46, 0xcd, 0xfb, 0x84, 0xf4, 0xe5, + 0xf6, 0x6c, 0xe2, 0xdd, 0x30, 0xa1, 0x2f, 0xd7, 0x65, 0x7d, 0xb9, 0x46, + 0xed, 0xcb, 0x99, 0xd8, 0x43, 0xe3, 0x9c, 0x2f, 0x57, 0x18, 0xcb, 0x83, + 0x56, 0x6a, 0xed, 0x59, 0x09, 0x63, 0x0b, 0x0d, 0x17, 0x5d, 0xbd, 0x6f, + 0x24, 0x37, 0xa0, 0xe0, 0x37, 0x18, 0x1f, 0x8b, 0xb1, 0x0a, 0xa5, 0xfe, + 0xce, 0xfa, 0x17, 0x1b, 0x24, 0xd3, 0xbc, 0x02, 0xe3, 0x7e, 0x4a, 0xcf, + 0xb9, 0x59, 0xc3, 0x82, 0x5c, 0x1b, 0x64, 0xcc, 0x87, 0x67, 0x47, 0x35, + 0x7f, 0x25, 0x7a, 0x23, 0x9d, 0xc6, 0x9e, 0xf5, 0x13, 0x6b, 0xa5, 0xfe, + 0xb8, 0x53, 0x18, 0x8f, 0xda, 0x7e, 0x13, 0x80, 0xa9, 0x06, 0x73, 0xf3, + 0x4e, 0x2b, 0x93, 0xd9, 0xf7, 0x3b, 0xea, 0x18, 0x1b, 0x98, 0x2a, 0x9a, + 0x18, 0x60, 0x5f, 0x31, 0x12, 0x9e, 0x5b, 0x57, 0x5c, 0x47, 0xce, 0x0c, + 0xae, 0x00, 0x2c, 0x2b, 0x96, 0xb5, 0x59, 0x1f, 0x7b, 0x43, 0x1d, 0x45, + 0x9a, 0x7a, 0x4a, 0xef, 0x2f, 0x5c, 0xd9, 0x9d, 0xdc, 0xa9, 0xcf, 0x23, + 0xe9, 0x58, 0x62, 0x5e, 0xb8, 0x7f, 0xf7, 0x9b, 0xf2, 0x36, 0x2d, 0xfb, + 0x0f, 0xa4, 0xa8, 0xc7, 0xb6, 0xe9, 0xdf, 0xb5, 0xe9, 0x20, 0x38, 0xdf, + 0xfd, 0x2c, 0x6c, 0x16, 0xdf, 0xfb, 0x96, 0xb4, 0xc7, 0x7b, 0xb5, 0x0d, + 0x85, 0xb9, 0x1a, 0xac, 0x97, 0x15, 0xfe, 0xb8, 0xdd, 0xab, 0x68, 0xd6, + 0x03, 0x0b, 0xc2, 0xfb, 0x17, 0x3a, 0x6c, 0x5e, 0x3e, 0xa8, 0x07, 0x3d, + 0x7d, 0x44, 0x8c, 0xac, 0xc9, 0xcd, 0xcb, 0x1a, 0xee, 0xa7, 0xcb, 0x90, + 0xa0, 0xdd, 0x23, 0x92, 0xe4, 0xdd, 0x49, 0xec, 0xbb, 0x20, 0x57, 0x41, + 0x3f, 0xb3, 0x1e, 0x6d, 0x56, 0x7e, 0x73, 0x0f, 0x8a, 0xef, 0x1d, 0x84, + 0x8e, 0xb9, 0x61, 0xa9, 0x8e, 0x89, 0xd3, 0xbf, 0xcf, 0x8d, 0xd2, 0x47, + 0x5c, 0x89, 0x3a, 0x2d, 0xf2, 0xd1, 0xb1, 0xdf, 0x5a, 0x4b, 0x1e, 0x1b, + 0x82, 0x7c, 0x57, 0xf7, 0x87, 0xe7, 0x2e, 0x99, 0xc6, 0x7c, 0xb6, 0x5b, + 0x27, 0x89, 0xf7, 0x79, 0xf2, 0xc5, 0x4a, 0x32, 0x31, 0x0b, 0x1d, 0x35, + 0xe4, 0x0c, 0xb7, 0x9a, 0xd8, 0xe9, 0xa7, 0xd6, 0x9a, 0x73, 0x5a, 0xf5, + 0xc0, 0x69, 0x18, 0x4f, 0xad, 0xa6, 0xdd, 0x59, 0x2b, 0x97, 0x83, 0xa0, + 0xbe, 0x5b, 0xcb, 0xe2, 0x9d, 0x94, 0xc5, 0x07, 0x52, 0x1d, 0x86, 0x07, + 0xb4, 0xef, 0xc4, 0x3d, 0x00, 0xc0, 0x43, 0xb7, 0xcb, 0xbd, 0xd0, 0x96, + 0x4f, 0xfd, 0xcc, 0x8c, 0x95, 0x4f, 0xca, 0x59, 0xca, 0x9f, 0x6a, 0x6b, + 0x74, 0x81, 0xec, 0x3d, 0x34, 0x46, 0xbd, 0x9c, 0x9a, 0xfe, 0x26, 0xe4, + 0x55, 0x4e, 0xe3, 0xa1, 0x45, 0xee, 0x1b, 0x93, 0xcc, 0x45, 0xe8, 0xac, + 0xc2, 0xd4, 0x42, 0x1e, 0x5d, 0xda, 0x1e, 0xc7, 0x7a, 0x7a, 0xad, 0xf1, + 0x71, 0x17, 0x8e, 0x75, 0x9a, 0x7b, 0x8c, 0xf4, 0x58, 0xb9, 0x37, 0xff, + 0x9c, 0x1d, 0xeb, 0xca, 0x70, 0xac, 0x3d, 0x0b, 0xc7, 0x1a, 0xfa, 0xf8, + 0xa1, 0xfc, 0x4d, 0xe8, 0xb3, 0x49, 0xfa, 0x4c, 0xcc, 0xd8, 0x4a, 0xe9, + 0x1d, 0x6d, 0xb4, 0x72, 0xd3, 0x83, 0x0e, 0xe2, 0x79, 0xa1, 0xe9, 0xcf, + 0x79, 0x62, 0x71, 0xa6, 0x88, 0x07, 0xca, 0xdc, 0x26, 0x7d, 0x9e, 0x71, + 0x02, 0x7e, 0xd6, 0x87, 0x8b, 0x2c, 0x1b, 0xe6, 0x5f, 0x29, 0x46, 0x1c, + 0xfa, 0xd6, 0xf4, 0x9f, 0x3a, 0x97, 0xc4, 0x16, 0x4c, 0x1c, 0x98, 0xf1, + 0x5f, 0x73, 0xcf, 0x02, 0xf7, 0x7d, 0xdf, 0x01, 0xde, 0xfa, 0xed, 0x62, + 0xb2, 0x27, 0x1b, 0xa1, 0x3c, 0x9d, 0x95, 0x43, 0x95, 0x3e, 0x69, 0xd3, + 0x67, 0xed, 0xdf, 0x30, 0x46, 0x9c, 0xa9, 0x8e, 0x11, 0x8b, 0x63, 0x62, + 0xc4, 0x3b, 0x7f, 0x8e, 0x18, 0xb1, 0x38, 0x26, 0x46, 0xbc, 0x9c, 0x9f, + 0x35, 0x52, 0x9a, 0xc5, 0xb8, 0xea, 0x21, 0x53, 0x94, 0x93, 0x9b, 0x6a, + 0xc0, 0xbb, 0x16, 0x6f, 0xc0, 0x32, 0x56, 0xc0, 0xdb, 0xc3, 0xfb, 0x20, + 0xde, 0x31, 0x19, 0x99, 0xd3, 0x1d, 0xb3, 0x90, 0x1f, 0xd4, 0x69, 0xac, + 0x6b, 0xfc, 0x82, 0xc9, 0x72, 0x33, 0xca, 0x5d, 0x72, 0x26, 0x58, 0xaf, + 0xd4, 0x28, 0xc3, 0x63, 0x94, 0xdd, 0x4d, 0x32, 0x3a, 0x16, 0xda, 0xb8, + 0x9f, 0x5d, 0xcf, 0xb5, 0x81, 0x21, 0x09, 0x6d, 0xd8, 0x67, 0xd6, 0x9b, + 0xb5, 0xdb, 0x2d, 0x31, 0xa9, 0x5f, 0x8d, 0x39, 0x38, 0xee, 0x5c, 0x1c, + 0x5f, 0xbd, 0xc0, 0x96, 0x4d, 0xd8, 0xd8, 0xe0, 0xb8, 0xd5, 0xc1, 0xcb, + 0xcb, 0x88, 0xea, 0xf9, 0x8f, 0xdb, 0x73, 0xbc, 0x51, 0x7b, 0xd7, 0x5f, + 0x42, 0xcf, 0xcf, 0x40, 0x65, 0x16, 0xfd, 0xad, 0x57, 0x99, 0x71, 0x8e, + 0x73, 0xee, 0x7e, 0x1e, 0xc8, 0xc5, 0x56, 0x35, 0x34, 0xbe, 0x80, 0x2e, + 0x41, 0xb7, 0x1c, 0x9b, 0x03, 0xda, 0xbd, 0x57, 0x26, 0x46, 0x09, 0x5f, + 0x47, 0x3c, 0xa2, 0xcf, 0xf5, 0xe2, 0x7b, 0xdc, 0x9c, 0x27, 0xea, 0xad, + 0x84, 0x67, 0x7a, 0xd7, 0x00, 0xde, 0xc5, 0xe7, 0x7a, 0xad, 0x9e, 0xd6, + 0x36, 0x04, 0xcf, 0xf7, 0x86, 0x63, 0x58, 0x8e, 0x9e, 0x02, 0x19, 0xd6, + 0xfb, 0x7d, 0xd7, 0xca, 0xe9, 0x07, 0xe7, 0xce, 0x17, 0x34, 0xc1, 0x56, + 0x69, 0x85, 0xa9, 0x3c, 0xe0, 0xa6, 0xb9, 0xef, 0x82, 0xfb, 0x0b, 0x3a, + 0xe2, 0xb7, 0xe9, 0x73, 0x1f, 0xf3, 0x67, 0xac, 0xe7, 0xcf, 0x7e, 0x84, + 0x67, 0x5a, 0xe3, 0xd2, 0x07, 0x3a, 0xec, 0xd7, 0xe9, 0x31, 0x8c, 0x87, + 0x6b, 0xbe, 0x1a, 0x0f, 0x90, 0x3d, 0x5c, 0xfb, 0xc5, 0xd8, 0x2b, 0x2d, + 0x2a, 0xa7, 0xcf, 0x58, 0x47, 0x2d, 0x8d, 0x5d, 0x76, 0xf6, 0x94, 0x13, + 0x6a, 0x4f, 0xd9, 0x57, 0x7b, 0xcb, 0x36, 0xaf, 0xfb, 0x01, 0xcc, 0x07, + 0x7e, 0x8f, 0x17, 0x9d, 0x21, 0xe0, 0xab, 0x50, 0x3a, 0xe2, 0x64, 0xf4, + 0xfb, 0xa8, 0x7d, 0x43, 0x0e, 0x60, 0xae, 0x7a, 0xc7, 0xa3, 0x5a, 0xde, + 0xcf, 0xdf, 0xd3, 0x17, 0xce, 0xeb, 0x0b, 0x7a, 0x0d, 0x68, 0x5a, 0x88, + 0x6b, 0xcf, 0xda, 0x10, 0xc7, 0x9d, 0x9c, 0xc6, 0x3d, 0xcb, 0x7c, 0x4b, + 0xff, 0x06, 0x9d, 0x2b, 0xd3, 0x5e, 0x2b, 0xde, 0x8b, 0xf7, 0x4d, 0x86, + 0xfa, 0x86, 0x70, 0xdf, 0x09, 0xbd, 0x16, 0xec, 0x37, 0xf2, 0x6a, 0x56, + 0x46, 0x2a, 0x5c, 0xc3, 0x64, 0x3b, 0x48, 0x2f, 0xd7, 0xc0, 0x1e, 0x58, + 0x78, 0xbe, 0xba, 0x7f, 0x7e, 0x1e, 0x12, 0xe3, 0x42, 0x58, 0xee, 0xd6, + 0x67, 0x17, 0xab, 0xef, 0x1e, 0xb9, 0xf2, 0xbf, 0x70, 0xfd, 0xd0, 0xc8, + 0x50, 0x0b, 0x47, 0x86, 0xf2, 0xce, 0xc8, 0x95, 0xaf, 0xcb, 0x41, 0xe0, + 0xf1, 0x30, 0x60, 0x52, 0xf7, 0xf3, 0xce, 0xab, 0x57, 0xa5, 0x30, 0x59, + 0x2f, 0xea, 0xa1, 0x82, 0xe3, 0x3e, 0x54, 0x2b, 0x91, 0x87, 0x94, 0x53, + 0xf3, 0x50, 0xbb, 0xf6, 0xcf, 0x77, 0xa4, 0xda, 0xe3, 0x7b, 0xe5, 0xb8, + 0xe3, 0xde, 0xaf, 0xf4, 0x59, 0xdb, 0x82, 0xc7, 0x58, 0xdf, 0x71, 0x27, + 0x72, 0x7f, 0xd4, 0x9e, 0xd3, 0x37, 0xf1, 0xbd, 0x59, 0xcd, 0xf7, 0xdf, + 0x58, 0x47, 0x9c, 0xcd, 0x0a, 0xf1, 0xf1, 0x59, 0xc8, 0xad, 0x4f, 0x4b, + 0x76, 0x34, 0x31, 0x57, 0xc6, 0xec, 0xb3, 0xdf, 0xb0, 0xce, 0xf0, 0x0b, + 0xcb, 0xbc, 0xe2, 0xf0, 0xce, 0x1c, 0xa3, 0x33, 0x3e, 0xdf, 0x12, 0xee, + 0xb9, 0x37, 0x73, 0xca, 0xfc, 0xc6, 0x75, 0x52, 0xff, 0x0a, 0xe6, 0x8b, + 0xfd, 0x11, 0x57, 0xab, 0xf4, 0x3d, 0x05, 0x9e, 0x6c, 0x89, 0xd7, 0xcd, + 0xd9, 0x43, 0x46, 0xf6, 0xd6, 0x01, 0x6e, 0xc0, 0x6f, 0xec, 0x3b, 0x21, + 0x9d, 0x0a, 0x24, 0x37, 0x69, 0xb6, 0xa3, 0x67, 0x87, 0x98, 0x39, 0x33, + 0x34, 0xb3, 0xc2, 0xd8, 0x91, 0xf8, 0x36, 0x74, 0xa1, 0x64, 0xfb, 0xd8, + 0x4b, 0x4e, 0x3f, 0xcf, 0x3c, 0x8a, 0xb6, 0x1b, 0x97, 0xb3, 0x09, 0xc1, + 0x4b, 0xcf, 0x5b, 0xff, 0x32, 0x08, 0xc6, 0x52, 0x29, 0xde, 0x2b, 0xb8, + 0x8c, 0x4f, 0xb9, 0xca, 0x99, 0x1c, 0x6d, 0x70, 0x26, 0x46, 0x03, 0xd9, + 0x93, 0xe2, 0x9d, 0x49, 0xdc, 0x93, 0xa0, 0xe3, 0xe3, 0x48, 0x6b, 0x87, + 0x6e, 0x7d, 0xc7, 0x3a, 0xee, 0x71, 0xbb, 0xd9, 0x6f, 0xb4, 0xe5, 0x88, + 0x63, 0xfa, 0xca, 0xed, 0x27, 0x72, 0xc2, 0xbb, 0x8b, 0xb6, 0xc4, 0x63, + 0x7a, 0x7f, 0xe2, 0x17, 0x50, 0x0f, 0x7d, 0x94, 0xd8, 0xaf, 0xeb, 0x4c, + 0x40, 0x9e, 0x4d, 0x8e, 0xf1, 0xbe, 0x14, 0x9e, 0x63, 0x88, 0xb4, 0x2a, + 0xb9, 0xd6, 0x1b, 0xb6, 0xf7, 0x69, 0xe6, 0xe1, 0x0a, 0x45, 0x74, 0xda, + 0x16, 0x6f, 0xf7, 0xdc, 0x1d, 0x9b, 0x61, 0x5a, 0x78, 0xd7, 0xa6, 0xd2, + 0x67, 0x56, 0xe0, 0xd3, 0x9e, 0x1e, 0x92, 0xb8, 0x33, 0x55, 0x6c, 0x75, + 0x4e, 0x16, 0x33, 0x5b, 0xd7, 0x81, 0x3e, 0xce, 0xa7, 0x3e, 0x46, 0xf9, + 0x05, 0xdb, 0xef, 0x45, 0xc9, 0x57, 0x3e, 0x24, 0xe3, 0x2d, 0xed, 0xde, + 0xfd, 0x7a, 0x6e, 0x2e, 0x03, 0x67, 0x2d, 0x2a, 0x3b, 0xfa, 0xc4, 0x3a, + 0xea, 0xb7, 0xdd, 0x45, 0x05, 0x5e, 0x56, 0xbf, 0x88, 0x07, 0x36, 0x6e, + 0xad, 0xb6, 0x51, 0xf6, 0xa6, 0x58, 0xae, 0xc1, 0xe9, 0x1d, 0x5d, 0x85, + 0x79, 0xdc, 0x05, 0xfd, 0xe9, 0xc0, 0x46, 0x22, 0xae, 0x1b, 0x9c, 0x3d, + 0xa3, 0x79, 0xf4, 0xc8, 0x7d, 0xd6, 0xbc, 0xf7, 0xf0, 0x30, 0xc6, 0xa8, + 0xe5, 0x2b, 0x78, 0xf7, 0x12, 0xd7, 0xdb, 0x83, 0x49, 0xd8, 0x06, 0xb9, + 0xae, 0x7f, 0x67, 0xd7, 0xab, 0xa7, 0xaf, 0xb0, 0x5e, 0xed, 0xc9, 0x23, + 0x15, 0x7d, 0x6f, 0x48, 0xe7, 0xb8, 0xe2, 0x3a, 0x6e, 0xf3, 0x55, 0x7a, + 0x7e, 0x54, 0x87, 0xdd, 0x1b, 0x78, 0x72, 0x9d, 0xbd, 0xd3, 0x06, 0x70, + 0x5c, 0x05, 0x18, 0x36, 0x62, 0xfc, 0x84, 0xc1, 0xd4, 0x11, 0x75, 0x4b, + 0x9c, 0x3a, 0x70, 0x56, 0x4e, 0xaf, 0x0b, 0xf7, 0x7b, 0xa0, 0x1d, 0xc8, + 0xb5, 0x47, 0xe3, 0x46, 0x37, 0xae, 0x5d, 0xa6, 0x9d, 0x70, 0x3c, 0x8e, + 0x1d, 0x0f, 0x69, 0x75, 0x43, 0x0b, 0xfd, 0x89, 0x59, 0xa9, 0x5b, 0x54, + 0x9e, 0xf1, 0xfc, 0x5d, 0xad, 0x66, 0xdf, 0x11, 0xcb, 0x7a, 0xb0, 0x4b, + 0x69, 0xe3, 0x12, 0x77, 0x7a, 0xae, 0x8a, 0xdc, 0x5b, 0x9c, 0xf3, 0x2f, + 0x43, 0x9e, 0x5c, 0xeb, 0xbd, 0x4d, 0x91, 0xf6, 0x42, 0xfc, 0x12, 0xb7, + 0x09, 0xe0, 0x95, 0x71, 0x95, 0xd3, 0x41, 0x66, 0x80, 0x7c, 0xc5, 0x36, + 0x98, 0xff, 0xa2, 0x8e, 0xe5, 0x0e, 0xa6, 0x18, 0x27, 0x6a, 0x3f, 0x71, + 0x87, 0x0a, 0x65, 0xd3, 0x2c, 0xd7, 0x10, 0x1c, 0xde, 0x21, 0xba, 0x0b, + 0x1d, 0x5e, 0x9c, 0x52, 0xce, 0x37, 0xc7, 0x5c, 0x7c, 0xd7, 0xd8, 0xfb, + 0x42, 0x8d, 0x6e, 0x12, 0xf9, 0xeb, 0x70, 0xbc, 0xf1, 0x3c, 0xe6, 0xfb, + 0x12, 0xe6, 0x7b, 0xf9, 0xfb, 0x41, 0x91, 0x57, 0x46, 0x5e, 0xf9, 0x43, + 0x41, 0xa6, 0x89, 0xf4, 0x47, 0x9a, 0x7b, 0x3d, 0x9f, 0x59, 0xef, 0x63, + 0x02, 0x6c, 0x67, 0xc1, 0x0b, 0x19, 0xae, 0x25, 0x07, 0xc7, 0x52, 0x37, + 0x81, 0x17, 0x76, 0xca, 0x9f, 0xc0, 0x16, 0xf8, 0xe3, 0x4a, 0x1a, 0x3c, + 0xd1, 0x03, 0x1e, 0xe9, 0x06, 0x5f, 0xa4, 0xb4, 0x5d, 0xfc, 0x28, 0x74, + 0xde, 0xd9, 0x4a, 0xc9, 0xd9, 0x3b, 0x5a, 0x74, 0x72, 0xa3, 0x47, 0x41, + 0x17, 0xdc, 0x03, 0xab, 0xae, 0xa9, 0x11, 0x37, 0x3e, 0x29, 0xa4, 0xff, + 0x76, 0xee, 0xed, 0x68, 0x06, 0xae, 0xce, 0x10, 0x57, 0x93, 0x95, 0x2d, + 0xde, 0x3a, 0xf0, 0x41, 0xb3, 0xe6, 0x83, 0x46, 0x27, 0xe3, 0xdd, 0x64, + 0xf9, 0x60, 0x04, 0x7c, 0x50, 0x58, 0xc2, 0x07, 0xcf, 0x58, 0x9a, 0x9f, + 0xae, 0xe2, 0x83, 0x49, 0x9b, 0x36, 0x7e, 0x05, 0x3e, 0xb8, 0xca, 0x4f, + 0x3e, 0x39, 0x24, 0x27, 0xc0, 0x07, 0x0f, 0x6b, 0x3e, 0xb8, 0x4a, 0xf3, + 0x01, 0xe3, 0x46, 0xe4, 0x85, 0x56, 0xc8, 0x0e, 0xf2, 0xc2, 0xb3, 0x32, + 0x0b, 0x5e, 0x78, 0x51, 0xb1, 0xef, 0xcb, 0xb4, 0x0f, 0x46, 0xe9, 0x8f, + 0x9d, 0x2a, 0x15, 0xc1, 0xbb, 0x4a, 0xbe, 0x30, 0x16, 0x04, 0x33, 0xf0, + 0xd1, 0x1f, 0x84, 0x0d, 0xef, 0xea, 0x3b, 0x69, 0xa7, 0x61, 0xbb, 0x10, + 0x36, 0xda, 0xe4, 0xe3, 0x0e, 0xe8, 0xfd, 0xf0, 0x04, 0xc6, 0xb0, 0x47, + 0xfd, 0x3e, 0xfc, 0x60, 0x0f, 0xf3, 0x4a, 0xdb, 0xfe, 0xb8, 0xe6, 0x9b, + 0x1a, 0xe8, 0x80, 0x93, 0xdd, 0x8c, 0x33, 0xf9, 0xde, 0x5e, 0xd5, 0x9e, + 0xef, 0x03, 0xcc, 0x11, 0x75, 0xbf, 0x30, 0xc6, 0xd1, 0xb4, 0xc8, 0xb6, + 0xa7, 0x5c, 0x18, 0x90, 0xfb, 0x6c, 0x5e, 0x3e, 0xa8, 0x83, 0x1d, 0x5a, + 0xa7, 0x8c, 0x5d, 0xae, 0xb6, 0x25, 0xbd, 0xdf, 0x80, 0xd0, 0xac, 0x4d, + 0x9b, 0x3d, 0x81, 0x7d, 0xc5, 0x6a, 0xbb, 0xfe, 0x5e, 0xd8, 0xf5, 0xac, + 0x23, 0xae, 0xb1, 0xeb, 0xef, 0xb2, 0xbc, 0xc6, 0xdf, 0x9e, 0xb6, 0xf1, + 0x0f, 0x00, 0xbe, 0x1d, 0x73, 0x36, 0x3e, 0xdb, 0xa0, 0xad, 0x21, 0x72, + 0x03, 0xec, 0xbc, 0x1b, 0xc1, 0x83, 0x37, 0xc1, 0x8f, 0x7a, 0x77, 0xd1, + 0x93, 0x9d, 0xc5, 0x66, 0xf8, 0xdb, 0xad, 0xf2, 0xab, 0x63, 0x1b, 0xa5, + 0x7f, 0xf4, 0x77, 0x9a, 0xa1, 0x57, 0x61, 0x97, 0xbe, 0x08, 0x38, 0x23, + 0x56, 0x56, 0x47, 0xc1, 0x03, 0xed, 0x89, 0x1f, 0xa8, 0x44, 0xab, 0x91, + 0xed, 0x3c, 0x4b, 0xbe, 0x5c, 0x3b, 0x31, 0xd4, 0x67, 0x1c, 0xa5, 0x45, + 0xce, 0x1c, 0xa7, 0xe7, 0x95, 0x80, 0x2d, 0x9e, 0x82, 0x1d, 0xb2, 0x01, + 0xed, 0x31, 0x96, 0xbc, 0x5a, 0x9e, 0xd9, 0xea, 0xde, 0x9d, 0xd3, 0x7c, + 0x78, 0xc9, 0xc9, 0x8e, 0xdd, 0x24, 0x85, 0xc1, 0x28, 0xc6, 0xa0, 0x9a, + 0xd7, 0xca, 0xf5, 0xd2, 0xaf, 0xc7, 0x73, 0x59, 0x0e, 0x42, 0x1f, 0xff, + 0x69, 0xb1, 0x5f, 0x66, 0x07, 0x9a, 0xf0, 0x1d, 0x95, 0x67, 0x8a, 0x5b, + 0xe0, 0xef, 0xfc, 0x0a, 0x70, 0x54, 0x8b, 0xef, 0x5a, 0xe9, 0x5d, 0x47, + 0x5e, 0x6d, 0x90, 0x19, 0xa4, 0xdf, 0x28, 0xbf, 0x64, 0xd3, 0x99, 0x46, + 0xde, 0x68, 0x40, 0xdd, 0xa8, 0x9c, 0x2f, 0xd2, 0x96, 0xd4, 0x3c, 0xd1, + 0xf3, 0xb2, 0x6c, 0xc9, 0xbc, 0x0c, 0xdb, 0xf4, 0x59, 0x3c, 0xcf, 0x4b, + 0x72, 0xe7, 0x6e, 0x67, 0x4b, 0xa2, 0xdd, 0x81, 0xbe, 0xc4, 0xe3, 0x3a, + 0x5b, 0xbc, 0x5a, 0xe7, 0x5a, 0xdb, 0x46, 0x8d, 0x3c, 0x3f, 0xa8, 0xe2, + 0x0d, 0x98, 0x93, 0xcd, 0x4e, 0x87, 0x4d, 0xe3, 0xb7, 0xbe, 0x2f, 0x51, + 0xda, 0xcf, 0xa8, 0x0d, 0xab, 0x44, 0xda, 0x1a, 0x60, 0xe7, 0xec, 0x11, + 0xd5, 0xdc, 0x20, 0xae, 0xb4, 0x4f, 0xa8, 0x56, 0xa4, 0xf9, 0x36, 0x2d, + 0xd6, 0x00, 0x9d, 0x80, 0xb4, 0x16, 0xa4, 0x6d, 0xb2, 0x69, 0x4d, 0x0d, + 0x52, 0x8b, 0xb4, 0xcb, 0x9a, 0xe7, 0x2f, 0x76, 0xf8, 0x5e, 0xce, 0xa9, + 0x97, 0xb6, 0x53, 0x0d, 0x90, 0x0d, 0xab, 0x65, 0x66, 0x6b, 0x9d, 0xb4, + 0x21, 0x8f, 0x31, 0xee, 0xd4, 0xa9, 0xa8, 0xbc, 0xf3, 0x54, 0x7b, 0xfc, + 0xa3, 0x18, 0x43, 0xfb, 0x19, 0xc6, 0xbc, 0xff, 0xac, 0x99, 0x31, 0x9f, + 0xb6, 0x33, 0x7c, 0xd7, 0x69, 0xf9, 0x43, 0x7c, 0x98, 0x3b, 0xdf, 0x60, + 0x63, 0x94, 0x8e, 0x3b, 0xc3, 0xa3, 0xd4, 0xdb, 0xed, 0xf6, 0x7e, 0xa2, + 0xff, 0xd9, 0x4c, 0x5f, 0x6d, 0x82, 0x36, 0x54, 0x89, 0xfc, 0x48, 0xdd, + 0x83, 0xf7, 0xb8, 0x23, 0x85, 0x79, 0x99, 0x35, 0x45, 0xbe, 0x3a, 0xae, + 0xb8, 0x4f, 0x05, 0x69, 0x95, 0x77, 0x05, 0x66, 0x8e, 0xc9, 0x0b, 0x46, + 0x2e, 0xfd, 0x9a, 0x91, 0x4b, 0xa7, 0xcf, 0x2d, 0x90, 0x4b, 0x05, 0x2d, + 0x97, 0x06, 0x05, 0xef, 0xa9, 0x02, 0xe4, 0xd2, 0x08, 0xbe, 0x3d, 0x2d, + 0x97, 0x62, 0x62, 0x6d, 0x64, 0x89, 0x5e, 0xc5, 0xfe, 0x27, 0x4b, 0xae, + 0xb6, 0xa5, 0x0a, 0xe3, 0xb0, 0x43, 0x4a, 0x23, 0x56, 0x67, 0x4b, 0xba, + 0x49, 0x3a, 0x7a, 0x7e, 0x2a, 0xa1, 0x9d, 0x39, 0xdb, 0xcc, 0x3b, 0x8f, + 0x5f, 0x54, 0x94, 0x61, 0x27, 0x20, 0xc3, 0x1e, 0xbe, 0x82, 0x0c, 0x43, + 0x5e, 0x19, 0x79, 0x65, 0xb6, 0xfb, 0xdd, 0x9f, 0x0e, 0x79, 0x94, 0x1f, + 0x94, 0x19, 0x90, 0x49, 0x25, 0xc8, 0xa4, 0x12, 0xe4, 0x54, 0x09, 0x72, + 0xa9, 0x04, 0xb9, 0x54, 0x82, 0x5c, 0x2a, 0x41, 0x2e, 0x41, 0xc6, 0x3d, + 0x0a, 0x19, 0x67, 0x64, 0xda, 0x00, 0xed, 0x35, 0xb9, 0xcf, 0xea, 0x77, + 0x13, 0x27, 0xe9, 0xb2, 0x7e, 0x91, 0xd9, 0xb3, 0x7a, 0xae, 0x2a, 0x2e, + 0xb8, 0xeb, 0x88, 0xe6, 0x77, 0xcf, 0x57, 0xd7, 0x3a, 0xdc, 0x1f, 0xf3, + 0x03, 0xed, 0xb3, 0x6f, 0xe6, 0x6f, 0xa9, 0x03, 0x5f, 0xbf, 0x62, 0xf9, + 0x7a, 0xf3, 0x1c, 0x5f, 0x27, 0x1d, 0xc6, 0x89, 0x97, 0xe7, 0xeb, 0x16, + 0x9b, 0x97, 0x0f, 0x56, 0x80, 0xaf, 0x57, 0x2c, 0xe2, 0xeb, 0x28, 0xf8, + 0x7a, 0xe7, 0x12, 0xbe, 0x5e, 0xe5, 0xf4, 0xea, 0x3a, 0x3c, 0x83, 0xc6, + 0xef, 0x5a, 0x67, 0x9e, 0xaf, 0xf7, 0x6b, 0xbe, 0x3e, 0x04, 0xbe, 0xbe, + 0xbe, 0x8a, 0xaf, 0x77, 0x4a, 0xf2, 0x96, 0x6c, 0x64, 0xa3, 0xec, 0xbe, + 0x5f, 0x35, 0xaf, 0x91, 0x7f, 0x11, 0x53, 0xdf, 0xf0, 0x58, 0xef, 0x58, + 0xb3, 0xe4, 0x1e, 0xfa, 0x11, 0xd7, 0x06, 0xc8, 0x23, 0x43, 0x19, 0xc7, + 0x93, 0x83, 0x47, 0x7e, 0x20, 0xd3, 0x9a, 0xb7, 0x44, 0xf6, 0x1c, 0x89, + 0xca, 0xf0, 0x11, 0xc6, 0x1e, 0xbe, 0x63, 0xe9, 0xbd, 0x4e, 0x86, 0x07, + 0xb9, 0x5f, 0xd2, 0x95, 0xdd, 0x47, 0xe0, 0x63, 0x1d, 0x61, 0xec, 0xe1, + 0xf2, 0x1c, 0x8f, 0x4d, 0x43, 0xb6, 0xec, 0x3e, 0xa2, 0xe7, 0x1a, 0xed, + 0x34, 0xc8, 0xa1, 0x23, 0x22, 0xb7, 0x1d, 0x71, 0xe5, 0xf6, 0x23, 0x73, + 0xbc, 0x36, 0x10, 0xf2, 0xda, 0x9f, 0x83, 0xd7, 0xda, 0x2d, 0xaf, 0xa9, + 0x39, 0x5e, 0xfb, 0x5a, 0x15, 0xaf, 0xb1, 0x3e, 0x79, 0xed, 0x82, 0x4d, + 0xe3, 0xb7, 0x2b, 0x7b, 0x8f, 0xb4, 0xca, 0xee, 0x87, 0xde, 0x22, 0x7b, + 0xee, 0x27, 0xac, 0xe6, 0x9e, 0x3c, 0xda, 0x5f, 0xe3, 0x95, 0x76, 0xb4, + 0x1f, 0xee, 0x0f, 0xd2, 0x77, 0x65, 0x75, 0x4e, 0x48, 0x32, 0xcf, 0xfe, + 0x6a, 0xe1, 0x3b, 0x9f, 0x82, 0x4f, 0xb1, 0x17, 0x30, 0xdd, 0x7a, 0x44, + 0x92, 0xae, 0xbc, 0x26, 0x23, 0xa9, 0x47, 0x5b, 0x8d, 0x3d, 0x71, 0x09, + 0xbc, 0x42, 0xfa, 0xcf, 0x48, 0xee, 0xed, 0x81, 0xf6, 0x2b, 0x46, 0xcb, + 0x42, 0xff, 0x9f, 0x31, 0x73, 0xc7, 0xdc, 0x77, 0xc7, 0xf3, 0xbe, 0x35, + 0xfa, 0xbc, 0x9b, 0x8e, 0xd7, 0x76, 0x33, 0xbf, 0x46, 0xef, 0x37, 0xcd, + 0xe9, 0xb3, 0xdc, 0xac, 0xcf, 0x76, 0x62, 0x3a, 0x9e, 0x5e, 0x28, 0xf3, + 0x8e, 0x30, 0xde, 0xbd, 0xcc, 0xbb, 0x06, 0xff, 0xf8, 0x2a, 0x13, 0x9b, + 0x25, 0xdf, 0x7d, 0xdd, 0xc9, 0x15, 0x2f, 0xe9, 0x7d, 0x85, 0x59, 0x1f, + 0xbf, 0xcb, 0xfc, 0x66, 0xf9, 0x4b, 0x8c, 0x71, 0x24, 0x12, 0xea, 0x81, + 0x56, 0xee, 0x3b, 0x18, 0x9c, 0x32, 0x76, 0x94, 0xe1, 0xd1, 0x06, 0xed, + 0x6b, 0x8c, 0xe0, 0x7b, 0xf7, 0x68, 0xa3, 0x53, 0xa0, 0x6d, 0x32, 0xd0, + 0xe0, 0xe4, 0xc7, 0xf7, 0xb4, 0x1a, 0x9b, 0x79, 0x20, 0xce, 0x3d, 0x85, + 0x19, 0xb5, 0x54, 0x26, 0x9f, 0x92, 0x50, 0x26, 0x27, 0x6f, 0xc9, 0xc0, + 0xb6, 0xce, 0x1d, 0xd1, 0xf7, 0xf7, 0x25, 0xda, 0x15, 0xc7, 0xf4, 0x09, + 0xc8, 0xd7, 0x90, 0x16, 0xe2, 0xf2, 0xf1, 0x23, 0xa4, 0x07, 0x15, 0x6b, + 0x94, 0xdf, 0xb2, 0xf4, 0x70, 0x59, 0x8a, 0x90, 0x3b, 0x47, 0x8e, 0xdc, + 0x2e, 0xe3, 0xbb, 0x16, 0xd3, 0xc3, 0x9e, 0x79, 0x7a, 0x88, 0xc1, 0x3e, + 0x73, 0xaa, 0xe9, 0xe1, 0x37, 0xe7, 0xe8, 0x61, 0xdc, 0xf9, 0xd7, 0xd2, + 0xc3, 0x0d, 0x0b, 0xe8, 0x61, 0x44, 0xd3, 0x43, 0xff, 0x1c, 0x3d, 0x8c, + 0x1c, 0x61, 0xbf, 0x7a, 0x5d, 0xd4, 0x9b, 0x71, 0x38, 0xe7, 0x73, 0xb4, + 0x90, 0x18, 0xd6, 0xfb, 0x44, 0x93, 0x79, 0x9e, 0x25, 0x5d, 0xa5, 0x18, + 0x1b, 0x99, 0x9f, 0xff, 0xc6, 0x7f, 0xd3, 0xf9, 0x7f, 0x47, 0xfc, 0xff, + 0xef, 0xfc, 0x5f, 0x8f, 0xf6, 0x29, 0x8b, 0x43, 0x79, 0x1c, 0xd2, 0xc3, + 0x7b, 0xe2, 0x46, 0x2f, 0x70, 0x8e, 0xf9, 0x6d, 0xf6, 0xac, 0x9f, 0x83, + 0xfc, 0x7b, 0x1c, 0xf2, 0xef, 0xb1, 0x05, 0xeb, 0x01, 0x3d, 0x36, 0x06, + 0x11, 0xc8, 0xc1, 0xd4, 0x3c, 0x3e, 0x66, 0xba, 0x89, 0x0f, 0xb3, 0xf7, + 0xe4, 0x6c, 0x65, 0x31, 0x4e, 0x5c, 0xbd, 0xdf, 0xe8, 0x64, 0xaa, 0x1a, + 0x27, 0x84, 0x7b, 0xb6, 0x6a, 0x8c, 0xf8, 0x5d, 0xe6, 0xf7, 0x65, 0xbd, + 0x87, 0xa4, 0xa0, 0xd7, 0x9f, 0x88, 0x17, 0xae, 0x3f, 0x11, 0x27, 0xae, + 0xb6, 0xf7, 0x0b, 0xe5, 0x3a, 0xbd, 0x2f, 0xfc, 0xc0, 0x54, 0x4c, 0x66, + 0x62, 0x8c, 0xeb, 0xf1, 0xde, 0x57, 0xfa, 0xca, 0x7e, 0xbc, 0x20, 0x79, + 0x7b, 0xd6, 0x67, 0x95, 0xa5, 0x6d, 0xc6, 0x03, 0x79, 0x27, 0x42, 0xb8, + 0x0e, 0xd1, 0x69, 0x65, 0x5d, 0x43, 0x55, 0x9c, 0x12, 0x78, 0x1f, 0x93, + 0x44, 0xb6, 0x1b, 0xef, 0x29, 0xf6, 0xfd, 0xa4, 0x8c, 0x3c, 0x58, 0x86, + 0x2d, 0xf7, 0x30, 0x74, 0x8e, 0x23, 0x10, 0x93, 0xfa, 0x2e, 0x14, 0xc2, + 0x30, 0xa1, 0xef, 0xf5, 0xa3, 0xdf, 0x47, 0x7a, 0x88, 0xe3, 0xfb, 0xb2, + 0x8d, 0x25, 0xc5, 0xa5, 0x50, 0xfc, 0x01, 0xe0, 0xe7, 0x1d, 0x94, 0x3f, + 0xc2, 0xfb, 0x8d, 0xe6, 0xc3, 0xf8, 0x21, 0x03, 0xfa, 0xcd, 0xb9, 0x79, + 0xcd, 0xc9, 0x94, 0xcd, 0xfe, 0x96, 0xaa, 0xfb, 0xf5, 0xe5, 0xb0, 0xb6, + 0x9f, 0xd3, 0x76, 0x5f, 0x0b, 0xcf, 0xe7, 0x19, 0x1b, 0xfa, 0xcb, 0xb0, + 0xa1, 0x9f, 0xa8, 0x64, 0xf4, 0x1a, 0xd6, 0x63, 0xb0, 0xa1, 0x1f, 0x85, + 0xee, 0xa1, 0xce, 0x89, 0x59, 0x9d, 0x33, 0xa2, 0x76, 0x69, 0x9d, 0xf3, + 0xd7, 0x5a, 0xe7, 0xfc, 0xea, 0x12, 0x9d, 0x73, 0x48, 0xb5, 0x8f, 0x52, + 0xe7, 0xf4, 0xaa, 0x9d, 0x0e, 0xed, 0xc5, 0xb5, 0xcb, 0xe8, 0x9c, 0xf7, + 0xca, 0xaf, 0xd8, 0xbc, 0xfd, 0xf2, 0xbe, 0x6d, 0x7a, 0xdd, 0xc6, 0x9b, + 0x50, 0xbc, 0xcb, 0xce, 0xe8, 0xa0, 0xeb, 0x55, 0xa7, 0x5e, 0xef, 0xfd, + 0x6a, 0x95, 0xce, 0x69, 0x53, 0xdd, 0x4e, 0xaf, 0xae, 0xc3, 0x78, 0x04, + 0xbf, 0x53, 0x4e, 0x66, 0xa0, 0x0e, 0xdf, 0x71, 0x89, 0x1c, 0xc1, 0xd8, + 0xcd, 0x7d, 0x7b, 0xca, 0xe4, 0x5d, 0x63, 0xf3, 0x54, 0x98, 0xee, 0x9a, + 0xf4, 0x76, 0x9b, 0x6e, 0x74, 0x55, 0x9b, 0x6a, 0xd5, 0xba, 0x6a, 0x33, + 0x18, 0x6a, 0x02, 0xfa, 0x75, 0xa2, 0x14, 0xea, 0x2c, 0xfe, 0x66, 0xbc, + 0x99, 0x71, 0x89, 0x30, 0x6e, 0x9d, 0x40, 0x19, 0x3c, 0xa5, 0xd0, 0xa6, + 0xe4, 0x6f, 0xf8, 0x0a, 0x78, 0xa6, 0x80, 0xd7, 0x5b, 0xc0, 0x3f, 0xbf, + 0x5e, 0x64, 0xdc, 0xb3, 0x59, 0x8e, 0x8e, 0x55, 0xe7, 0xb5, 0xca, 0xbb, + 0xc7, 0x36, 0xc8, 0xbe, 0x51, 0xff, 0x6a, 0xa9, 0xdf, 0x28, 0x23, 0xa3, + 0x2f, 0xea, 0xfb, 0x40, 0xd6, 0xe8, 0x7b, 0x92, 0x78, 0x7f, 0x98, 0x91, + 0x91, 0xfd, 0x8e, 0x91, 0x91, 0x19, 0x35, 0x6f, 0xb3, 0x86, 0x6d, 0xf2, + 0x6e, 0xa6, 0xbe, 0xd1, 0xb8, 0xbe, 0x43, 0x7a, 0xa2, 0x72, 0xad, 0xfc, + 0xd1, 0x71, 0x75, 0xa7, 0x9a, 0xbf, 0x4b, 0x41, 0xdb, 0xac, 0x93, 0x0b, + 0x6c, 0xd6, 0xbf, 0x97, 0x99, 0xf7, 0x45, 0x31, 0x4e, 0xd0, 0xf0, 0x75, + 0x2f, 0x73, 0x1d, 0xb4, 0x39, 0x26, 0x97, 0xa4, 0x4f, 0xe3, 0x8f, 0xf2, + 0xb4, 0x01, 0x72, 0x70, 0x56, 0xeb, 0xd7, 0xb5, 0xbc, 0xf3, 0xf8, 0x08, + 0x6d, 0xd7, 0xaf, 0x6b, 0x79, 0xb6, 0xd6, 0xda, 0xae, 0xd3, 0x90, 0xd3, + 0x94, 0xa3, 0x37, 0xca, 0x5f, 0xdb, 0x74, 0xa6, 0x25, 0xe3, 0xb3, 0x42, + 0x7d, 0x17, 0x83, 0x0c, 0xa5, 0x3c, 0xfd, 0x59, 0x6d, 0xd7, 0xe7, 0x6c, + 0x1b, 0x94, 0x9f, 0x46, 0x76, 0x6f, 0x76, 0xa6, 0x6d, 0x1a, 0xbf, 0xc3, + 0x18, 0xba, 0x9f, 0xc9, 0x59, 0x3e, 0x53, 0xce, 0x93, 0xc8, 0x5f, 0x83, + 0x7c, 0xf2, 0xd9, 0x63, 0x9a, 0xcf, 0xb4, 0x7d, 0xe2, 0x74, 0xd9, 0x35, + 0x85, 0xb9, 0xf5, 0x80, 0x3c, 0xf9, 0x4c, 0x1d, 0xf5, 0xa6, 0x8d, 0x3c, + 0xf0, 0x90, 0xfe, 0x45, 0xe8, 0x0e, 0xd6, 0x45, 0xfa, 0xb1, 0x0c, 0xe6, + 0xf0, 0x24, 0xfc, 0x9f, 0x46, 0x7c, 0x37, 0xe3, 0x7b, 0x42, 0x7e, 0x75, + 0x30, 0xaa, 0xc7, 0x3d, 0x82, 0x71, 0x1c, 0x38, 0x82, 0x31, 0x39, 0xc6, + 0x76, 0x76, 0xcf, 0xb8, 0x52, 0x73, 0x86, 0x7c, 0xc7, 0x33, 0x86, 0x41, + 0xb0, 0xb7, 0x8b, 0x74, 0x9b, 0xf4, 0xfa, 0xf5, 0xf9, 0xb7, 0xcd, 0xf1, + 0x08, 0x70, 0x72, 0x00, 0xf3, 0x31, 0x52, 0xf4, 0xbd, 0xac, 0xe3, 0xc7, + 0x31, 0x4e, 0xd8, 0x80, 0xed, 0xb0, 0x05, 0xdb, 0x61, 0x07, 0xb6, 0xc3, + 0x0e, 0x5c, 0x2d, 0xa7, 0xb6, 0x72, 0x7f, 0x49, 0xfe, 0x9d, 0xbc, 0x77, + 0xf9, 0x1b, 0x3a, 0x36, 0x5f, 0x7b, 0x4b, 0x1f, 0x7c, 0x76, 0xf1, 0x92, + 0x03, 0xdc, 0x63, 0x3f, 0xeb, 0xd5, 0xde, 0xd2, 0x2f, 0xed, 0x3d, 0xc8, + 0xef, 0xb9, 0x24, 0x1d, 0xb7, 0x7c, 0xd8, 0xa9, 0x1d, 0xe8, 0x03, 0x1e, + 0x33, 0x4e, 0x32, 0x3e, 0xe4, 0x30, 0x4e, 0x91, 0xdd, 0x1c, 0xd1, 0x67, + 0xc4, 0xa6, 0x19, 0x8b, 0xb8, 0xa5, 0x3d, 0xb2, 0x25, 0xb1, 0xdb, 0x49, + 0x0e, 0xa8, 0x48, 0x72, 0xa0, 0xcf, 0x09, 0xcb, 0xf1, 0x0e, 0x6a, 0xc8, + 0x19, 0xc0, 0x7a, 0xa0, 0xf4, 0x75, 0xd0, 0xd3, 0x79, 0x29, 0x1c, 0x6f, + 0x90, 0xa9, 0x62, 0xbb, 0x97, 0x55, 0x31, 0xe1, 0xbe, 0x12, 0x75, 0x0a, + 0x44, 0x7f, 0x26, 0x2a, 0x13, 0xa3, 0x1b, 0x45, 0x69, 0xdb, 0xbd, 0x45, + 0xb2, 0x63, 0xa3, 0x72, 0xbe, 0x5b, 0x9a, 0x14, 0xda, 0xe7, 0xdd, 0xde, + 0xea, 0x14, 0xd7, 0x11, 0x43, 0x5e, 0x58, 0x4f, 0x3e, 0x19, 0x05, 0x0e, + 0x41, 0xb7, 0x8c, 0xeb, 0xd6, 0x09, 0xe5, 0xde, 0xed, 0x3a, 0x66, 0xca, + 0x38, 0x6d, 0xf5, 0x7a, 0x03, 0xf9, 0x23, 0xba, 0x2c, 0x7f, 0x4c, 0x96, + 0xb8, 0x36, 0x23, 0x79, 0x97, 0x71, 0x61, 0x1f, 0xbf, 0xc7, 0x59, 0xb6, + 0x4e, 0x46, 0xba, 0xf3, 0x76, 0x8f, 0xc7, 0x37, 0xc1, 0x07, 0x1c, 0x9f, + 0x5e, 0x27, 0x01, 0xaf, 0x2f, 0x5e, 0xcf, 0x88, 0x56, 0xc9, 0x03, 0x47, + 0x66, 0x46, 0xc3, 0xf5, 0x0f, 0xb6, 0x87, 0xef, 0x71, 0x23, 0x6f, 0xb3, + 0x4b, 0xea, 0x11, 0x2e, 0xae, 0x55, 0x2e, 0x94, 0xb1, 0x4a, 0x9f, 0x13, + 0xf6, 0xb4, 0x7c, 0x3d, 0x5d, 0x31, 0xb2, 0x75, 0xbc, 0x12, 0xea, 0x96, + 0xa8, 0xd1, 0xa5, 0x4b, 0xf4, 0x89, 0x89, 0x60, 0xce, 0xeb, 0x93, 0x4b, + 0x3a, 0x46, 0xf7, 0x6b, 0x53, 0x2d, 0xe2, 0x1e, 0x93, 0xd9, 0x11, 0xff, + 0x54, 0x2b, 0xf7, 0x69, 0x8c, 0xa4, 0xde, 0x8c, 0x7e, 0x8c, 0xb5, 0x50, + 0x1f, 0x0e, 0xa9, 0xb5, 0x78, 0xaf, 0xd1, 0xf4, 0x07, 0x9e, 0xc2, 0xb7, + 0xf1, 0x13, 0xbe, 0x0c, 0x3f, 0xe1, 0x09, 0xe8, 0xba, 0x73, 0xf0, 0x13, + 0x1e, 0x87, 0x9f, 0xf0, 0x18, 0xfc, 0x84, 0x47, 0xa1, 0x27, 0xab, 0xfd, + 0x83, 0xe1, 0x05, 0xfe, 0x41, 0xa0, 0xf9, 0x9f, 0x31, 0xc0, 0xc7, 0xab, + 0x7c, 0x83, 0xbd, 0x46, 0x5f, 0xc1, 0xef, 0x37, 0x7c, 0xd4, 0xa6, 0x6e, + 0xd6, 0xfa, 0xd1, 0xec, 0xd9, 0x1d, 0x98, 0xd3, 0x57, 0x6d, 0xca, 0xe8, + 0xab, 0x89, 0x79, 0x7d, 0x65, 0xf8, 0xe8, 0xd8, 0xa8, 0x44, 0xfc, 0xd1, + 0xe9, 0x6c, 0x6a, 0xbb, 0xe6, 0xa1, 0x26, 0x7f, 0xa3, 0x44, 0x1e, 0x50, + 0xcd, 0x35, 0x92, 0xb5, 0xdf, 0xa0, 0xaf, 0xa3, 0x5f, 0x47, 0x5b, 0xef, + 0x94, 0x9c, 0xb6, 0xcf, 0xae, 0x8c, 0xef, 0x47, 0x17, 0xe1, 0xbb, 0x50, + 0x7a, 0x56, 0xe3, 0xfc, 0x7e, 0x7d, 0x26, 0xbf, 0x41, 0x86, 0xcb, 0x21, + 0xce, 0x79, 0x06, 0x8e, 0xfb, 0x30, 0x5a, 0x25, 0x72, 0xac, 0x45, 0xfa, + 0x53, 0xa2, 0x72, 0xa9, 0x95, 0x7a, 0xff, 0xca, 0xa9, 0x6e, 0x89, 0xe7, + 0xba, 0x49, 0xab, 0xf7, 0xc9, 0x84, 0x9e, 0x8b, 0x16, 0xa9, 0x39, 0x46, + 0x1b, 0x25, 0x5c, 0xc3, 0xbb, 0xbd, 0xc5, 0xde, 0x41, 0x1d, 0x35, 0xe5, + 0x44, 0x0e, 0xea, 0xf9, 0x9a, 0xd5, 0x7b, 0x0c, 0x6f, 0x9e, 0x62, 0x2c, + 0x9e, 0xf7, 0xfd, 0x31, 0x0e, 0xff, 0xaf, 0x99, 0xbf, 0x42, 0x8b, 0xb1, + 0x67, 0xd6, 0x58, 0x3b, 0xc6, 0xc4, 0xa9, 0x96, 0xb7, 0x61, 0xd8, 0x4e, + 0xf5, 0x1d, 0xb5, 0xab, 0xe0, 0x03, 0x37, 0xa0, 0x4d, 0xae, 0x63, 0xdb, + 0xbf, 0x17, 0xe4, 0xfd, 0xb3, 0x73, 0xc0, 0x5f, 0x85, 0xb4, 0x06, 0xe4, + 0x31, 0x66, 0xf3, 0x85, 0x16, 0xc6, 0x65, 0xb3, 0x7e, 0xa3, 0x4d, 0x5b, + 0xe5, 0x8c, 0x8c, 0xb6, 0xc3, 0x37, 0xe7, 0x39, 0x76, 0xe6, 0xf7, 0x73, + 0xee, 0x84, 0x7f, 0xab, 0x69, 0x12, 0xf2, 0x67, 0x8f, 0x5c, 0x6b, 0xe3, + 0xce, 0xd4, 0xc3, 0xbf, 0xb8, 0x60, 0xbd, 0xf6, 0x10, 0xf4, 0xd8, 0xad, + 0x90, 0x47, 0xd4, 0xc3, 0x87, 0xe4, 0x17, 0x2c, 0x3d, 0x2f, 0xd4, 0xc3, + 0x17, 0x85, 0xb1, 0xe1, 0x2e, 0xe4, 0xe5, 0x83, 0x28, 0xe8, 0xe1, 0x70, + 0x95, 0xaf, 0x46, 0xbf, 0xaf, 0x2e, 0x6d, 0xd6, 0xc0, 0x16, 0xfa, 0x7d, + 0x90, 0x03, 0xb1, 0xd0, 0xcf, 0xab, 0x9d, 0x5b, 0xa3, 0xdd, 0x69, 0xeb, + 0x8e, 0xa4, 0x5e, 0x22, 0x8e, 0x12, 0x87, 0xe4, 0xf6, 0xf5, 0xbc, 0x26, + 0xcf, 0xf5, 0xbf, 0xa5, 0x71, 0x26, 0x8a, 0xb4, 0xb7, 0x46, 0xc3, 0x68, + 0xe5, 0x7c, 0x22, 0xdc, 0xbf, 0x51, 0xb0, 0x75, 0xf7, 0xd8, 0xf5, 0xf8, + 0x82, 0x7c, 0x9b, 0x71, 0xce, 0x44, 0x5f, 0x64, 0x25, 0xcf, 0x64, 0xa3, + 0xee, 0xed, 0xda, 0x6f, 0xcf, 0x48, 0xd8, 0x16, 0xbf, 0x6b, 0xaa, 0xda, + 0xa6, 0x1d, 0xc5, 0xf7, 0xe2, 0xfb, 0x1b, 0x9e, 0xd7, 0x6b, 0x8b, 0xe6, + 0x6e, 0x9a, 0x90, 0x4f, 0xc8, 0x3b, 0x09, 0x7d, 0x8e, 0xc9, 0x3f, 0x46, + 0xbb, 0x87, 0xeb, 0xae, 0xde, 0xf4, 0x70, 0xea, 0x23, 0xfa, 0x0e, 0xd5, + 0x71, 0x11, 0xa7, 0x90, 0xda, 0xab, 0xf7, 0x9d, 0x14, 0x74, 0x7c, 0x39, + 0x8f, 0xf7, 0xbc, 0x8f, 0xda, 0x76, 0x8c, 0x7f, 0x0b, 0x88, 0x69, 0x1f, + 0x04, 0x6c, 0xd4, 0x21, 0x94, 0xbd, 0x31, 0x69, 0x3b, 0xfa, 0x7e, 0xcd, + 0x0b, 0x6b, 0xe1, 0x0b, 0xf4, 0x1e, 0x85, 0xae, 0x3e, 0x1a, 0x97, 0xfe, + 0xa3, 0x5a, 0x37, 0x66, 0x96, 0xc6, 0x0a, 0xb6, 0x78, 0x2e, 0xfd, 0x89, + 0x98, 0x27, 0xd7, 0x1c, 0x8d, 0xc8, 0xe1, 0xd8, 0x16, 0xaf, 0xc3, 0xb9, + 0xd1, 0xea, 0x42, 0x43, 0x7f, 0xa0, 0x15, 0xd4, 0x37, 0xeb, 0x90, 0xbd, + 0xf3, 0xb1, 0x6b, 0xd4, 0x7f, 0x49, 0x46, 0xc8, 0x4b, 0x95, 0x88, 0x8c, + 0x0f, 0xb6, 0x02, 0x9e, 0xb7, 0xae, 0x07, 0x0e, 0x40, 0x53, 0x98, 0x1f, + 0xfd, 0xf7, 0x3c, 0xdc, 0x38, 0xe5, 0x57, 0x1b, 0xfa, 0xef, 0x3b, 0x4a, + 0x1d, 0xe6, 0x6b, 0xbe, 0x46, 0xbf, 0x5e, 0x8d, 0xf6, 0x3d, 0xc8, 0x8b, + 0x6f, 0x11, 0xff, 0x01, 0xc8, 0xb5, 0xa3, 0x51, 0xe9, 0x38, 0xda, 0x20, + 0x9b, 0x8e, 0xd2, 0xf7, 0xa8, 0xf6, 0x45, 0x69, 0x8b, 0x5e, 0xc2, 0xb8, + 0x6e, 0x34, 0xf7, 0x0d, 0x4e, 0x45, 0x65, 0x1f, 0xf9, 0x15, 0x65, 0x73, + 0xb0, 0x93, 0xb3, 0x47, 0x3d, 0xbd, 0x16, 0x9a, 0xc5, 0x38, 0xf9, 0x37, + 0x2c, 0xfa, 0x8e, 0x1a, 0x39, 0x53, 0xa0, 0x6f, 0x32, 0xd0, 0x02, 0xbc, + 0x3e, 0x60, 0xf9, 0xe5, 0x3d, 0xeb, 0x2d, 0x5f, 0xfe, 0x9c, 0xfc, 0x96, + 0x5b, 0x6f, 0xe4, 0xe5, 0x87, 0xd6, 0x73, 0x2f, 0xd2, 0x5a, 0x9f, 0xef, + 0x3a, 0x6d, 0x43, 0x18, 0xb9, 0xf9, 0x7a, 0xfc, 0x27, 0xc0, 0x51, 0xb8, + 0xfe, 0x44, 0x3e, 0xe4, 0x1a, 0xb2, 0x3e, 0xb3, 0x92, 0x9a, 0xd1, 0x7f, + 0x53, 0x89, 0x6b, 0x61, 0xf3, 0xf7, 0x59, 0x6d, 0xaf, 0x30, 0x36, 0xfe, + 0x4c, 0xf8, 0x37, 0x9c, 0xaa, 0xf6, 0x19, 0x56, 0xaf, 0x75, 0x31, 0xbe, + 0x34, 0xb7, 0x17, 0x28, 0x18, 0xd5, 0x77, 0xc2, 0xc5, 0x9c, 0x8b, 0xc5, + 0x5a, 0xe7, 0x9b, 0x63, 0x12, 0xb8, 0x7e, 0xdc, 0xf9, 0x96, 0xcf, 0xb5, + 0x71, 0xcf, 0x79, 0xb9, 0xe8, 0x83, 0xf7, 0xfe, 0x02, 0xe3, 0x68, 0x75, + 0x5e, 0xc1, 0x9c, 0x1e, 0x2c, 0x65, 0x92, 0x9e, 0x8d, 0x83, 0x3f, 0x5b, + 0x6c, 0x75, 0x9e, 0x9b, 0x8f, 0x21, 0xf5, 0x84, 0x74, 0x71, 0x88, 0x79, + 0x65, 0xe4, 0x95, 0x19, 0xeb, 0xad, 0x77, 0x26, 0xc7, 0xec, 0x7e, 0x12, + 0xa3, 0x8b, 0xe6, 0xd6, 0x5f, 0x06, 0xf4, 0xfa, 0x84, 0xeb, 0x4c, 0x4e, + 0x4d, 0xaf, 0x37, 0xfb, 0x8a, 0x6a, 0x91, 0x67, 0xf6, 0x58, 0x4e, 0x4c, + 0xd5, 0xa2, 0x4c, 0xbd, 0x33, 0xa1, 0x63, 0x5e, 0xda, 0xf6, 0x70, 0xc6, + 0xa7, 0xea, 0x9d, 0x29, 0xbd, 0xd6, 0x1c, 0x75, 0x4e, 0x8e, 0xb1, 0xed, + 0x28, 0xca, 0x88, 0x73, 0x0a, 0xed, 0x4d, 0x8d, 0xb5, 0xc7, 0xf7, 0x49, + 0x3b, 0x6c, 0x01, 0xfe, 0x8d, 0x34, 0xde, 0x17, 0xe0, 0x3a, 0x53, 0x73, + 0xed, 0x2a, 0xb4, 0xc3, 0xb2, 0xa4, 0x41, 0xf6, 0xeb, 0xa2, 0xfd, 0xa5, + 0x6b, 0x52, 0x4b, 0x71, 0x32, 0x06, 0x9c, 0x1c, 0xb4, 0x38, 0x39, 0x61, + 0x71, 0x32, 0x5a, 0x85, 0x93, 0x87, 0x17, 0xe1, 0xe4, 0x04, 0x70, 0xf2, + 0xf0, 0x15, 0x70, 0x82, 0xbc, 0xf2, 0xc3, 0x16, 0x27, 0xf7, 0x2d, 0xc2, + 0x49, 0x7e, 0x2e, 0x16, 0x6f, 0x70, 0x32, 0x02, 0x9c, 0xd4, 0xb4, 0x1a, + 0xd8, 0x0f, 0x5a, 0x9c, 0xe0, 0x3d, 0x75, 0x10, 0x65, 0xee, 0xab, 0xc2, + 0xc9, 0x41, 0xe0, 0xe4, 0x3e, 0x8b, 0x93, 0xc3, 0x16, 0x27, 0x87, 0x51, + 0x26, 0x0f, 0x9c, 0x14, 0x96, 0xc1, 0xc9, 0x08, 0x70, 0x12, 0xb6, 0x5b, + 0x40, 0x3b, 0x87, 0xab, 0x70, 0x32, 0xb2, 0x0c, 0x4e, 0xb8, 0xe6, 0x1a, + 0xee, 0xe1, 0xbe, 0xfc, 0x06, 0x7b, 0xb8, 0x53, 0x9f, 0x7d, 0xe3, 0x3d, + 0xdc, 0x2c, 0x73, 0xb9, 0xea, 0xcc, 0xfb, 0xb3, 0x76, 0x4f, 0x9a, 0xd9, + 0xfb, 0x37, 0x7f, 0x0f, 0x5e, 0x3b, 0xf8, 0xbc, 0x90, 0xf7, 0xc4, 0xec, + 0x21, 0x75, 0xb7, 0x4d, 0x81, 0xd7, 0x8e, 0xca, 0x81, 0xe3, 0xb5, 0x87, + 0x73, 0x36, 0xcd, 0xdf, 0xd6, 0x9e, 0x57, 0x8a, 0x79, 0xe1, 0xde, 0x83, + 0x17, 0xcd, 0x5d, 0x50, 0x31, 0x9e, 0xc7, 0xa8, 0x5e, 0x7b, 0x7e, 0xd1, + 0xde, 0x55, 0xe4, 0xdd, 0x9b, 0xf5, 0xa7, 0x13, 0xdc, 0x57, 0x55, 0xd0, + 0xf0, 0x72, 0x2d, 0xad, 0x47, 0xef, 0xa5, 0xca, 0x16, 0x69, 0x67, 0x27, + 0xb8, 0x27, 0x0d, 0xf6, 0x31, 0xf7, 0xed, 0x9a, 0x7d, 0xba, 0xbd, 0x0b, + 0xf6, 0xe9, 0x56, 0x9f, 0xef, 0x26, 0xdf, 0xcd, 0xd3, 0xcd, 0xc1, 0xb9, + 0xbb, 0x57, 0x8f, 0x3b, 0xcf, 0xe8, 0xf8, 0x70, 0x3d, 0xe6, 0x27, 0x08, + 0x4e, 0xa7, 0x4c, 0x5c, 0x76, 0x46, 0xc7, 0x65, 0x05, 0x1e, 0xf8, 0xb0, + 0x8d, 0xcd, 0x76, 0xf4, 0x5c, 0x9e, 0x8b, 0xcb, 0x2e, 0xd8, 0xa3, 0xa3, + 0xef, 0xff, 0xc8, 0x8e, 0x5e, 0xd2, 0x7b, 0x71, 0xfa, 0x52, 0x8e, 0x14, + 0x20, 0x23, 0xf6, 0x8c, 0xbf, 0x2a, 0xc3, 0x0f, 0xf2, 0x9b, 0x3a, 0x2d, + 0x02, 0xbd, 0x45, 0xb9, 0x9d, 0x97, 0x6c, 0x0f, 0xd3, 0x4c, 0x9d, 0x3e, + 0xed, 0x23, 0x1f, 0x77, 0x7a, 0xe7, 0xfa, 0x27, 0x7e, 0xc3, 0x35, 0x70, + 0xfe, 0xa6, 0x9d, 0x93, 0x71, 0xb2, 0x15, 0xe6, 0x87, 0x6b, 0xe1, 0x77, + 0xdb, 0xfb, 0x08, 0x99, 0x5f, 0x7d, 0xff, 0xb5, 0xe1, 0xd3, 0xac, 0xfe, + 0x3b, 0x22, 0x23, 0x4e, 0x1f, 0xea, 0x4c, 0x7b, 0x0d, 0x03, 0x2a, 0x7d, + 0xd3, 0x00, 0xcf, 0xca, 0x4d, 0x2c, 0xf9, 0xfb, 0x01, 0xf3, 0xba, 0xb0, + 0xa0, 0xe7, 0x94, 0xfb, 0xb0, 0xa6, 0x41, 0x8b, 0x9a, 0xb6, 0x34, 0xfd, + 0x1f, 0x98, 0xd3, 0x91, 0xd4, 0xad, 0xd4, 0x93, 0xa1, 0x8e, 0x4c, 0xc6, + 0xfb, 0x78, 0x7f, 0x84, 0xa6, 0x71, 0x7b, 0x97, 0xc4, 0xd4, 0x39, 0xad, + 0xdf, 0x47, 0x52, 0xbc, 0x5f, 0x66, 0x99, 0xb2, 0xa3, 0x55, 0x65, 0xf5, + 0xb8, 0x3d, 0xf9, 0x43, 0xcc, 0xcd, 0x17, 0x61, 0x6f, 0xf6, 0x8e, 0xbd, + 0x0a, 0x9f, 0x31, 0x2e, 0x5f, 0x2a, 0xbd, 0x04, 0x7a, 0xcd, 0xaf, 0xb5, + 0x77, 0xe1, 0x65, 0x01, 0x37, 0xcf, 0x38, 0xeb, 0xfd, 0xc3, 0x91, 0x3f, + 0x02, 0x5d, 0xfc, 0xc1, 0x4b, 0xec, 0x03, 0xb0, 0x44, 0x60, 0xcf, 0xc3, + 0x36, 0x18, 0x7f, 0x49, 0xef, 0x95, 0xbb, 0xbe, 0xfc, 0x92, 0x8e, 0x53, + 0xf4, 0x97, 0x5b, 0x65, 0x7b, 0xb9, 0x41, 0x76, 0x40, 0x2f, 0xec, 0x28, + 0xfb, 0x78, 0xa2, 0x72, 0x63, 0xd9, 0xcc, 0xd3, 0x47, 0xca, 0x9c, 0xef, + 0x6d, 0x32, 0x71, 0xbc, 0x9a, 0x66, 0xa7, 0xed, 0xde, 0x31, 0xd2, 0x0f, + 0x9e, 0x52, 0x32, 0x3f, 0xad, 0xc7, 0xce, 0x5d, 0xac, 0xc9, 0xc3, 0xb3, + 0xc2, 0xbd, 0xf8, 0xfc, 0x1b, 0x74, 0xdf, 0x68, 0xe5, 0x19, 0x77, 0xde, + 0x8f, 0xd8, 0x5f, 0x09, 0xf7, 0x86, 0xbf, 0xfe, 0x19, 0x10, 0xfd, 0x77, + 0x5d, 0xf4, 0xde, 0x70, 0x4d, 0x7b, 0xd2, 0x76, 0x26, 0xa6, 0x75, 0x84, + 0xa1, 0xf1, 0xf9, 0xbf, 0xe7, 0x22, 0xf2, 0x7f, 0x01, 0x95, 0xf6, 0x2d, + 0x58, 0xd0, 0x73, 0x00, 0x00, 0x00 }; +static u32 bnx2_CP_b09FwData[(0x50/4) + 1] = { + 0x00010030, 0x00000030, 0x00000000, 0x00000001, 0x00010fd0, 0x00000fd0, + 0x00001430, 0x0000007f, 0x00030400, 0x00001000, 0x00000030, 0x00000020, + 0x00050200, 0x00001000, 0x00000030, 0x00000010, 0x00010400, 0x00000400, + 0x00001030, 0x00000020, 0x00000000 }; +static u32 bnx2_CP_b09FwRodata[(0x118/4) + 1] = { + 0x080005d8, 0x080007f8, 0x0800073c, 0x08000764, 0x0800078c, 0x080007b4, + 0x08000610, 0x080005fc, 0x08000820, 0x08000820, 0x0800062c, 0x08000648, + 0x08000648, 0x08000820, 0x08000660, 0x08000674, 0x08000820, 0x08000688, + 0x08000820, 0x08000820, 0x0800069c, 0x08000820, 0x08000820, 0x08000820, + 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820, 0x08000820, + 0x08000820, 0x080006b0, 0x08000820, 0x080006c4, 0x080006d8, 0x080006ec, + 0x08000820, 0x08000700, 0x08000714, 0x08000728, 0x08003740, 0x08003758, + 0x08003768, 0x08003778, 0x08003790, 0x080037a8, 0x080037b8, 0x080037c8, + 0x080037e8, 0x080037f8, 0x08003808, 0x08003898, 0x080037d8, 0x08003818, + 0x08003828, 0x08003840, 0x08003860, 0x08003898, 0x08003878, 0x08003878, + 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x080055f0, 0x08005618, + 0x08005618, 0x08005640, 0x08005690, 0x08005660, 0x00000000 }; +static u32 bnx2_CP_b09FwBss[(0x870/4) + 1] = { 0x0 }; +static u32 bnx2_CP_b09FwSbss[(0xe9/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_cp_fw_09 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x0800006c, + + .text_addr = 0x08000000, + .text_len = 0x73cc, + .text_index = 0x0, + .gz_text = bnx2_CP_b09FwText, + .gz_text_len = sizeof(bnx2_CP_b09FwText), + + .data_addr = 0x08007500, + .data_len = 0x50, + .data_index = 0x0, + .data = bnx2_CP_b09FwData, + + .sbss_addr = 0x08007554, + .sbss_len = 0xe9, + .sbss_index = 0x0, + .sbss = bnx2_CP_b09FwSbss, + + .bss_addr = 0x08007640, + .bss_len = 0x870, + .bss_index = 0x0, + .bss = bnx2_CP_b09FwBss, + + .rodata_addr = 0x080073d0, + .rodata_len = 0x118, + .rodata_index = 0x0, + .rodata = bnx2_CP_b09FwRodata, +}; + -- cgit v1.2.3 From 123d19a3fa4a2c94f9154d04e5355304720020fd Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:13:23 -0800 Subject: [BNX2]: New firmware to support 5709 (part 3). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2_fw2.h | 712 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 712 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h index 66ff441bf2d4..abab341546df 100644 --- a/drivers/net/bnx2_fw2.h +++ b/drivers/net/bnx2_fw2.h @@ -2335,3 +2335,715 @@ static struct fw_info bnx2_cp_fw_09 = { .rodata = bnx2_CP_b09FwRodata, }; +static u8 bnx2_RXP_b09FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x19, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xec, 0x5c, 0x6b, 0x6c, + 0x1c, 0xd7, 0x75, 0x3e, 0xf3, 0x20, 0xb5, 0xa2, 0xf8, 0x18, 0x2e, 0x57, + 0xcc, 0x4a, 0x66, 0xec, 0x5d, 0x71, 0x24, 0xb2, 0x16, 0x6b, 0x8c, 0xd8, + 0xad, 0x4d, 0x04, 0x6b, 0x7b, 0x33, 0xbb, 0x92, 0x98, 0x54, 0x85, 0x29, + 0x87, 0x75, 0x0c, 0xc3, 0x75, 0xd9, 0xa5, 0x1a, 0xbb, 0xae, 0x51, 0xc8, + 0x8f, 0xc4, 0x06, 0x6a, 0xd6, 0x9b, 0x25, 0xdd, 0xa8, 0xe9, 0x82, 0x43, + 0x4b, 0xaa, 0xe9, 0x02, 0x69, 0xbb, 0x20, 0xa9, 0xc7, 0x8f, 0x85, 0x56, + 0x76, 0x52, 0xc7, 0xf9, 0xe1, 0x48, 0x50, 0x95, 0x20, 0x28, 0x0c, 0x43, + 0x48, 0x8d, 0xd6, 0x3f, 0xda, 0x40, 0x95, 0x9f, 0x68, 0x92, 0x42, 0x41, + 0x0b, 0xc7, 0x68, 0x6c, 0x4f, 0xbf, 0xef, 0xce, 0x0c, 0xb9, 0xa4, 0x5f, + 0x40, 0x7f, 0xf4, 0x4f, 0xe7, 0x02, 0x8b, 0xb9, 0xf7, 0xce, 0x3d, 0xe7, + 0x9e, 0x7b, 0xde, 0xe7, 0x0e, 0xa5, 0xdf, 0xef, 0x94, 0x0e, 0x09, 0x5b, + 0x17, 0x7e, 0x99, 0xc3, 0x8f, 0x3d, 0x74, 0xc3, 0xd8, 0x0d, 0xa3, 0x22, + 0x7b, 0xf6, 0x18, 0x5b, 0x12, 0x7a, 0x34, 0x1f, 0xb7, 0xb8, 0xc5, 0x2d, + 0x6e, 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, + 0x71, 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, + 0x8b, 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, + 0x5b, 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, + 0xdc, 0xe2, 0x16, 0xb7, 0xb8, 0xc5, 0x2d, 0x6e, 0x71, 0x8b, 0x5b, 0xdc, + 0xe2, 0xf6, 0xff, 0xbd, 0x19, 0x22, 0x16, 0x9f, 0x5d, 0xe1, 0x4f, 0x12, + 0x7a, 0xfe, 0xf2, 0x1f, 0xba, 0xb6, 0x24, 0x8c, 0xfc, 0xcf, 0x66, 0xa6, + 0x6d, 0x91, 0x42, 0x63, 0x77, 0xa6, 0x28, 0xef, 0xfb, 0x95, 0x94, 0x29, + 0x9c, 0xff, 0x6c, 0xfe, 0xbd, 0xbf, 0x7d, 0xf1, 0xa6, 0xec, 0xd5, 0xba, + 0x21, 0x09, 0x2b, 0x3f, 0xb7, 0xc7, 0xda, 0x25, 0x89, 0x01, 0xc0, 0x7c, + 0x6b, 0xe8, 0xc7, 0xdd, 0xd2, 0x2d, 0x6b, 0x78, 0xec, 0x84, 0x5c, 0x36, + 0x5e, 0xd0, 0xdc, 0xa6, 0xef, 0x9f, 0x70, 0x7c, 0xff, 0x87, 0xf8, 0xbd, + 0xe5, 0x60, 0xec, 0x7d, 0xe0, 0x17, 0x4c, 0x43, 0x74, 0xfb, 0x2f, 0x34, + 0x77, 0xb9, 0x43, 0xaa, 0x8b, 0xa6, 0xcc, 0x7a, 0x29, 0x39, 0xe2, 0x55, + 0xb4, 0x52, 0xb3, 0xa6, 0xed, 0x3d, 0x35, 0xaf, 0xed, 0x3b, 0x75, 0x44, + 0xdb, 0x7f, 0x6a, 0x41, 0x73, 0x4f, 0x49, 0x45, 0xdf, 0xd3, 0x29, 0x05, + 0xeb, 0xb4, 0x56, 0x6c, 0xf6, 0x6b, 0xee, 0xe2, 0x7b, 0xbe, 0xeb, 0x64, + 0xad, 0xbb, 0xc4, 0x2c, 0x80, 0x16, 0x71, 0x6b, 0x3e, 0xc6, 0xa6, 0x14, + 0x52, 0xbe, 0xaf, 0xe7, 0xfd, 0x27, 0xdc, 0x9c, 0x6d, 0xe9, 0x5a, 0x4a, + 0xaa, 0xcd, 0x7e, 0xe0, 0xed, 0xd4, 0x8a, 0x8b, 0xa6, 0x56, 0xf2, 0xfc, + 0x73, 0xae, 0x23, 0x03, 0x86, 0xf8, 0xfe, 0x9c, 0xb3, 0x33, 0x7d, 0x48, + 0x4e, 0x02, 0x6f, 0x03, 0xf8, 0xc4, 0xd2, 0xf3, 0xa4, 0x8f, 0x74, 0x92, + 0xe4, 0x8a, 0x56, 0x1c, 0x8a, 0xe8, 0x93, 0x0c, 0xe9, 0x2f, 0xaf, 0xe8, + 0xa0, 0x73, 0x8b, 0x94, 0xeb, 0x96, 0x4c, 0xad, 0x6c, 0x5c, 0x7f, 0xd9, + 0x7f, 0x71, 0x28, 0x25, 0xcf, 0x36, 0xb3, 0x47, 0x2a, 0x92, 0x90, 0x39, + 0x2f, 0x23, 0x7a, 0x5e, 0x0a, 0x6e, 0x6e, 0x40, 0xce, 0x35, 0xd3, 0xf2, + 0x5c, 0xd3, 0x4e, 0x57, 0x65, 0x93, 0x94, 0x53, 0x96, 0x9c, 0x6d, 0xa6, + 0x70, 0x46, 0xff, 0x9c, 0x6e, 0xdb, 0x56, 0x15, 0x6b, 0xab, 0xcd, 0x97, + 0xf8, 0xef, 0x5f, 0xac, 0xe9, 0x9c, 0x82, 0xa9, 0x80, 0xee, 0x70, 0x2d, + 0xcf, 0xa1, 0xd6, 0xaa, 0xb3, 0x04, 0x6b, 0xa5, 0x32, 0x9d, 0xc3, 0x5c, + 0x73, 0x34, 0xe4, 0xef, 0x16, 0x9c, 0x97, 0x4f, 0x4b, 0xaa, 0x9e, 0x01, + 0xde, 0xb0, 0xff, 0xcf, 0xc0, 0x37, 0x80, 0xf3, 0x5e, 0xab, 0x7e, 0xee, + 0xa2, 0xa4, 0x74, 0xd9, 0x99, 0x2e, 0x0b, 0x78, 0xdb, 0xec, 0xc4, 0x98, + 0xf4, 0xf9, 0xfe, 0x7e, 0x47, 0xac, 0xaa, 0xd3, 0x03, 0x98, 0x8c, 0x54, + 0x9d, 0x6e, 0xe0, 0x69, 0x13, 0xcb, 0xe6, 0xb9, 0xb8, 0xd7, 0x66, 0xcc, + 0xfb, 0x5d, 0x46, 0xde, 0xf7, 0xa7, 0x73, 0xd2, 0x1d, 0xcc, 0xed, 0x56, + 0x38, 0xa6, 0x26, 0x34, 0xac, 0xfb, 0x05, 0x69, 0x4e, 0x24, 0xf3, 0xec, + 0xf3, 0x99, 0x13, 0x77, 0xfe, 0xda, 0x90, 0x96, 0x34, 0x68, 0xb9, 0x26, + 0xec, 0x83, 0xff, 0x1e, 0xf8, 0xe0, 0x7c, 0x06, 0x63, 0xed, 0x3a, 0xe0, + 0x19, 0xae, 0x0a, 0xf7, 0xe8, 0x93, 0xa5, 0x94, 0xe8, 0x57, 0x9c, 0xde, + 0x70, 0x5d, 0x37, 0x68, 0x8d, 0xf4, 0xa0, 0x5f, 0xe6, 0x16, 0xc9, 0xeb, + 0x1a, 0x64, 0x83, 0xe7, 0x8d, 0x15, 0xad, 0xd0, 0x3c, 0x82, 0xbe, 0x29, + 0xd3, 0xb6, 0x7f, 0x6e, 0xce, 0x99, 0xd7, 0x8a, 0xa7, 0x4e, 0x6a, 0xa5, + 0x53, 0x2f, 0x68, 0x7b, 0x9b, 0x2f, 0x74, 0x49, 0x47, 0x16, 0xa7, 0x4e, + 0xc8, 0x93, 0x9e, 0x26, 0xa4, 0x73, 0x09, 0xbc, 0x2b, 0x58, 0x15, 0x31, + 0xed, 0x6e, 0x6d, 0x1f, 0xf0, 0xb4, 0xd9, 0x7f, 0xd2, 0x29, 0xdd, 0x86, + 0x6c, 0xb2, 0xa3, 0xb5, 0x29, 0xf9, 0x33, 0xd0, 0x74, 0xc1, 0x49, 0x91, + 0x5f, 0x3d, 0x01, 0x4c, 0x44, 0x07, 0xf5, 0x8a, 0x3a, 0xa5, 0x17, 0x4a, + 0xc7, 0xff, 0xbc, 0xaf, 0x3a, 0xb2, 0x85, 0x6b, 0xa0, 0xff, 0xd6, 0xfd, + 0xd3, 0xb6, 0xdb, 0x6b, 0x4a, 0xc5, 0xd2, 0x25, 0x6b, 0x15, 0xe5, 0x3a, + 0x99, 0x73, 0x44, 0x8a, 0x35, 0xec, 0x69, 0x9b, 0xe0, 0x8d, 0x0d, 0xde, + 0xec, 0x3c, 0x32, 0xa8, 0xff, 0x96, 0x64, 0xfa, 0x2b, 0x9a, 0x19, 0xf2, + 0x71, 0x49, 0x6e, 0x51, 0xf0, 0x7a, 0xde, 0x81, 0x7e, 0x76, 0xb0, 0x8f, + 0x7d, 0x13, 0x6a, 0x5f, 0x23, 0x6f, 0xa7, 0x97, 0x45, 0x34, 0x3d, 0xbf, + 0x1b, 0xf8, 0xa8, 0xb7, 0x5c, 0xf7, 0x04, 0x68, 0x24, 0xed, 0xec, 0xdb, + 0x80, 0x49, 0x88, 0xeb, 0x74, 0xb5, 0xd0, 0x49, 0x79, 0x93, 0xd7, 0xe4, + 0x9d, 0x3a, 0xa7, 0xb6, 0x76, 0xce, 0x5f, 0xf9, 0x9b, 0x46, 0x4d, 0xf9, + 0xa1, 0x3a, 0x2f, 0x6d, 0x8c, 0xeb, 0x52, 0xa1, 0x4e, 0x24, 0xa0, 0x47, + 0xa2, 0x95, 0x1d, 0x6b, 0x15, 0x57, 0x59, 0x44, 0x37, 0xf2, 0x9d, 0x52, + 0x54, 0xf4, 0x8d, 0x61, 0x2f, 0xda, 0x1e, 0x6c, 0xc8, 0xe6, 0x59, 0x38, + 0x97, 0x87, 0x8d, 0x67, 0xd9, 0x97, 0xf2, 0x02, 0xed, 0x9d, 0xb4, 0x9d, + 0xcf, 0xaa, 0x7f, 0x8e, 0x45, 0x5d, 0x3c, 0xd6, 0x03, 0xda, 0x38, 0x86, + 0x1d, 0xda, 0x78, 0x3f, 0xa2, 0x89, 0x3b, 0x36, 0x08, 0xfe, 0x70, 0x9d, + 0x9d, 0x81, 0x9c, 0x0b, 0x2e, 0xf6, 0x74, 0x9d, 0xdf, 0x50, 0x3c, 0xe8, + 0xc5, 0x79, 0x06, 0xe7, 0xc9, 0xaf, 0x0e, 0xe8, 0xb6, 0x26, 0x65, 0x27, + 0x9b, 0xa1, 0xdc, 0x03, 0xda, 0x75, 0xd9, 0x74, 0x63, 0x2b, 0xed, 0x91, + 0xac, 0xa8, 0x87, 0xa6, 0x24, 0x47, 0xb9, 0x96, 0xeb, 0xb8, 0x3e, 0x3b, + 0x26, 0xfa, 0xaf, 0x7c, 0x6b, 0xdd, 0x59, 0x6d, 0xd9, 0x31, 0x0f, 0x1a, + 0x02, 0xde, 0x82, 0x27, 0x9f, 0xb6, 0x96, 0x7c, 0xdd, 0xc8, 0x3f, 0xae, + 0x6d, 0x5d, 0x07, 0x9d, 0xe8, 0x27, 0x0d, 0x27, 0x3a, 0x03, 0x5b, 0x8b, + 0x68, 0x8a, 0x64, 0xa3, 0x85, 0x38, 0x3e, 0xe9, 0x1c, 0x5c, 0x0f, 0x1f, + 0xe0, 0xc1, 0x07, 0xc0, 0xaf, 0x3d, 0xeb, 0xc1, 0xfe, 0x3d, 0xfa, 0x8c, + 0x8c, 0xbc, 0x38, 0x04, 0x1f, 0xb7, 0xe6, 0x63, 0xd0, 0xc6, 0xd1, 0xd7, + 0xc5, 0x80, 0x8f, 0x99, 0xad, 0xeb, 0xb0, 0x59, 0xf0, 0x78, 0x85, 0x73, + 0xb0, 0xed, 0x95, 0x12, 0x9e, 0xb6, 0x54, 0x1b, 0xd4, 0xab, 0xc8, 0x97, + 0xd2, 0xe7, 0xa4, 0xe1, 0x5f, 0xe8, 0x77, 0xe8, 0x57, 0xb8, 0xd6, 0xf7, + 0x4b, 0x0e, 0x61, 0x7d, 0x99, 0x70, 0x68, 0x43, 0x9d, 0xa2, 0x27, 0x2b, + 0xda, 0xc1, 0x21, 0xd8, 0xd6, 0xf5, 0x6d, 0xa0, 0x95, 0x36, 0x76, 0x8d, + 0x48, 0x3b, 0xf7, 0xfb, 0x69, 0x57, 0xf0, 0xef, 0xee, 0x36, 0x61, 0x0d, + 0x9f, 0xef, 0x86, 0x63, 0x2d, 0xf4, 0x2d, 0x7c, 0x9f, 0xcd, 0x14, 0xa4, + 0x3f, 0x1c, 0xb3, 0xbf, 0x4a, 0xaf, 0xa3, 0xdf, 0x98, 0x90, 0x1d, 0x27, + 0x03, 0x9f, 0xb8, 0x63, 0xc9, 0x12, 0xfb, 0x64, 0x40, 0xe3, 0x8e, 0x33, + 0x91, 0x6f, 0x7c, 0x1f, 0xf0, 0xa0, 0xcf, 0x5b, 0x8d, 0x03, 0x68, 0x3f, + 0xd3, 0x60, 0x2a, 0x98, 0xdb, 0xc8, 0x0b, 0xfa, 0x63, 0xda, 0x9b, 0xd5, + 0x6a, 0x6f, 0x7b, 0x60, 0x6f, 0x4e, 0xbb, 0x64, 0x9d, 0xbf, 0x87, 0xbd, + 0x7d, 0xc3, 0xd1, 0xc0, 0x1b, 0x91, 0x8b, 0xb5, 0x34, 0x6c, 0xdd, 0x4c, + 0xbf, 0x26, 0x3b, 0x33, 0xb3, 0xa2, 0xc9, 0x09, 0xce, 0x35, 0x30, 0xa7, + 0x7c, 0x71, 0xe0, 0x0b, 0x2e, 0x1b, 0x4f, 0x81, 0x2e, 0xdf, 0x9f, 0x05, + 0xce, 0xf2, 0x88, 0x11, 0xda, 0x56, 0x34, 0x6f, 0xdd, 0xef, 0xda, 0xee, + 0xaf, 0x19, 0x52, 0x19, 0x6e, 0x93, 0xec, 0xf0, 0x12, 0x70, 0x4f, 0x3b, + 0x81, 0x1d, 0x53, 0xd7, 0x97, 0x81, 0x7f, 0xce, 0x1b, 0x82, 0x1e, 0xd3, + 0x0e, 0x40, 0x17, 0xf0, 0x2f, 0x03, 0xff, 0x5c, 0xb3, 0x4d, 0xbe, 0x6e, + 0x46, 0xb1, 0x32, 0x3a, 0x4f, 0x37, 0x96, 0x45, 0xfb, 0x1e, 0x96, 0x2f, + 0x7a, 0x49, 0xcd, 0x3d, 0x46, 0xff, 0x5a, 0x1d, 0x86, 0x9d, 0x68, 0x55, + 0x87, 0x7b, 0x1b, 0xb2, 0xbc, 0xba, 0x46, 0x0a, 0xd5, 0xc0, 0x06, 0x0b, + 0xee, 0x50, 0x25, 0x6d, 0x28, 0x5f, 0x22, 0xb2, 0x0f, 0xb6, 0xb7, 0x6c, + 0x73, 0xcc, 0xf9, 0x60, 0x6e, 0xbc, 0xd6, 0x0f, 0x9f, 0xc8, 0xf1, 0x7b, + 0xfe, 0xb4, 0x13, 0xcc, 0x7d, 0xa1, 0x76, 0x57, 0x37, 0xfd, 0x2e, 0xe2, + 0x44, 0xa6, 0xea, 0xfc, 0xbb, 0x0f, 0xfd, 0x5d, 0x07, 0xf3, 0xd1, 0x78, + 0xb2, 0xe3, 0x81, 0xce, 0x8a, 0xb6, 0xdf, 0xd6, 0xfb, 0xdb, 0x43, 0x1f, + 0xb6, 0x1f, 0x93, 0x7b, 0x6b, 0xd5, 0xbe, 0x76, 0x79, 0xcf, 0x60, 0x1c, + 0xbd, 0x22, 0x62, 0xba, 0xb5, 0x5d, 0xe0, 0x47, 0xb5, 0xb7, 0x65, 0x2e, + 0x51, 0xaa, 0xf9, 0x72, 0xc1, 0x09, 0x60, 0x30, 0xee, 0x2c, 0xd6, 0xf4, + 0xfe, 0x84, 0xac, 0x8e, 0x2d, 0xc2, 0xac, 0xc8, 0xae, 0xe1, 0x65, 0x51, + 0xb0, 0x7d, 0x89, 0x35, 0xd8, 0x54, 0xa9, 0x56, 0xed, 0x6d, 0x19, 0xa7, + 0x8b, 0xc0, 0xa5, 0xef, 0x59, 0x85, 0x1d, 0x58, 0x83, 0xdd, 0x2a, 0x99, + 0x5e, 0xc2, 0xeb, 0xfd, 0x9b, 0xd7, 0x70, 0x67, 0x42, 0x7a, 0xfa, 0x36, + 0xaf, 0xe1, 0xb0, 0x89, 0xb3, 0x65, 0x3c, 0x4c, 0x9c, 0x3b, 0xd6, 0x70, + 0x8e, 0xac, 0xa7, 0xe7, 0xb0, 0xc0, 0x07, 0x25, 0xda, 0xf3, 0xb2, 0xe7, + 0x62, 0x6d, 0x70, 0xe2, 0x8b, 0x82, 0x58, 0x37, 0xb2, 0x29, 0xf4, 0xc9, + 0xe6, 0x1e, 0x17, 0xbc, 0x32, 0x85, 0x3e, 0x4e, 0x93, 0x2a, 0xe4, 0x7c, + 0x7f, 0x43, 0xf6, 0x5c, 0x68, 0x98, 0xa1, 0x2e, 0x51, 0x27, 0xde, 0x86, + 0x8d, 0x75, 0x4e, 0x99, 0x88, 0xc3, 0xe7, 0x94, 0x8d, 0xc9, 0x44, 0xb5, + 0x26, 0x95, 0xed, 0xf9, 0x27, 0x7c, 0xe8, 0xe2, 0x94, 0x05, 0x3f, 0x5a, + 0x94, 0xce, 0x31, 0x37, 0x87, 0xf9, 0x06, 0x6d, 0x0b, 0x7e, 0x05, 0xb0, + 0xd0, 0xb5, 0x84, 0x31, 0xbf, 0xf3, 0x55, 0xd7, 0xe0, 0x3e, 0x19, 0xe4, + 0x4d, 0x89, 0x84, 0x3e, 0x7f, 0xd5, 0xa7, 0x9e, 0x4d, 0x8f, 0x5c, 0x45, + 0x9e, 0x62, 0xc1, 0x57, 0xc2, 0x7f, 0x40, 0xdf, 0x67, 0x9b, 0x82, 0xb8, + 0xfe, 0x40, 0x4f, 0x60, 0x63, 0x47, 0xb7, 0x06, 0x4f, 0x31, 0xe9, 0x9b, + 0xa7, 0x73, 0xcc, 0x01, 0xda, 0x13, 0x6e, 0x6e, 0x7c, 0x9b, 0x71, 0xe6, + 0xc0, 0x36, 0xfd, 0x4c, 0x65, 0x9b, 0x0e, 0x9f, 0x0e, 0x9b, 0xd2, 0xdd, + 0x1c, 0xfa, 0x67, 0x22, 0x1b, 0x4a, 0xc3, 0x86, 0xde, 0x56, 0x39, 0xc8, + 0xb9, 0xe6, 0x29, 0xd8, 0xab, 0xa2, 0x55, 0x26, 0x90, 0x13, 0xe8, 0xa3, + 0xef, 0x43, 0x4f, 0x70, 0x16, 0xf8, 0xc0, 0x02, 0xb8, 0xa4, 0x8f, 0xbe, + 0x11, 0xda, 0x33, 0xfb, 0xef, 0xf8, 0x41, 0x7c, 0xf8, 0x7c, 0xb8, 0xff, + 0x3f, 0x75, 0x07, 0x3e, 0x20, 0xc2, 0x45, 0x3c, 0xc3, 0xda, 0x04, 0xf2, + 0x99, 0x89, 0xa6, 0xa9, 0xd1, 0x9f, 0x17, 0x3d, 0xe6, 0x21, 0xcc, 0x41, + 0x1e, 0x0b, 0xfd, 0x22, 0x73, 0x8f, 0xce, 0x90, 0xa7, 0xb9, 0x28, 0xce, + 0x29, 0x7b, 0x43, 0xcc, 0xc9, 0x94, 0x9d, 0x36, 0xe5, 0x93, 0xa7, 0x73, + 0x9d, 0x58, 0x87, 0xb9, 0x26, 0xce, 0x0d, 0xbf, 0x84, 0x5c, 0x06, 0x6b, + 0xce, 0x63, 0x7d, 0x7b, 0x68, 0xf3, 0x17, 0xa5, 0x0c, 0x9f, 0x6a, 0xda, + 0x7c, 0x9f, 0xeb, 0x91, 0x0e, 0x8c, 0x1b, 0xd8, 0x0b, 0x7e, 0xc2, 0x50, + 0x7c, 0x46, 0x2c, 0x48, 0x5d, 0xc7, 0x1c, 0x09, 0x6b, 0x33, 0x58, 0x4b, + 0xbf, 0xcb, 0xb5, 0xcf, 0x82, 0x0e, 0x8c, 0x1b, 0x84, 0xa1, 0x8f, 0x12, + 0xdf, 0xcd, 0x6d, 0x86, 0x26, 0xf9, 0xe7, 0x0c, 0x3b, 0x5a, 0x1b, 0xe1, + 0xdd, 0xb8, 0x96, 0xf9, 0x09, 0x71, 0xf7, 0x84, 0xf1, 0x7f, 0x5c, 0x0a, + 0xcd, 0x02, 0x7e, 0x22, 0xd3, 0xc7, 0x90, 0x8f, 0xd9, 0x6d, 0x88, 0x55, + 0x9c, 0xdf, 0x6a, 0x05, 0x67, 0x8d, 0xe0, 0xee, 0xef, 0x5b, 0x3f, 0xfe, + 0x42, 0x72, 0xcd, 0x47, 0xd2, 0xc2, 0xa4, 0x80, 0x18, 0x01, 0x5e, 0x65, + 0xa6, 0x98, 0xc3, 0x15, 0x1b, 0x4a, 0xa6, 0x98, 0x1b, 0x83, 0x5f, 0x0c, + 0xf2, 0xa2, 0x73, 0xde, 0x46, 0xd9, 0x59, 0xe0, 0x77, 0x01, 0x3c, 0xce, + 0x40, 0x87, 0xc6, 0x01, 0x2b, 0x87, 0x81, 0x83, 0xf1, 0xd7, 0xd1, 0xf3, + 0x49, 0x29, 0x5b, 0xcc, 0x13, 0xda, 0x49, 0x67, 0x81, 0xf6, 0xaf, 0xe7, + 0x37, 0x63, 0x8e, 0xfd, 0x7b, 0x7b, 0x02, 0x99, 0x75, 0x71, 0x3c, 0xa1, + 0xe7, 0x7b, 0x36, 0xcc, 0x7f, 0xbf, 0x2b, 0xa0, 0x4d, 0x8d, 0x31, 0xff, + 0xf2, 0x86, 0xf1, 0xef, 0x25, 0xd7, 0x8f, 0xef, 0xda, 0x16, 0xea, 0x20, + 0xfa, 0x8f, 0x85, 0xf4, 0x82, 0xb6, 0x55, 0x5a, 0xa3, 0x9c, 0x57, 0x16, + 0x74, 0xe4, 0x7f, 0x6e, 0x6e, 0x27, 0x62, 0x7d, 0x46, 0x4a, 0x4d, 0xd0, + 0xbd, 0x1a, 0xcb, 0x56, 0xd7, 0x54, 0xd6, 0xd6, 0x04, 0xbe, 0xbe, 0xd4, + 0xf4, 0x91, 0x3b, 0xb5, 0xc6, 0xbd, 0x61, 0xf4, 0x2b, 0xd8, 0xa7, 0x20, + 0xd3, 0xde, 0x85, 0x82, 0x6e, 0x1f, 0x09, 0xf2, 0x3e, 0xfb, 0x9b, 0x5a, + 0x69, 0x99, 0xf9, 0x20, 0xec, 0xc9, 0x56, 0xf9, 0x3f, 0xe2, 0xca, 0x51, + 0xad, 0x70, 0xea, 0x38, 0xf2, 0xc1, 0x15, 0xfc, 0x4e, 0xe3, 0xd7, 0xc0, + 0x2f, 0xca, 0xc3, 0x9f, 0x41, 0x1e, 0xaf, 0x7c, 0x2c, 0xe2, 0x41, 0xb0, + 0xff, 0x1b, 0x2b, 0xd0, 0xb3, 0xe3, 0x29, 0xf9, 0x86, 0xad, 0xf7, 0xe9, + 0x81, 0x5f, 0x29, 0x20, 0x8f, 0xb5, 0xde, 0x96, 0xdf, 0x0e, 0xf3, 0x22, + 0x91, 0xd7, 0x16, 0xc0, 0xc7, 0x91, 0xfd, 0xa1, 0xce, 0x16, 0xee, 0x75, + 0x95, 0xff, 0x0c, 0xf3, 0x1e, 0xe4, 0x5f, 0x05, 0xb5, 0xea, 0x5b, 0xe0, + 0x8d, 0x26, 0x6f, 0x41, 0x87, 0x5e, 0x5b, 0xe8, 0x00, 0x3d, 0xb6, 0x94, + 0x27, 0x91, 0x2f, 0x68, 0x83, 0xd6, 0x26, 0xad, 0x03, 0x76, 0x0c, 0x1b, + 0x57, 0x63, 0x49, 0xb4, 0xe5, 0x2f, 0xcd, 0x2c, 0xd5, 0x74, 0xac, 0x45, + 0xee, 0x93, 0x43, 0x1f, 0xb2, 0xbf, 0xb2, 0x40, 0x38, 0x5d, 0x5e, 0x5f, + 0x30, 0xe4, 0x4d, 0xe4, 0x52, 0x6f, 0xd9, 0x97, 0x66, 0x10, 0xb7, 0xfa, + 0x11, 0x23, 0x50, 0x8b, 0xec, 0xa4, 0x9f, 0xde, 0x61, 0xe2, 0x59, 0xc2, + 0x6f, 0x1f, 0x72, 0xc1, 0x8f, 0x86, 0xf9, 0xb8, 0xf5, 0xa4, 0x2d, 0x01, + 0x18, 0xae, 0x37, 0x41, 0x5b, 0x37, 0xe4, 0x9f, 0xb5, 0xa6, 0xe4, 0xf5, + 0x1e, 0x95, 0xaf, 0x68, 0x9c, 0x0f, 0x7c, 0xd3, 0x87, 0xe7, 0xc9, 0x67, + 0x03, 0x3a, 0xce, 0x31, 0xdf, 0xd1, 0x87, 0x12, 0x5f, 0x76, 0xac, 0x80, + 0xc3, 0x5c, 0x59, 0x08, 0xfa, 0xd1, 0x9c, 0x68, 0x51, 0x1c, 0xa3, 0x6f, + 0x2c, 0xc1, 0x4e, 0x38, 0x9e, 0x10, 0x25, 0x83, 0x75, 0xf2, 0x94, 0x84, + 0x99, 0x3f, 0x3b, 0x33, 0x67, 0x53, 0xae, 0xf0, 0x71, 0xb5, 0x48, 0xae, + 0x94, 0x51, 0xbb, 0x54, 0x17, 0xbe, 0x09, 0xb9, 0xea, 0x61, 0xbe, 0x0f, + 0x1b, 0x3f, 0x4e, 0xf9, 0xa2, 0xfe, 0x5b, 0x40, 0xee, 0xb3, 0x20, 0xc9, + 0xa0, 0x5e, 0x39, 0x8a, 0x3c, 0x1f, 0xf2, 0xab, 0x1d, 0x07, 0x0e, 0xd8, + 0x69, 0x6d, 0x05, 0x4f, 0xd4, 0x16, 0xb5, 0xd3, 0x78, 0x0e, 0xe0, 0xd9, + 0xa0, 0x6e, 0x86, 0xb9, 0xc6, 0x87, 0xe8, 0x81, 0x3d, 0x95, 0x68, 0x4f, + 0xf2, 0xfd, 0x66, 0x5e, 0xbe, 0xdb, 0x1c, 0x93, 0xe7, 0x9b, 0x39, 0xf9, + 0xbb, 0xa6, 0x23, 0xdf, 0x69, 0x8e, 0xc8, 0xb7, 0x9b, 0xc3, 0xac, 0xc9, + 0x90, 0x37, 0x65, 0x98, 0x37, 0xc9, 0xbd, 0xde, 0xad, 0xb0, 0x77, 0xca, + 0xff, 0xd2, 0x4c, 0xa1, 0x31, 0x28, 0xe5, 0x63, 0xf0, 0xcf, 0xce, 0xcd, + 0xac, 0x25, 0xe5, 0x11, 0x87, 0x35, 0x41, 0x1b, 0xdf, 0xa3, 0xce, 0x84, + 0xff, 0x86, 0x3f, 0x9b, 0x4a, 0x65, 0x4f, 0xbb, 0x46, 0x47, 0xe8, 0x03, + 0x6e, 0x49, 0x4a, 0x07, 0xf6, 0x82, 0x0f, 0x5c, 0x7a, 0x1a, 0x36, 0xa0, + 0x6a, 0x9a, 0x04, 0xfc, 0x0d, 0x73, 0x01, 0x93, 0x76, 0x8c, 0x3a, 0x30, + 0x9b, 0x71, 0x0d, 0xd6, 0x77, 0xb4, 0x67, 0x03, 0x81, 0x83, 0x70, 0xfb, + 0x2c, 0xca, 0xcd, 0xb4, 0xe9, 0x57, 0x0b, 0xa1, 0x8f, 0x4b, 0x84, 0x7a, + 0x69, 0x61, 0xfe, 0xf1, 0xd0, 0x27, 0x6f, 0xdc, 0x07, 0xf1, 0x02, 0xf9, + 0x64, 0xb0, 0x8e, 0xb0, 0x5a, 0x08, 0xdb, 0x17, 0xce, 0x75, 0x82, 0xdf, + 0x8e, 0x94, 0xbd, 0x37, 0x35, 0xe6, 0xd9, 0xc8, 0x77, 0x30, 0x1e, 0xc1, + 0xf8, 0x4a, 0x38, 0xfe, 0x9c, 0x4c, 0x2f, 0x0a, 0x68, 0xfd, 0x89, 0x56, + 0x54, 0xe3, 0x31, 0x8c, 0x75, 0x8c, 0x0d, 0xd6, 0x02, 0x68, 0x37, 0x27, + 0xa9, 0xeb, 0xba, 0x4d, 0x5f, 0x38, 0x19, 0xfa, 0xc3, 0x82, 0x1c, 0xf6, + 0x06, 0x0b, 0x57, 0x11, 0x33, 0xb4, 0xb6, 0x28, 0xff, 0xd9, 0x0e, 0xbe, + 0xf8, 0xfe, 0xed, 0xac, 0xb9, 0x93, 0xa6, 0x7c, 0x7b, 0x3e, 0x6b, 0x3d, + 0xa4, 0x7f, 0x0d, 0x67, 0xf2, 0xfd, 0x83, 0x76, 0xf6, 0xc8, 0x94, 0xde, + 0x25, 0xdf, 0x3d, 0xca, 0xd8, 0x7b, 0x76, 0xe6, 0x07, 0xd0, 0xbd, 0xfa, + 0x4a, 0xbb, 0xd4, 0xeb, 0xa6, 0x5c, 0x19, 0x1d, 0x04, 0x9d, 0x96, 0xd4, + 0x1b, 0x49, 0xe4, 0x73, 0x9b, 0x65, 0xb6, 0x5f, 0x19, 0x18, 0xfc, 0xf4, + 0xb0, 0xf2, 0xd3, 0xae, 0x8d, 0x67, 0xe3, 0xe7, 0x3d, 0xeb, 0xcf, 0x5c, + 0x02, 0xfd, 0xd0, 0xeb, 0xe4, 0x76, 0x25, 0xe7, 0xb2, 0x37, 0x68, 0x95, + 0x75, 0xc4, 0x2e, 0x73, 0xd0, 0xba, 0x57, 0xff, 0x2f, 0xff, 0xf3, 0x26, + 0x65, 0xf7, 0xaa, 0xaa, 0x61, 0x54, 0xac, 0xc3, 0x7e, 0x4b, 0x2b, 0x2f, + 0x83, 0x16, 0xf8, 0xd8, 0xc6, 0xf6, 0x70, 0x9c, 0x51, 0xbc, 0x38, 0xdb, + 0xe8, 0x90, 0xef, 0xd4, 0xb7, 0xc8, 0x72, 0x9d, 0xef, 0xdb, 0x65, 0xa9, + 0x3e, 0x78, 0xb5, 0x4f, 0xef, 0x97, 0xf3, 0xd7, 0x5c, 0x6f, 0xdd, 0xa3, + 0x23, 0x37, 0x98, 0xfc, 0x40, 0x7e, 0x39, 0xda, 0x23, 0x3f, 0xfe, 0x72, + 0xf6, 0x99, 0x3f, 0xd5, 0x61, 0x03, 0xa3, 0x9d, 0xb4, 0x6d, 0xf4, 0x39, + 0x9f, 0xbd, 0x5a, 0xd0, 0xa9, 0xdb, 0x3f, 0x02, 0x4f, 0xb3, 0x0b, 0x81, + 0x1d, 0x10, 0x37, 0xf1, 0x42, 0x37, 0xec, 0xef, 0x01, 0x27, 0xde, 0x35, + 0x06, 0x81, 0xeb, 0x7b, 0x8a, 0x17, 0xb7, 0x3b, 0xd9, 0xab, 0x08, 0x49, + 0xfe, 0x15, 0x7b, 0x70, 0x78, 0x87, 0xbe, 0x5d, 0xea, 0xe9, 0xeb, 0xad, + 0xe7, 0xe0, 0xff, 0x0b, 0xa9, 0xec, 0x91, 0xcb, 0x72, 0x76, 0xe6, 0xa2, + 0x4d, 0xfd, 0xa7, 0xdf, 0x78, 0x09, 0xb9, 0xa7, 0x25, 0x0b, 0x0d, 0xfa, + 0x4b, 0xe2, 0x62, 0xfe, 0xbf, 0xcb, 0x3a, 0xac, 0x33, 0x4f, 0xc0, 0x3b, + 0xcc, 0x1b, 0xbf, 0x4e, 0x39, 0xb7, 0x11, 0x76, 0xb8, 0xa0, 0xff, 0x62, + 0x03, 0x8f, 0x06, 0xad, 0xbd, 0x3a, 0xf7, 0xfb, 0x37, 0xec, 0xfb, 0x0e, + 0x68, 0x1d, 0x04, 0x2c, 0x62, 0x66, 0xba, 0x75, 0x8f, 0x57, 0xd4, 0x1e, + 0xc7, 0x1a, 0xc8, 0xf5, 0x56, 0xf7, 0xc0, 0x5c, 0x43, 0xc7, 0x39, 0x4d, + 0x25, 0x97, 0x2b, 0xa3, 0xe4, 0xef, 0x9e, 0x5e, 0xe6, 0x99, 0x46, 0xfe, + 0xaf, 0xfd, 0xa8, 0x7e, 0x7c, 0x7e, 0x7e, 0x12, 0xfe, 0xd9, 0xf7, 0x2f, + 0xec, 0x1a, 0x04, 0x0d, 0xa8, 0x43, 0xd3, 0xe4, 0xf9, 0xd9, 0x19, 0x17, + 0x38, 0x8a, 0x0a, 0xf7, 0x25, 0x59, 0x01, 0xee, 0x09, 0xf2, 0x01, 0xb8, + 0xe7, 0x38, 0xaf, 0x64, 0x80, 0xf9, 0x46, 0x06, 0x78, 0x23, 0xfd, 0x4c, + 0x42, 0xd7, 0x76, 0x5b, 0xb7, 0x07, 0xba, 0x9e, 0x60, 0x6c, 0x7b, 0x0e, + 0xba, 0x57, 0x48, 0x52, 0x7f, 0xda, 0x7b, 0xd7, 0xf4, 0xa7, 0x15, 0x7f, + 0xbb, 0x94, 0x16, 0x12, 0xc0, 0x6b, 0xca, 0x5c, 0x8e, 0x78, 0x31, 0xae, + 0x53, 0xf7, 0x2b, 0xa1, 0xee, 0x77, 0x86, 0xb8, 0x17, 0xc1, 0x93, 0x6c, + 0xa6, 0xae, 0xb3, 0x8e, 0xda, 0xa6, 0x6a, 0x5b, 0x03, 0x36, 0x5d, 0xae, + 0xb1, 0x0e, 0xe5, 0xfd, 0xc8, 0xa5, 0x99, 0x69, 0xd4, 0xaa, 0xe5, 0xda, + 0x88, 0x56, 0x6e, 0xda, 0x5a, 0xd9, 0xa3, 0xbe, 0xed, 0xb2, 0x2e, 0x28, + 0x1e, 0xa7, 0x65, 0xa9, 0xf9, 0x4b, 0xbf, 0xba, 0x6b, 0x13, 0xfa, 0xd0, + 0xfd, 0x09, 0xca, 0xf7, 0xb3, 0xa4, 0x0b, 0x41, 0x9c, 0xfc, 0x4e, 0xc9, + 0xc9, 0x21, 0x14, 0xbd, 0xc8, 0xad, 0x4e, 0x0d, 0x11, 0x3f, 0xe8, 0x48, + 0xa5, 0x64, 0xd9, 0xe3, 0x1e, 0x67, 0x67, 0xc8, 0xcb, 0xf2, 0x71, 0x4b, + 0x0e, 0x2b, 0xf9, 0xbd, 0xac, 0x6c, 0xbb, 0xbc, 0x62, 0xc8, 0x74, 0x72, + 0xd0, 0x7a, 0x58, 0xb2, 0x57, 0x2f, 0x18, 0xd9, 0x67, 0xa6, 0x60, 0xd7, + 0x4b, 0x8b, 0x86, 0xb8, 0xaa, 0xde, 0xa2, 0x8c, 0xb2, 0x0b, 0xb0, 0xfc, + 0xf0, 0xec, 0x7b, 0x5b, 0xce, 0xde, 0x2d, 0x2b, 0x4f, 0xff, 0x26, 0x7c, + 0xce, 0x01, 0xc8, 0xc2, 0xcc, 0x1c, 0x42, 0x5e, 0xf1, 0xb4, 0x0c, 0x5a, + 0x55, 0xe4, 0xc9, 0xe0, 0x3b, 0xda, 0x01, 0x65, 0x03, 0x17, 0x74, 0x8c, + 0x07, 0xc8, 0x27, 0x8e, 0xaf, 0x95, 0x0b, 0xca, 0x96, 0xd2, 0xea, 0xdd, + 0x0e, 0xe0, 0x08, 0xde, 0x71, 0xfc, 0x19, 0xd9, 0xa1, 0xde, 0xdd, 0xa9, + 0xde, 0x55, 0xe9, 0x2b, 0x94, 0xfc, 0xbe, 0x82, 0x3d, 0xc9, 0xe3, 0x68, + 0xbe, 0x4b, 0x02, 0x5b, 0x8a, 0xf8, 0x6e, 0xc9, 0xc1, 0x46, 0x4a, 0xbe, + 0x84, 0xfa, 0xe7, 0x8e, 0xc6, 0x80, 0x94, 0x20, 0xc7, 0xe9, 0xdc, 0x83, + 0xbd, 0x3c, 0x5b, 0x71, 0x25, 0xfb, 0x8c, 0xe8, 0xa4, 0xf5, 0x4e, 0x39, + 0xe4, 0x45, 0xf4, 0x74, 0x86, 0xf4, 0x4d, 0x86, 0xe3, 0x44, 0x48, 0x43, + 0x2b, 0xbe, 0x4e, 0xe0, 0x42, 0xac, 0xcf, 0x79, 0x21, 0x1e, 0xfa, 0x11, + 0xd0, 0x3a, 0x99, 0x96, 0x15, 0x8f, 0x74, 0x6c, 0x91, 0x6a, 0x8a, 0xfd, + 0x03, 0xd0, 0x37, 0xe2, 0xd9, 0xc4, 0x7c, 0x66, 0x1d, 0x8f, 0x1f, 0x6c, + 0x54, 0xc0, 0x63, 0xf2, 0x97, 0xeb, 0x10, 0x23, 0x3e, 0x47, 0xf9, 0xed, + 0x46, 0x2e, 0x6f, 0x07, 0xba, 0x69, 0xad, 0xed, 0x59, 0x3a, 0xde, 0x0d, + 0x59, 0x71, 0xdf, 0x0e, 0x99, 0x84, 0xdd, 0x17, 0xeb, 0xdc, 0x7f, 0x12, + 0x7a, 0x74, 0x51, 0xed, 0x5f, 0x5a, 0xe9, 0x0f, 0xe1, 0x09, 0xdb, 0xbd, + 0x01, 0xb6, 0x5d, 0xf6, 0x2e, 0x58, 0x1f, 0x01, 0xff, 0xbb, 0x80, 0xd7, + 0xe5, 0x44, 0x8e, 0xf0, 0xc4, 0x83, 0x75, 0xf5, 0xd4, 0x27, 0xe0, 0x49, + 0xaa, 0xba, 0xbe, 0x58, 0x6f, 0x97, 0xe2, 0x42, 0x84, 0x8b, 0x78, 0x3e, + 0x40, 0xdd, 0x7b, 0xb7, 0xc2, 0x35, 0xad, 0x70, 0xe1, 0x7d, 0x9d, 0x3e, + 0xe7, 0x26, 0xc0, 0xa3, 0x76, 0xb7, 0x41, 0x5b, 0xb2, 0x4b, 0xaa, 0xaa, + 0x76, 0xef, 0x50, 0xbe, 0xa6, 0x9a, 0xdc, 0x8c, 0xf7, 0x3e, 0xf6, 0xdc, + 0x8d, 0x7c, 0xa6, 0x1b, 0x73, 0x99, 0x0d, 0x73, 0x1b, 0xe9, 0x4f, 0x6c, + 0xa0, 0xff, 0xbf, 0x7b, 0x19, 0x52, 0xe6, 0x72, 0xc1, 0xba, 0x12, 0xd6, + 0xcd, 0x1e, 0x87, 0x4d, 0x30, 0x4f, 0x4f, 0x31, 0x36, 0x5f, 0xa3, 0x68, + 0x99, 0x5d, 0xf9, 0x29, 0xd6, 0xf5, 0x03, 0x36, 0x1a, 0x07, 0x7c, 0x78, + 0x0a, 0x78, 0x8e, 0xd7, 0xd5, 0x1d, 0x05, 0x64, 0xf0, 0xbe, 0x3a, 0x7b, + 0xb5, 0xfe, 0x69, 0x3c, 0xbb, 0xa6, 0x85, 0x5f, 0xe4, 0x15, 0xe9, 0x25, + 0xad, 0xbc, 0x2f, 0x82, 0xbd, 0x39, 0xd0, 0xe3, 0xa4, 0x21, 0xa5, 0x1c, + 0xe2, 0xba, 0xc7, 0xbb, 0x57, 0xda, 0xe5, 0x40, 0x50, 0x23, 0xd8, 0x8c, + 0xef, 0xa6, 0x3a, 0xfb, 0xa1, 0x15, 0xde, 0xbf, 0x66, 0x78, 0x47, 0x37, + 0x8c, 0xda, 0x5b, 0x1e, 0x5a, 0xb1, 0xe5, 0x6b, 0x8d, 0x61, 0x79, 0xb8, + 0x91, 0xb5, 0xee, 0x81, 0x0f, 0x28, 0xaf, 0xde, 0xcb, 0x6e, 0x4b, 0xd2, + 0x7f, 0x99, 0xc8, 0x3d, 0xdb, 0xec, 0x20, 0x17, 0xa9, 0xb2, 0x36, 0x3b, + 0x9e, 0xe5, 0x7d, 0x8d, 0x55, 0x97, 0x8d, 0xf9, 0xca, 0xff, 0x65, 0xae, + 0xc2, 0xfd, 0xe9, 0xaf, 0x91, 0x9b, 0x78, 0xc8, 0x4d, 0x3c, 0xe4, 0x26, + 0x1e, 0x72, 0x13, 0x0f, 0xb9, 0x89, 0x87, 0xdc, 0xc4, 0x43, 0x6e, 0xe2, + 0x21, 0x37, 0x41, 0x1d, 0x10, 0xd4, 0x07, 0xe3, 0xc8, 0xb9, 0xe1, 0xbf, + 0xbc, 0x5b, 0xc2, 0xdc, 0x22, 0x8a, 0xcd, 0x9c, 0x3b, 0xbf, 0xc9, 0x0d, + 0xea, 0x2b, 0xe5, 0x13, 0x0a, 0xcd, 0x89, 0x30, 0x07, 0xe2, 0x9a, 0x28, + 0x76, 0x73, 0x9d, 0x8c, 0xb9, 0xa8, 0x3d, 0x0b, 0x93, 0xcc, 0x91, 0x82, + 0x98, 0x15, 0xe4, 0xe7, 0xaf, 0x22, 0x4f, 0xca, 0x20, 0x4f, 0x1a, 0x40, + 0x4e, 0xc4, 0x7b, 0xea, 0xe8, 0x2e, 0xa9, 0xa0, 0x1d, 0xf4, 0xc6, 0xb5, + 0x2f, 0x79, 0xcc, 0xdf, 0xed, 0x4c, 0x59, 0xd7, 0x8f, 0xf7, 0x89, 0x2f, + 0xc5, 0xd1, 0xaf, 0x23, 0x57, 0xfe, 0x4b, 0x75, 0x6f, 0x36, 0x31, 0x44, + 0x99, 0xdf, 0xf7, 0x31, 0xf9, 0x72, 0xc4, 0xdf, 0xe0, 0xbe, 0x4f, 0x5f, + 0x22, 0xff, 0x44, 0x7a, 0xcf, 0x80, 0xe1, 0x67, 0x12, 0x92, 0x3c, 0xb9, + 0x05, 0x73, 0x96, 0xf4, 0xa9, 0x3b, 0x23, 0x88, 0xf2, 0xcc, 0x7f, 0x40, + 0x5e, 0xb6, 0xe8, 0x67, 0x78, 0xb3, 0x40, 0xbc, 0xf4, 0xaf, 0xf5, 0x99, + 0x62, 0xbd, 0xae, 0x74, 0xea, 0x60, 0xa3, 0x84, 0x3c, 0xca, 0xe8, 0x93, + 0x0e, 0x13, 0xb5, 0x54, 0x84, 0x9b, 0x38, 0xdf, 0x4c, 0xaa, 0x1a, 0xe7, + 0xcc, 0xaa, 0x3c, 0x21, 0x6b, 0xee, 0x53, 0x9f, 0xa9, 0x2e, 0x64, 0xd3, + 0xac, 0x71, 0x0b, 0x56, 0x7d, 0xe6, 0x49, 0xe0, 0x58, 0x46, 0x6e, 0x60, + 0xa8, 0xbd, 0xeb, 0x33, 0xb3, 0x0b, 0xc1, 0xbd, 0x55, 0x40, 0x03, 0xe3, + 0x55, 0x87, 0x18, 0x4b, 0xc1, 0xfd, 0x95, 0xae, 0x60, 0x09, 0x47, 0x78, + 0x13, 0x70, 0x94, 0xdb, 0x30, 0x60, 0x29, 0x3b, 0xd2, 0x50, 0x9f, 0xa9, + 0xd4, 0x5b, 0x69, 0x20, 0x1e, 0xe2, 0x8d, 0xce, 0xc3, 0xb3, 0x24, 0x45, + 0x3f, 0xe9, 0xfb, 0xe5, 0xd1, 0x81, 0xb0, 0xae, 0x44, 0x1d, 0x79, 0xcc, + 0x0c, 0xf4, 0x5c, 0x8d, 0xff, 0x58, 0xc5, 0xa9, 0x8c, 0xce, 0x79, 0x3e, + 0xf1, 0x2e, 0xf7, 0x28, 0xe6, 0x30, 0x5e, 0x8e, 0xd6, 0xea, 0xe1, 0xda, + 0xae, 0x16, 0x7e, 0xb6, 0x85, 0xfb, 0x91, 0x26, 0x9e, 0xf3, 0x15, 0xec, + 0x45, 0xba, 0xb8, 0xc6, 0x04, 0x6d, 0x90, 0xa5, 0xf7, 0xbf, 0xe5, 0x7d, + 0xeb, 0x99, 0xc8, 0x53, 0x13, 0x30, 0x5c, 0x4f, 0x1c, 0x11, 0x0c, 0x5e, + 0x9c, 0x09, 0xe0, 0xf4, 0xd5, 0x7b, 0xbe, 0x4f, 0xda, 0xb7, 0x95, 0xd6, + 0x68, 0xff, 0x08, 0xcf, 0x70, 0x20, 0xb7, 0x55, 0x78, 0xf5, 0x7f, 0x7f, + 0xe1, 0x09, 0x5d, 0xfc, 0xd0, 0x7d, 0xe9, 0x70, 0x4b, 0x8d, 0x1c, 0xdd, + 0x3b, 0xb0, 0xfe, 0x67, 0x3d, 0xcf, 0xef, 0x03, 0xad, 0xf5, 0x69, 0x29, + 0x8c, 0x65, 0xdb, 0xa4, 0x60, 0xb2, 0x56, 0x19, 0x0f, 0xc7, 0x5b, 0x11, + 0xdb, 0x38, 0xbe, 0x15, 0xfc, 0x85, 0x2e, 0x3b, 0x1d, 0x61, 0xad, 0x94, + 0x0c, 0xbe, 0xeb, 0x0c, 0xd3, 0x8e, 0x58, 0x6b, 0x6e, 0x0e, 0xe7, 0x22, + 0x3b, 0xa2, 0x1f, 0x36, 0xc3, 0x39, 0xfa, 0x5b, 0x1d, 0xf5, 0x12, 0xfb, + 0xc0, 0xb3, 0xdc, 0x6a, 0x4b, 0xd1, 0x33, 0x29, 0xa7, 0x17, 0x23, 0xbf, + 0x05, 0x9f, 0x32, 0x64, 0x86, 0xbe, 0xbf, 0x13, 0xbe, 0xaf, 0x5b, 0xf6, + 0xc2, 0x67, 0xed, 0x83, 0xcf, 0xda, 0x8f, 0x1a, 0x75, 0x7c, 0xa5, 0xf5, + 0x3e, 0x97, 0x75, 0x71, 0x55, 0x0e, 0x29, 0xf9, 0x57, 0x7c, 0xc3, 0xfe, + 0x00, 0x3a, 0xb0, 0x53, 0xe5, 0x7b, 0x81, 0x4e, 0xc0, 0xdf, 0x3a, 0x49, + 0xe8, 0xc4, 0xc6, 0x7b, 0xe3, 0x61, 0xd8, 0x46, 0x47, 0x41, 0xc5, 0x86, + 0x95, 0x80, 0xf7, 0xd5, 0x7a, 0xc0, 0x7b, 0xf8, 0x65, 0xe0, 0x37, 0xa5, + 0xd2, 0xb0, 0xa4, 0x82, 0x7d, 0x2b, 0xd8, 0xb7, 0x82, 0xda, 0x72, 0xb6, + 0xd1, 0xfa, 0xed, 0xaa, 0x2b, 0xa4, 0x9d, 0xb0, 0x51, 0xdf, 0x6a, 0x39, + 0x7f, 0xf4, 0x3c, 0x02, 0xfe, 0x3f, 0x02, 0xfe, 0x1f, 0x46, 0x4d, 0xf5, + 0x00, 0x6a, 0xaa, 0xfb, 0x50, 0x53, 0x1d, 0x42, 0x4d, 0x35, 0x85, 0x9a, + 0xea, 0x6e, 0xf8, 0x8f, 0x3b, 0xe1, 0x3f, 0x26, 0xe1, 0x3f, 0x26, 0xd4, + 0x9d, 0xd1, 0x41, 0x6f, 0xe3, 0x1d, 0x4a, 0xb4, 0x17, 0xdb, 0x1b, 0x22, + 0x50, 0x81, 0xf2, 0xb1, 0x71, 0xa9, 0x37, 0x59, 0x5b, 0x39, 0xea, 0x3e, + 0x6c, 0xda, 0x99, 0xd4, 0xa6, 0x90, 0xbf, 0xdf, 0x33, 0xc2, 0x9a, 0x2b, + 0xa9, 0x15, 0x55, 0xcd, 0x95, 0x7d, 0xc1, 0x45, 0x8a, 0x84, 0xdc, 0x0f, + 0x67, 0xce, 0x9e, 0x2e, 0x1a, 0x51, 0xbd, 0xd3, 0xbb, 0x5a, 0xef, 0x2c, + 0xcf, 0xb3, 0xde, 0x79, 0x75, 0xb5, 0xde, 0x59, 0x9e, 0x67, 0xbd, 0xf3, + 0xca, 0xba, 0x7a, 0xe7, 0xca, 0xd3, 0x97, 0xd6, 0xd5, 0x3b, 0x57, 0x9e, + 0x7e, 0x29, 0x1c, 0x4b, 0xa8, 0x0f, 0x21, 0xad, 0x96, 0x83, 0x67, 0x4f, + 0x98, 0x73, 0x34, 0xfb, 0xd6, 0xff, 0xdf, 0x74, 0xca, 0x96, 0x35, 0xb1, + 0xff, 0x68, 0x6b, 0x50, 0x23, 0xb5, 0xce, 0x77, 0xb7, 0xcc, 0x5f, 0x56, + 0xdf, 0x4b, 0xcb, 0xb5, 0xcd, 0xef, 0xc2, 0x03, 0xcb, 0xca, 0x10, 0xf3, + 0xbc, 0x0f, 0x7c, 0x7e, 0xf3, 0x73, 0xf5, 0x0e, 0xf5, 0xcd, 0xcd, 0x55, + 0xf9, 0x36, 0xec, 0x7c, 0xf4, 0xd1, 0xad, 0x81, 0x2f, 0x60, 0x3f, 0xa5, + 0x05, 0xfe, 0xfd, 0x01, 0xe0, 0x01, 0xaf, 0x3d, 0x53, 0xdd, 0x07, 0x05, + 0xe7, 0x0d, 0xee, 0xc6, 0xcd, 0xfc, 0xe5, 0x19, 0xe6, 0xd6, 0x55, 0x85, + 0x9b, 0xf5, 0x23, 0x6b, 0xce, 0x28, 0x06, 0x44, 0xb8, 0x5e, 0x4d, 0x05, + 0x74, 0xbb, 0xa8, 0x1d, 0xb9, 0x26, 0x1a, 0xb7, 0xd6, 0x9a, 0x9d, 0xe1, + 0xbd, 0xdb, 0xe5, 0x20, 0xaf, 0x52, 0xf8, 0xcc, 0x10, 0xdf, 0xcf, 0xfd, + 0xc0, 0xf7, 0x10, 0xde, 0x6a, 0x81, 0x1f, 0x47, 0xae, 0xc7, 0x7b, 0x1a, + 0xe6, 0x6c, 0xa6, 0xbc, 0x33, 0xdf, 0x25, 0xff, 0x79, 0xd4, 0xf7, 0x27, + 0x9c, 0xec, 0xf0, 0x25, 0xd4, 0x1e, 0x27, 0x69, 0x27, 0xa3, 0xa4, 0x73, + 0x30, 0x33, 0x2b, 0xa9, 0x3e, 0xd2, 0x72, 0x5e, 0x3f, 0xac, 0x7d, 0x98, + 0x6e, 0x3d, 0xdc, 0xe7, 0x1f, 0x5b, 0xf6, 0xc9, 0xb4, 0xec, 0x53, 0xa0, + 0xcd, 0xd6, 0xef, 0xc0, 0x99, 0x2b, 0xdb, 0xaf, 0xb7, 0x52, 0x61, 0x5d, + 0xf6, 0xf0, 0xe8, 0x66, 0x59, 0xe8, 0xcf, 0x9e, 0x7d, 0x05, 0xf9, 0x7a, + 0x79, 0x14, 0x73, 0xa9, 0x41, 0xbc, 0xe3, 0x7c, 0xb6, 0x8e, 0x5c, 0xf4, + 0x6c, 0x5d, 0xb6, 0x01, 0x3e, 0x5b, 0x11, 0xe1, 0x3c, 0xfb, 0x8a, 0xb6, + 0x7a, 0xe8, 0x03, 0xd2, 0x17, 0x70, 0xe6, 0x29, 0xd4, 0x5f, 0x87, 0x83, + 0x7b, 0xb4, 0x70, 0x9f, 0x1b, 0xb5, 0x20, 0x6f, 0xce, 0x69, 0x95, 0xf0, + 0x0e, 0xf0, 0x2b, 0xf0, 0x17, 0x86, 0x4e, 0xd8, 0x77, 0x80, 0x5b, 0x93, + 0xa5, 0xa3, 0x86, 0xba, 0x3b, 0x2d, 0x8f, 0x52, 0xd6, 0x7c, 0x7e, 0x14, + 0xef, 0xa2, 0x33, 0xfd, 0x4d, 0x78, 0xa6, 0xd1, 0xb0, 0x6e, 0x8f, 0xce, + 0x94, 0x90, 0xd7, 0xe7, 0x2d, 0xc0, 0x8e, 0x80, 0x1f, 0x25, 0x59, 0x69, + 0x66, 0x3e, 0x05, 0x4f, 0xad, 0x85, 0x37, 0xe6, 0x06, 0x19, 0x46, 0x75, + 0x0f, 0x78, 0x30, 0x91, 0x86, 0x1d, 0xde, 0xd7, 0x17, 0xdd, 0xe9, 0x1a, + 0xb6, 0xae, 0x05, 0x75, 0x3c, 0xe7, 0x07, 0x60, 0x8b, 0x19, 0xd8, 0x27, + 0x73, 0xa6, 0x12, 0x6b, 0x15, 0xda, 0x93, 0xe5, 0x1a, 0x59, 0x6b, 0x52, + 0x86, 0x51, 0xef, 0xf0, 0xfc, 0x79, 0x59, 0x6e, 0x46, 0x34, 0xe4, 0x60, + 0x8f, 0x63, 0xf8, 0x8d, 0xe0, 0x9d, 0x83, 0x1f, 0x6b, 0xa5, 0x82, 0x7c, + 0x55, 0xe5, 0xe2, 0xc8, 0xb5, 0x87, 0x48, 0xdf, 0x01, 0xac, 0xa7, 0x3e, + 0x53, 0x4f, 0x0f, 0x88, 0xdb, 0x4f, 0x5f, 0x91, 0x06, 0x6e, 0xc0, 0x78, + 0xaf, 0xc1, 0xd6, 0x07, 0xf0, 0xcc, 0x5a, 0x65, 0xf2, 0x56, 0xe1, 0xf7, + 0x7d, 0x23, 0xc7, 0x6f, 0x11, 0xe3, 0xe1, 0x78, 0xd0, 0xfa, 0x1d, 0xea, + 0x5e, 0xfa, 0x5a, 0x39, 0xbb, 0x18, 0xc5, 0xc1, 0x19, 0xd8, 0x20, 0xef, + 0x68, 0xc7, 0xc1, 0x17, 0x8e, 0xb5, 0x30, 0x1e, 0x62, 0x7e, 0xf9, 0xaf, + 0x70, 0xee, 0xbc, 0x9c, 0x44, 0xfd, 0x2f, 0xfd, 0x7c, 0x66, 0x80, 0x7f, + 0x4b, 0xa8, 0xef, 0xeb, 0xe1, 0x0d, 0x9b, 0xfd, 0x71, 0xd0, 0x67, 0xb6, + 0xc0, 0x13, 0x26, 0xac, 0x4f, 0x04, 0xf1, 0x38, 0xed, 0xdf, 0xaa, 0xe7, + 0xef, 0x96, 0x3f, 0x50, 0x67, 0xca, 0xcb, 0xa1, 0x45, 0xdf, 0x77, 0x73, + 0x83, 0xc3, 0xcb, 0x92, 0x1d, 0x7e, 0x52, 0x76, 0x5b, 0x7b, 0x59, 0x8f, + 0x59, 0xc4, 0xe3, 0xdf, 0xda, 0x96, 0xf7, 0xfd, 0x13, 0xa0, 0xfd, 0x07, + 0x6a, 0x9f, 0xbb, 0x41, 0x3f, 0x78, 0xa5, 0x6a, 0x12, 0xd2, 0x0a, 0xde, + 0xa4, 0x48, 0x6f, 0xa7, 0x1c, 0x6a, 0x3e, 0x1f, 0xca, 0xe6, 0x11, 0x71, + 0xbd, 0xb7, 0x0d, 0xde, 0x6f, 0x97, 0x9b, 0x8f, 0x86, 0xb4, 0xe5, 0x41, + 0x2f, 0xf6, 0x6f, 0xfe, 0x43, 0x8a, 0xbe, 0x81, 0x32, 0x77, 0x91, 0x35, + 0xba, 0xa3, 0xcf, 0x40, 0x07, 0x3f, 0xce, 0x0f, 0x24, 0x65, 0xbd, 0x1f, + 0x20, 0x5c, 0xf2, 0x23, 0x74, 0x85, 0x74, 0x88, 0xf2, 0x9f, 0x2a, 0x6e, + 0x29, 0x7c, 0xc6, 0x06, 0x5f, 0xf0, 0xa4, 0x7a, 0x9e, 0x37, 0xe8, 0x9b, + 0x18, 0xff, 0xa8, 0xc3, 0xdd, 0xf0, 0x7f, 0xd0, 0x41, 0xd8, 0x71, 0x71, + 0x91, 0xf7, 0x13, 0x43, 0xea, 0x4e, 0xab, 0x04, 0xd9, 0x2e, 0xf1, 0x3b, + 0x63, 0x2a, 0xc8, 0x27, 0x83, 0xfa, 0x2b, 0x43, 0x5f, 0x88, 0xf6, 0xb8, + 0xf2, 0x93, 0x25, 0xf5, 0x5d, 0x31, 0x89, 0x35, 0x3e, 0x9e, 0xad, 0x7f, + 0x27, 0xf1, 0xa3, 0x42, 0xf0, 0x77, 0x12, 0xe1, 0x37, 0xde, 0x7a, 0x90, + 0x47, 0x3c, 0xd8, 0x30, 0x65, 0xaa, 0x11, 0xfd, 0xdd, 0x04, 0xe5, 0x60, + 0x4b, 0xb9, 0x11, 0xe5, 0x0e, 0x7e, 0x50, 0xd3, 0xac, 0x93, 0xe5, 0xe3, + 0x61, 0x4e, 0xc4, 0x1a, 0x80, 0x3c, 0xc4, 0x78, 0x39, 0x90, 0xdf, 0x92, + 0xbe, 0x03, 0xf2, 0x03, 0xcf, 0x3d, 0x13, 0xb6, 0x94, 0x0e, 0xe3, 0xba, + 0xc5, 0x1a, 0x33, 0xac, 0x7b, 0xb7, 0x4b, 0x75, 0x92, 0xef, 0x13, 0xf2, + 0xda, 0xfc, 0x40, 0x70, 0x4f, 0x24, 0x89, 0xf0, 0x3d, 0xc7, 0x49, 0x29, + 0xab, 0xf7, 0x77, 0x86, 0xf8, 0x50, 0xa7, 0xdd, 0x19, 0x8d, 0xd3, 0x90, + 0x63, 0x00, 0x37, 0x8d, 0x58, 0xf6, 0x55, 0xc4, 0xb1, 0x69, 0xf0, 0xbd, + 0x38, 0x51, 0x91, 0x6b, 0x6d, 0x4b, 0xc5, 0x7d, 0x37, 0x49, 0x1d, 0xa3, + 0x7e, 0x11, 0xa6, 0x07, 0xb9, 0x2a, 0xce, 0x3b, 0x2a, 0x53, 0x46, 0xfe, + 0xdd, 0xdb, 0xca, 0xb5, 0xac, 0x55, 0x90, 0xf7, 0x7d, 0xd7, 0xe4, 0xf8, + 0xfc, 0x6d, 0x0f, 0x06, 0x77, 0xfe, 0xba, 0x9e, 0xbf, 0x78, 0x5b, 0x39, + 0xe8, 0xe3, 0xcc, 0xef, 0x86, 0x7d, 0xc2, 0x19, 0xea, 0x7b, 0xec, 0x4f, + 0x6e, 0x32, 0xe5, 0xc2, 0x4d, 0xbe, 0x7f, 0x0f, 0xbf, 0x09, 0x85, 0x75, + 0xac, 0xa5, 0xea, 0xd8, 0x0e, 0x95, 0x8f, 0xb8, 0xa3, 0x19, 0xad, 0x04, + 0xdb, 0x3d, 0xe9, 0xa1, 0xe6, 0xd1, 0xb3, 0x63, 0xe7, 0x75, 0x0b, 0xf1, + 0x37, 0x9b, 0x39, 0x2e, 0xb9, 0x3e, 0x7e, 0x63, 0x9e, 0x73, 0xb8, 0x66, + 0x5b, 0x70, 0xef, 0x75, 0x83, 0xab, 0x7c, 0xae, 0x48, 0x18, 0x87, 0x6e, + 0x68, 0xb5, 0x8f, 0xd6, 0x3c, 0x93, 0x76, 0x21, 0x53, 0x26, 0xe8, 0xa9, + 0xd6, 0xa2, 0x9c, 0x8d, 0x7f, 0x0f, 0x70, 0xfe, 0xb6, 0xa7, 0x1a, 0x17, + 0x6f, 0x9b, 0x85, 0x7c, 0x78, 0xa6, 0xd9, 0x46, 0xa4, 0x7f, 0x51, 0xdd, + 0xc0, 0x3e, 0xe2, 0xbf, 0x87, 0xf8, 0xef, 0x21, 0xfe, 0x7b, 0x88, 0xff, + 0x1e, 0xe2, 0xbf, 0x87, 0xf8, 0x0f, 0x1e, 0x3e, 0x07, 0x7d, 0x79, 0xd6, + 0x9b, 0x08, 0x73, 0xb6, 0xc7, 0x56, 0x73, 0x36, 0xfe, 0xcd, 0xcb, 0xb9, + 0xa6, 0xa2, 0xa5, 0x52, 0x91, 0x20, 0xe7, 0x15, 0x9d, 0xf9, 0x4d, 0x94, + 0xf3, 0x7e, 0xf4, 0xf7, 0x90, 0x00, 0x8e, 0xf9, 0x1e, 0xe1, 0x2a, 0x9a, + 0x6e, 0x13, 0x2e, 0xc8, 0xf9, 0x58, 0x67, 0xad, 0x87, 0xe1, 0x77, 0x37, + 0xfa, 0xb6, 0xe0, 0x9b, 0x4f, 0xf0, 0x7d, 0xa9, 0x76, 0x87, 0x8b, 0x58, + 0x5c, 0x6e, 0xa8, 0x78, 0x8c, 0x71, 0xe3, 0x0e, 0xfe, 0xad, 0x02, 0x64, + 0xc0, 0x77, 0x5f, 0x66, 0x6d, 0x51, 0x6e, 0x20, 0x2f, 0x5a, 0x8e, 0x72, + 0x21, 0xc0, 0x79, 0x6f, 0x6a, 0xa5, 0x05, 0xca, 0x59, 0x97, 0xd9, 0x14, + 0x98, 0x62, 0xb7, 0xe6, 0x78, 0x97, 0x54, 0xbd, 0x74, 0xb6, 0x49, 0x7a, + 0x46, 0x40, 0x5b, 0x74, 0x8f, 0x2c, 0x62, 0xcc, 0xa7, 0x44, 0x9f, 0x47, + 0x7e, 0x6b, 0x0f, 0xa9, 0xbf, 0x6f, 0xe8, 0xc5, 0x3e, 0xfa, 0xfc, 0x8e, + 0x96, 0x7b, 0x5a, 0x29, 0x04, 0x3e, 0x9b, 0xb1, 0x87, 0xe7, 0x48, 0xc1, + 0x76, 0xdd, 0x6d, 0x38, 0x1b, 0xe4, 0xfa, 0xaf, 0x5b, 0x55, 0x0e, 0x0e, + 0x3f, 0x7a, 0x62, 0xa8, 0xbf, 0x5f, 0xba, 0xb7, 0xcb, 0xc9, 0x21, 0xd6, + 0x6b, 0x9b, 0x81, 0x8f, 0x6b, 0x79, 0xff, 0xb4, 0x5d, 0x4e, 0x2d, 0xc2, + 0xcf, 0x2e, 0x66, 0x1d, 0xea, 0xf2, 0xd2, 0x50, 0x0a, 0xfe, 0xf9, 0xe6, + 0x7e, 0xc6, 0xe7, 0xe5, 0x26, 0x75, 0xa5, 0x17, 0xf0, 0x03, 0xd0, 0xcb, + 0x4d, 0xb0, 0x27, 0x1d, 0xfb, 0x47, 0xb8, 0xff, 0x45, 0xe1, 0xee, 0xb5, + 0x9d, 0x6d, 0x4a, 0x37, 0xf4, 0xac, 0x95, 0xd1, 0x41, 0xfb, 0xff, 0x14, + 0x6e, 0x6d, 0x31, 0x71, 0x5c, 0x67, 0xf8, 0x3f, 0xb3, 0xdc, 0x8c, 0xd7, + 0x30, 0x86, 0xf5, 0xb2, 0x58, 0xae, 0xba, 0x03, 0x63, 0x33, 0xd1, 0x62, + 0x65, 0xb0, 0xec, 0x16, 0x55, 0x96, 0xba, 0xda, 0x05, 0x42, 0xe2, 0x3a, + 0xdd, 0x24, 0xb4, 0x72, 0xd5, 0x2a, 0x42, 0x60, 0x37, 0x8e, 0xfa, 0xd2, + 0x46, 0x55, 0xdb, 0x37, 0xaf, 0x16, 0xec, 0x38, 0xcd, 0xac, 0x17, 0x37, + 0x38, 0xf4, 0x71, 0xb3, 0x2c, 0x0e, 0x90, 0x75, 0x56, 0x6e, 0xf2, 0x90, + 0x3e, 0x19, 0x6d, 0xa2, 0x24, 0x55, 0xa5, 0xbc, 0x54, 0x7d, 0xab, 0x5a, + 0x0b, 0x27, 0xc4, 0x0f, 0xa9, 0xad, 0xf6, 0xa5, 0x77, 0x4d, 0xbf, 0xef, + 0xcc, 0x2c, 0xc6, 0xa4, 0x51, 0x91, 0x56, 0x73, 0xe6, 0xcc, 0xb9, 0x9f, + 0xff, 0xf2, 0xfd, 0x17, 0x3e, 0x67, 0x67, 0xba, 0xc2, 0xbd, 0xcd, 0x95, + 0x76, 0xc6, 0xfe, 0xb6, 0xd4, 0xcc, 0x02, 0xf3, 0x1a, 0x86, 0x64, 0xdc, + 0x64, 0xae, 0xcf, 0x96, 0x3a, 0x57, 0x66, 0x1b, 0x1b, 0x65, 0xda, 0xe4, + 0x4b, 0x6a, 0xa6, 0xdc, 0x23, 0x17, 0x41, 0xc7, 0x85, 0xe1, 0xd6, 0xd0, + 0xf7, 0xda, 0x19, 0xf2, 0x73, 0x77, 0x3c, 0xd4, 0x57, 0x1a, 0x57, 0x16, + 0x34, 0xb6, 0xee, 0xde, 0xf5, 0xed, 0x49, 0xac, 0x29, 0x41, 0x5f, 0x79, + 0x5c, 0xcb, 0x26, 0x83, 0xef, 0x7d, 0xbb, 0xde, 0xe3, 0xbb, 0xde, 0x0f, + 0xfc, 0x8f, 0xf6, 0x2c, 0xef, 0xa6, 0x07, 0xae, 0xd3, 0x1a, 0xe5, 0x2c, + 0x05, 0xcf, 0x36, 0x66, 0x3d, 0x2b, 0x4d, 0x5c, 0x90, 0x15, 0x5f, 0x65, + 0xdd, 0x36, 0xc8, 0xbb, 0x36, 0x99, 0x5f, 0x04, 0xcd, 0x63, 0x1f, 0xed, + 0x36, 0x63, 0xe4, 0x43, 0x71, 0xf2, 0x4c, 0x07, 0xae, 0xc1, 0xb0, 0x07, + 0x13, 0x68, 0xe7, 0x3f, 0xef, 0xa6, 0xcc, 0xb3, 0xda, 0x97, 0x43, 0x3c, + 0xe3, 0xab, 0x82, 0xce, 0xf7, 0x60, 0x9b, 0x16, 0xb9, 0x63, 0x67, 0x7a, + 0xc2, 0x7c, 0x20, 0xd8, 0xbe, 0x5f, 0x8d, 0x13, 0x6b, 0x3c, 0xe7, 0x6e, + 0xd7, 0x99, 0x9b, 0xc2, 0x1c, 0x2b, 0x10, 0xcd, 0x53, 0x22, 0xe5, 0xaa, + 0xc8, 0xeb, 0xf8, 0xfd, 0xa6, 0x1a, 0xc6, 0x4f, 0x14, 0xed, 0xee, 0x93, + 0xb2, 0x5e, 0xfa, 0x9a, 0xd4, 0xa0, 0x7f, 0xd6, 0x5c, 0xdf, 0xbf, 0xeb, + 0x26, 0xf5, 0x99, 0xbf, 0xe8, 0x29, 0x19, 0x18, 0xa1, 0x7e, 0x6b, 0x93, + 0x97, 0x17, 0x5b, 0x64, 0xc3, 0xb4, 0xcc, 0xbb, 0x44, 0x01, 0x5e, 0x42, + 0x26, 0x63, 0x11, 0x8d, 0x51, 0xe5, 0x5b, 0x22, 0x5b, 0xf8, 0xb6, 0xb5, + 0xf8, 0x4c, 0x9c, 0xfe, 0x97, 0x4f, 0x16, 0xf9, 0x6e, 0xe0, 0x69, 0x48, + 0xc3, 0x8e, 0x00, 0xcb, 0x42, 0x08, 0x99, 0x3c, 0x77, 0xee, 0xf7, 0xbb, + 0x5c, 0x1b, 0xea, 0x68, 0xcf, 0xb6, 0x49, 0xe1, 0x30, 0x64, 0xa2, 0x1a, + 0xd4, 0x39, 0x47, 0x8d, 0x98, 0x96, 0xd1, 0x91, 0x0a, 0x7d, 0xf8, 0xe6, + 0x5e, 0x2d, 0xaf, 0x33, 0x37, 0x7e, 0xa4, 0xf7, 0x82, 0x72, 0xbe, 0xe2, + 0x92, 0x56, 0x4d, 0x59, 0x03, 0xaf, 0xad, 0xd6, 0x5f, 0xed, 0xe3, 0x5d, + 0xad, 0xd7, 0x5f, 0x88, 0x07, 0xf6, 0x1a, 0xeb, 0x7e, 0x1c, 0x0f, 0xea, + 0x92, 0xa1, 0xfd, 0x45, 0x3b, 0xad, 0x8c, 0xbd, 0xbd, 0x20, 0xf5, 0xa5, + 0x9f, 0xc9, 0x3b, 0xa5, 0x9f, 0xc8, 0xaf, 0x97, 0xce, 0x00, 0x7f, 0x58, + 0xe5, 0x3c, 0xf4, 0xc9, 0xcd, 0xba, 0xef, 0xdf, 0x74, 0xa7, 0x60, 0x2b, + 0xf8, 0xfe, 0xef, 0xdc, 0x0d, 0x19, 0x38, 0xf6, 0x3d, 0xec, 0x39, 0x07, + 0x1e, 0xa2, 0x2c, 0x9c, 0x04, 0xbd, 0xb9, 0x7d, 0xd2, 0x19, 0xd5, 0x74, + 0x32, 0x78, 0xac, 0x15, 0x7b, 0x30, 0x42, 0x4c, 0xce, 0xbd, 0x8c, 0xf4, + 0x91, 0x66, 0x8c, 0x7a, 0x09, 0xf3, 0xb7, 0x82, 0x2f, 0xf6, 0xe2, 0xa7, + 0xe4, 0xee, 0x08, 0xd6, 0x3a, 0x42, 0xda, 0x6b, 0x95, 0x81, 0x47, 0xb1, + 0x8f, 0x5c, 0x8b, 0xdc, 0xf3, 0x7e, 0x19, 0xa7, 0x6f, 0xef, 0x9e, 0xc7, + 0xb2, 0xf1, 0x95, 0x2e, 0xf1, 0xa5, 0x05, 0xba, 0x7c, 0xfe, 0x78, 0x80, + 0x9b, 0xde, 0x55, 0x43, 0x68, 0x6f, 0xe7, 0xdf, 0x53, 0xc4, 0x79, 0x79, + 0xbf, 0x15, 0xb8, 0x7c, 0x1c, 0x78, 0x28, 0x53, 0xbf, 0x20, 0x8d, 0x91, + 0x28, 0xda, 0x10, 0xaf, 0x68, 0x59, 0x22, 0x59, 0x8f, 0x39, 0x5a, 0xcc, + 0x97, 0xc2, 0x1a, 0xa7, 0x74, 0x2e, 0x57, 0x1f, 0xcf, 0x9c, 0x58, 0x3e, + 0xa8, 0xb3, 0x41, 0x23, 0xac, 0x23, 0x7d, 0xa7, 0x35, 0xa6, 0x82, 0x0e, + 0xc5, 0x78, 0xc3, 0x92, 0xd1, 0xe5, 0x2e, 0x8c, 0x77, 0x41, 0x32, 0x6e, + 0x73, 0xcc, 0x51, 0xb4, 0xa1, 0x9c, 0x19, 0x05, 0x96, 0xf8, 0x58, 0x8d, + 0x2d, 0xc6, 0xa0, 0xcb, 0xe3, 0x32, 0x66, 0xee, 0xd9, 0xb1, 0xc7, 0xbc, + 0xb6, 0x15, 0x0c, 0x63, 0x38, 0x5c, 0x53, 0xd7, 0x8e, 0x35, 0xb1, 0x3f, + 0x7e, 0xb0, 0x93, 0x33, 0x8b, 0x0b, 0x90, 0x53, 0x0b, 0x1f, 0x66, 0xdc, + 0x67, 0x25, 0x1b, 0x6b, 0xd3, 0xb6, 0x4d, 0x05, 0xf7, 0x92, 0xf5, 0xe8, + 0xd3, 0xfa, 0x0e, 0xe4, 0xd0, 0x9e, 0xb0, 0x8e, 0x6d, 0xc5, 0xc8, 0xe0, + 0xec, 0x03, 0x1b, 0x97, 0x75, 0x5f, 0x96, 0xcc, 0x42, 0x4e, 0x26, 0x74, + 0x3f, 0x9e, 0xe1, 0x41, 0x8d, 0x43, 0xc8, 0xab, 0x03, 0xbd, 0x38, 0xcb, + 0xd4, 0x03, 0x7b, 0x38, 0xd9, 0x4b, 0x2e, 0xfa, 0x4f, 0xc8, 0xb3, 0xf8, + 0xd6, 0xcb, 0x3b, 0x6a, 0x93, 0x81, 0x67, 0xa0, 0x2f, 0xbd, 0x66, 0x7d, + 0x54, 0x3e, 0xf3, 0xfc, 0x38, 0x63, 0x2e, 0x7f, 0xf6, 0x4c, 0xf9, 0xc4, + 0xd3, 0xb1, 0xd8, 0xe9, 0x88, 0x58, 0xe7, 0x03, 0x5b, 0xfd, 0xf0, 0xf4, + 0xbc, 0xe2, 0xf7, 0xc3, 0xe7, 0x57, 0x54, 0x07, 0xda, 0x46, 0xd1, 0x8e, + 0xeb, 0x30, 0x65, 0xdc, 0xfb, 0xab, 0x3f, 0x73, 0xc4, 0xf7, 0x27, 0x74, + 0x4e, 0x58, 0xca, 0x9c, 0x57, 0x4d, 0x7c, 0xee, 0x88, 0x17, 0x6b, 0xc7, + 0x5c, 0x29, 0x73, 0x45, 0x1d, 0xc6, 0x7a, 0x58, 0xee, 0x25, 0x4f, 0x24, + 0x36, 0x84, 0xe3, 0x5b, 0x93, 0xcb, 0x2a, 0x95, 0x1c, 0x54, 0x56, 0xba, + 0x80, 0x5f, 0x8b, 0xd2, 0x71, 0xcc, 0x44, 0x52, 0x81, 0x77, 0xb1, 0x27, + 0xfb, 0xa8, 0xef, 0x4f, 0xda, 0xac, 0x4f, 0x99, 0x51, 0x45, 0xdf, 0x4b, + 0xa7, 0x8e, 0x77, 0x5e, 0x3e, 0x90, 0x32, 0x8f, 0xaa, 0xfd, 0xe1, 0xfb, + 0x28, 0x64, 0xe6, 0xf6, 0x78, 0x67, 0x96, 0x95, 0x29, 0x2f, 0x79, 0xa9, + 0xe4, 0xac, 0xb2, 0x72, 0x18, 0x33, 0x37, 0xa6, 0x28, 0x37, 0x52, 0x66, + 0xa7, 0xa2, 0x7f, 0xb4, 0x5d, 0xef, 0x7b, 0x12, 0xfd, 0x53, 0xaa, 0x25, + 0x5c, 0x0f, 0xef, 0xeb, 0x4a, 0x5f, 0xc0, 0x33, 0x94, 0x39, 0xfd, 0xc6, + 0xcc, 0x02, 0xf3, 0xcb, 0x74, 0x5e, 0x43, 0x7a, 0xe0, 0x18, 0xdf, 0x0d, + 0xb9, 0x7f, 0xe2, 0x6f, 0xa8, 0x43, 0xb9, 0xcc, 0x3a, 0x27, 0xe4, 0xb7, + 0x23, 0x1a, 0x3f, 0xdf, 0x3f, 0x91, 0xd7, 0xb9, 0x8b, 0x0d, 0x35, 0x10, + 0xee, 0x7b, 0xfb, 0xce, 0x92, 0x19, 0xf7, 0x4b, 0x1c, 0x67, 0x21, 0x72, + 0xb2, 0x5d, 0x98, 0x23, 0x3a, 0x5e, 0x6a, 0xd2, 0x06, 0x7d, 0x03, 0xcc, + 0x15, 0x68, 0xc6, 0xdd, 0x2f, 0x88, 0x71, 0xac, 0x63, 0x07, 0x9d, 0x00, + 0x77, 0x02, 0xaf, 0x56, 0x31, 0x4e, 0x61, 0x51, 0xf2, 0x41, 0x7f, 0xe9, + 0x60, 0x4e, 0x6a, 0xa1, 0xfa, 0x45, 0x63, 0x04, 0x3a, 0x70, 0x1c, 0xef, + 0xf7, 0x4f, 0x90, 0x3e, 0x79, 0x36, 0x49, 0x35, 0xbe, 0xc4, 0xf5, 0x1c, + 0x94, 0x89, 0x45, 0x60, 0x23, 0xfc, 0xe6, 0x17, 0x83, 0x7b, 0xbb, 0x0e, + 0x9c, 0x3d, 0xe1, 0x99, 0x9a, 0x5f, 0x67, 0x5d, 0xc6, 0x4f, 0xc0, 0x2b, + 0x3a, 0x8f, 0x8a, 0x7d, 0x99, 0x4b, 0x78, 0x88, 0xfa, 0xd1, 0x6d, 0x48, + 0x0c, 0x6d, 0x89, 0x59, 0x59, 0x6f, 0x8d, 0x26, 0x23, 0xdd, 0x32, 0x0f, + 0x79, 0x57, 0x81, 0xee, 0x2c, 0x5c, 0x89, 0xca, 0xac, 0xa7, 0xe3, 0xd9, + 0xc9, 0x8f, 0x95, 0x2b, 0xb5, 0xfa, 0x71, 0xb9, 0x51, 0x77, 0xf4, 0x37, + 0xea, 0xb5, 0xc2, 0xab, 0x86, 0x7c, 0xff, 0x88, 0xce, 0xa5, 0x73, 0x2a, + 0xd2, 0xd9, 0x4f, 0xcc, 0xb3, 0xa2, 0xf3, 0xea, 0x20, 0x3b, 0x80, 0x39, + 0xde, 0x06, 0xe6, 0x78, 0x0b, 0x98, 0xe3, 0x57, 0xc0, 0xd8, 0x37, 0x4b, + 0x93, 0xa1, 0xfc, 0x9f, 0x86, 0x1c, 0xa2, 0xae, 0xb6, 0xce, 0xe0, 0x4e, + 0xa7, 0xf3, 0xa0, 0xc1, 0xdb, 0xb0, 0x3f, 0xd6, 0x4b, 0x19, 0x59, 0x5d, + 0x9a, 0x90, 0xb5, 0xa5, 0x20, 0x0f, 0xf9, 0x03, 0xe6, 0x7d, 0x8d, 0xf0, + 0x9e, 0x1c, 0xc8, 0xa1, 0x3d, 0x32, 0x70, 0x94, 0xf2, 0xa3, 0x43, 0x96, + 0x8b, 0xab, 0x5a, 0x0e, 0x2d, 0x17, 0x59, 0x8e, 0x88, 0xce, 0x21, 0x9b, + 0xda, 0x90, 0x8a, 0x5b, 0x47, 0xfd, 0x3e, 0xed, 0x0f, 0x0a, 0xfc, 0xf3, + 0x94, 0x97, 0x7f, 0x0a, 0xef, 0x5e, 0xe9, 0xdc, 0xba, 0x19, 0xb3, 0x1b, + 0xed, 0x9a, 0xb2, 0x6b, 0x30, 0x88, 0xb9, 0xab, 0xdb, 0x68, 0x83, 0x39, + 0x80, 0x19, 0xaf, 0x43, 0x87, 0x34, 0x9c, 0x6e, 0x8d, 0xfd, 0x1a, 0xce, + 0x21, 0x9d, 0x77, 0xcb, 0x71, 0x0a, 0x45, 0x5b, 0xe6, 0x8a, 0x56, 0x32, + 0x0f, 0xfa, 0xbb, 0x01, 0xbb, 0x6d, 0x15, 0x77, 0xb0, 0x86, 0x33, 0x58, + 0xaf, 0x53, 0xcf, 0x6f, 0x6a, 0xd9, 0xbb, 0x5c, 0xff, 0x23, 0xc6, 0xb1, + 0xce, 0xa4, 0xe5, 0x0f, 0x7d, 0x94, 0x81, 0xf4, 0x4d, 0x65, 0x75, 0xff, + 0xa0, 0xdf, 0x2a, 0xda, 0xae, 0xd5, 0x29, 0x8f, 0x45, 0x2e, 0x79, 0x36, + 0x74, 0xc9, 0xcb, 0x09, 0x62, 0x80, 0xb2, 0x6a, 0xf6, 0xf3, 0xc3, 0x35, + 0xfb, 0xfe, 0x5e, 0x9b, 0xeb, 0x72, 0x42, 0xb9, 0x4d, 0xdd, 0xbf, 0xa1, + 0xb1, 0x8d, 0x57, 0x7a, 0x56, 0xde, 0xc4, 0x7d, 0x07, 0x18, 0x27, 0x27, + 0x6f, 0x00, 0xe3, 0xd5, 0x4b, 0xcd, 0xbc, 0xed, 0x93, 0x38, 0xa7, 0x92, + 0x9a, 0xbb, 0xda, 0x29, 0x97, 0xaf, 0x15, 0xd4, 0x4b, 0xd7, 0x3c, 0xf5, + 0xf3, 0xab, 0x45, 0x55, 0xb8, 0xea, 0xfb, 0xff, 0x70, 0x67, 0xe4, 0x9d, + 0x25, 0x5f, 0x4e, 0xbb, 0x46, 0x7f, 0x44, 0x9a, 0xf9, 0x74, 0xbe, 0xdf, + 0x01, 0xd9, 0xbc, 0x7e, 0xc0, 0xf7, 0x1f, 0x19, 0x19, 0x11, 0xe7, 0x00, + 0x31, 0xca, 0x70, 0x82, 0x39, 0xae, 0x94, 0x39, 0x19, 0xdb, 0x3e, 0x5f, + 0x51, 0x0a, 0xf2, 0xad, 0x3b, 0xc0, 0x2f, 0x8f, 0xee, 0x0b, 0xe3, 0x26, + 0x3f, 0x7c, 0x9e, 0x7e, 0xe5, 0xc4, 0xe7, 0xfc, 0xca, 0xa6, 0x9c, 0x2d, + 0xf6, 0xa2, 0x7f, 0x4c, 0x7e, 0x50, 0x8c, 0xee, 0x2a, 0x9b, 0x78, 0x3a, + 0x46, 0xa1, 0x78, 0xcf, 0x1f, 0xd4, 0xf1, 0x03, 0x60, 0x12, 0xd3, 0xf7, + 0x67, 0x5d, 0xce, 0xd7, 0x8d, 0xf9, 0x36, 0xcc, 0x7d, 0xd0, 0xff, 0xa7, + 0xb5, 0x7e, 0x2e, 0x2b, 0xd8, 0xc1, 0xe0, 0xef, 0x98, 0x8c, 0x15, 0xa1, + 0xe3, 0x15, 0xf3, 0x4c, 0x89, 0x15, 0xac, 0xc4, 0x2c, 0x64, 0xc7, 0x0c, + 0xe4, 0xcd, 0x29, 0x1d, 0x67, 0xed, 0xd5, 0xb2, 0x67, 0x8e, 0xe5, 0x9c, + 0xa4, 0x2b, 0x6e, 0x8f, 0x3e, 0xbf, 0xcd, 0x1b, 0x2f, 0x26, 0x82, 0x3b, + 0x07, 0x1f, 0xe7, 0x94, 0xb4, 0xc1, 0x1e, 0xca, 0xae, 0x4c, 0x81, 0x27, + 0x12, 0x38, 0xdb, 0x56, 0xcd, 0x0f, 0x0d, 0xe8, 0xef, 0x86, 0xf6, 0x29, + 0x06, 0xb1, 0x8b, 0x86, 0xc9, 0x76, 0xa7, 0xd0, 0xaf, 0x5d, 0x32, 0x57, + 0xdb, 0xb4, 0x5c, 0x7d, 0xb8, 0x2e, 0x0d, 0x1c, 0xf2, 0x04, 0xca, 0x11, + 0xd4, 0x25, 0xc3, 0xb2, 0x81, 0xf2, 0x34, 0xca, 0x2d, 0x78, 0xb2, 0xcd, + 0x61, 0xe0, 0x0a, 0x3c, 0x5f, 0xc3, 0x78, 0x23, 0x58, 0x73, 0xce, 0x94, + 0x8f, 0x4e, 0x50, 0x97, 0x38, 0x06, 0x73, 0x91, 0x67, 0x6d, 0x3c, 0x6b, + 0x45, 0x95, 0x5d, 0x60, 0x19, 0xcf, 0x72, 0xf0, 0xfd, 0x21, 0x99, 0x84, + 0x3e, 0x99, 0x6b, 0x81, 0x4c, 0xfa, 0x68, 0x5b, 0x26, 0xb1, 0xae, 0x5d, + 0xc6, 0xae, 0x92, 0xd7, 0x4d, 0xd0, 0x5b, 0xa7, 0x64, 0xaf, 0xc5, 0x34, + 0x1e, 0xad, 0x80, 0x16, 0xaf, 0x83, 0xae, 0x96, 0x41, 0x53, 0x99, 0xa2, + 0x35, 0x3a, 0xad, 0x92, 0xda, 0x2f, 0xf0, 0x38, 0xe8, 0xb5, 0xe3, 0x0a, + 0xb1, 0x28, 0x79, 0xd9, 0x01, 0xed, 0x89, 0xdf, 0x61, 0xdb, 0x93, 0x8e, + 0xb2, 0x41, 0x83, 0xa0, 0xcb, 0x62, 0xc0, 0xd3, 0xef, 0x29, 0x2d, 0x57, + 0x47, 0xef, 0x48, 0x2a, 0x7d, 0x47, 0x2c, 0xc8, 0x02, 0xcb, 0xfd, 0x50, + 0x5c, 0x8c, 0x79, 0x5c, 0x5e, 0xc7, 0x3c, 0x06, 0xf8, 0xfb, 0xc8, 0x90, + 0xe6, 0xef, 0x51, 0x89, 0xec, 0xe6, 0x71, 0xd0, 0x1b, 0x64, 0x50, 0xc0, + 0xd3, 0xe9, 0x90, 0x46, 0x9f, 0x06, 0xff, 0x5a, 0xb0, 0xca, 0x92, 0x32, + 0x0f, 0xfe, 0xbf, 0x8e, 0xef, 0xb7, 0xea, 0x9f, 0xaa, 0xb9, 0x05, 0x15, + 0xe6, 0xb2, 0x7c, 0x1b, 0x38, 0xf9, 0xf7, 0x38, 0xbb, 0x2e, 0x8d, 0xdd, + 0x07, 0x46, 0x18, 0x4b, 0xfb, 0xb7, 0xba, 0x6c, 0x1f, 0x95, 0xcd, 0xe1, + 0xe3, 0x28, 0xef, 0xc3, 0xd3, 0xc0, 0x39, 0x44, 0x75, 0x2c, 0x7c, 0xd9, + 0x1b, 0x36, 0x0a, 0x3a, 0xef, 0xe0, 0x98, 0xce, 0xcf, 0x37, 0xec, 0x03, + 0xf8, 0x4e, 0xbf, 0x0c, 0xf7, 0x06, 0xcc, 0xa4, 0x12, 0x3a, 0xc7, 0xb4, + 0x02, 0x2c, 0xb1, 0x82, 0xf1, 0xde, 0xa7, 0x5f, 0xaf, 0x06, 0x1e, 0x1e, + 0xfe, 0xa7, 0x9f, 0x8e, 0x31, 0x27, 0x7d, 0x33, 0x11, 0xe8, 0xbf, 0xcf, + 0xfc, 0x4d, 0x7b, 0x6e, 0xd4, 0xc0, 0xcb, 0x6d, 0x33, 0x86, 0xb6, 0xd0, + 0x65, 0xd0, 0x45, 0x65, 0x4d, 0xbf, 0x6c, 0x17, 0xf4, 0x2d, 0xd4, 0x52, + 0xe6, 0x07, 0x12, 0xf4, 0x9d, 0xb7, 0xa9, 0x77, 0xda, 0x21, 0x5f, 0x92, + 0x1a, 0x57, 0xbe, 0x6f, 0xe7, 0x21, 0x15, 0xac, 0xe4, 0x24, 0x68, 0xb4, + 0x4d, 0x2c, 0x67, 0x5c, 0x1e, 0xcc, 0x3b, 0xab, 0xfb, 0xb2, 0x6d, 0xb3, + 0x6f, 0x73, 0x5e, 0xae, 0x9f, 0x7b, 0xe1, 0x1e, 0xe8, 0xa7, 0x36, 0x35, + 0x8d, 0x36, 0x6a, 0xed, 0xfd, 0x01, 0x8d, 0x36, 0xf7, 0x11, 0xfb, 0x3f, + 0xfb, 0x20, 0x9d, 0x0c, 0x1b, 0x41, 0x0e, 0x06, 0x9e, 0x35, 0x9e, 0xe7, + 0xa7, 0xc0, 0xf7, 0x3b, 0xe9, 0xa7, 0xe9, 0x67, 0x0c, 0xe8, 0xe7, 0x91, + 0x6d, 0xfa, 0x21, 0xdd, 0x74, 0xca, 0xd8, 0x35, 0x5b, 0x26, 0x8a, 0xfa, + 0xbe, 0x81, 0x35, 0xe9, 0x3f, 0x3a, 0x0e, 0xba, 0x21, 0xad, 0x93, 0xb7, + 0x4c, 0x29, 0x83, 0x8e, 0xca, 0x90, 0x4f, 0x65, 0xd0, 0x14, 0x31, 0x50, + 0x19, 0xf2, 0xad, 0x5c, 0xb7, 0x9c, 0x2a, 0xf6, 0x4c, 0x9d, 0xbd, 0x02, + 0x3a, 0xba, 0x5e, 0xe7, 0xfd, 0xeb, 0x35, 0x9b, 0xd4, 0x83, 0xb7, 0xb6, + 0xef, 0xfe, 0xef, 0xb8, 0xfb, 0x43, 0x72, 0x03, 0x76, 0xcb, 0x9b, 0xa5, + 0x61, 0xc8, 0x24, 0x21, 0x5e, 0x04, 0x6d, 0x8c, 0xca, 0x6a, 0xe9, 0xa4, + 0xac, 0x41, 0x3f, 0xad, 0x2f, 0x0d, 0x00, 0x4f, 0x43, 0x8e, 0xbe, 0x72, + 0x44, 0xde, 0x58, 0x52, 0x32, 0x63, 0x43, 0xbf, 0x2c, 0xd3, 0x07, 0x0f, + 0x7a, 0x2e, 0x77, 0xea, 0x98, 0xfd, 0x58, 0x35, 0xf0, 0xc5, 0x8f, 0x57, + 0xbb, 0x64, 0xa2, 0x6a, 0xca, 0x63, 0xd5, 0x1e, 0x79, 0xa2, 0x1a, 0x93, + 0xd3, 0xb5, 0x84, 0x7c, 0xa3, 0x7a, 0x50, 0x4e, 0x55, 0x0f, 0xc9, 0x93, + 0xb5, 0xa4, 0x7c, 0x13, 0x76, 0x61, 0xae, 0xe6, 0xc8, 0x64, 0x6d, 0x58, + 0x1e, 0xaf, 0xd1, 0xc7, 0x8e, 0xf9, 0xf0, 0xcb, 0x6e, 0xfb, 0x2e, 0xb8, + 0xae, 0x0e, 0xac, 0xcb, 0x51, 0xe3, 0x3a, 0x66, 0x29, 0xb9, 0xc0, 0xff, + 0x21, 0x72, 0x0e, 0x7d, 0x2f, 0xbe, 0xa2, 0xa4, 0xa2, 0xe7, 0x6f, 0xfe, + 0xdf, 0x48, 0x54, 0xdb, 0x46, 0xe7, 0xca, 0x07, 0xd1, 0xc6, 0xa6, 0x4d, + 0x12, 0xfa, 0x41, 0x9a, 0xfe, 0xff, 0xa6, 0xed, 0x65, 0x68, 0x1f, 0xf6, + 0x2d, 0xda, 0x5e, 0xfa, 0xec, 0x29, 0x3f, 0x68, 0xe7, 0xd0, 0xd6, 0xda, + 0x19, 0xe7, 0x68, 0xce, 0x7b, 0x31, 0xf7, 0xf0, 0xff, 0xa7, 0x04, 0xf1, + 0xaa, 0xb3, 0xb5, 0x83, 0xfc, 0x3f, 0x15, 0xac, 0xe5, 0x8b, 0xf3, 0xc5, + 0x27, 0x4a, 0x63, 0xea, 0xb1, 0x12, 0x11, 0x8d, 0x2f, 0x17, 0xb7, 0x73, + 0xf2, 0xbe, 0x2e, 0xcb, 0x6e, 0x54, 0xaf, 0x21, 0xf0, 0xdb, 0xa7, 0x75, + 0x7e, 0xde, 0xd8, 0x10, 0xe9, 0x8f, 0x71, 0xb8, 0xae, 0x30, 0xb6, 0x00, + 0x6c, 0xeb, 0x9a, 0x72, 0xa9, 0x1a, 0xf8, 0xaf, 0xe6, 0x34, 0xbd, 0xbc, + 0x05, 0x9a, 0x63, 0xfc, 0x21, 0x78, 0xe6, 0xcb, 0x41, 0xdf, 0xec, 0x90, + 0x43, 0x7b, 0x1c, 0xfb, 0x35, 0x7a, 0x38, 0x17, 0xff, 0x4f, 0x07, 0xe5, + 0x70, 0xbd, 0xcc, 0x2f, 0xb6, 0x35, 0x2d, 0x06, 0x31, 0x5e, 0x47, 0x9e, + 0xc3, 0x5d, 0x54, 0x4c, 0xae, 0xbf, 0x43, 0x2a, 0x0e, 0x6d, 0x5b, 0xca, + 0xef, 0x21, 0x29, 0x63, 0x9e, 0x8a, 0xd3, 0xf4, 0x8d, 0x05, 0x72, 0xb6, + 0x62, 0x3e, 0x98, 0x77, 0xba, 0xbc, 0x1f, 0xef, 0xa8, 0x73, 0x80, 0x99, + 0xa6, 0xf8, 0x7e, 0x11, 0x65, 0xfa, 0x46, 0xe6, 0xf0, 0x4c, 0x84, 0x75, + 0xaf, 0xf5, 0x6b, 0xac, 0x7e, 0xf2, 0x41, 0xbf, 0x99, 0xb2, 0x95, 0xcf, + 0x44, 0xb6, 0x94, 0xf1, 0x8b, 0xf5, 0x7e, 0xca, 0xdc, 0xfd, 0x36, 0x7f, + 0x51, 0xf9, 0x8b, 0xa9, 0x7d, 0x0a, 0xe1, 0xb7, 0x3d, 0xf2, 0x94, 0xc9, + 0xdc, 0xf5, 0xb4, 0x1a, 0x2b, 0xfd, 0x34, 0xcc, 0xd3, 0xdd, 0x52, 0xfb, + 0x2b, 0x6f, 0xf7, 0x07, 0x79, 0xee, 0x1c, 0x7b, 0x67, 0x6e, 0xfb, 0x4e, + 0x3a, 0x61, 0x8e, 0x7b, 0x3b, 0x70, 0xab, 0x56, 0x62, 0xe0, 0x41, 0xc8, + 0x3b, 0xbb, 0x45, 0xf3, 0x63, 0xa1, 0xf6, 0x2f, 0x7f, 0x43, 0xf3, 0x73, + 0xd3, 0xc7, 0xf0, 0xdb, 0x7e, 0xda, 0xb6, 0x94, 0x1b, 0x97, 0x02, 0xbf, + 0x91, 0xb6, 0xa1, 0x21, 0x2b, 0x50, 0x47, 0x5e, 0x05, 0x9f, 0x6c, 0xb7, + 0xe5, 0xdf, 0x7f, 0x01, 0x99, 0xe7, 0xd3, 0x46, 0x40, 0x67, 0x00, 0x00, + 0x00 }; +static u32 bnx2_RXP_b09FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b09FwRodata[(0x278/4) + 1] = { + 0x08003fa4, 0x08003ea4, 0x08003f48, 0x08003f60, 0x08003f78, 0x08003f98, + 0x08003fa4, 0x08003fa4, 0x08003eac, 0x00000000, 0x080049d4, 0x08004a0c, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004a44, 0x08004c08, + 0x08004b50, 0x08004b88, 0x08004c08, 0x08004ad8, 0x08004c08, 0x08004c08, + 0x08004b88, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004bc8, + 0x08004c08, 0x08004bc8, 0x08004b50, 0x08004c08, 0x08004c08, 0x08004bc8, + 0x08004bc8, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, 0x08004c08, + 0x08004ab4, 0x00000000, 0x0800602c, 0x08006044, 0x08006044, 0x08006044, + 0x0800602c, 0x08006044, 0x08006044, 0x08006044, 0x0800602c, 0x08006044, + 0x08006044, 0x08006044, 0x0800602c, 0x08006044, 0x08006044, 0x08006044, + 0x08006038, 0x00000000, 0x00000000 }; +static u32 bnx2_RXP_b09FwBss[(0x13dc/4) + 1] = { 0x0 }; +static u32 bnx2_RXP_b09FwSbss[(0x2c/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_rxp_fw_09 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x08003184, + + .text_addr = 0x08000000, + .text_len = 0x673c, + .text_index = 0x0, + .gz_text = bnx2_RXP_b09FwText, + .gz_text_len = sizeof(bnx2_RXP_b09FwText), + + .data_addr = 0x080069e0, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_RXP_b09FwData, + + .sbss_addr = 0x080069e0, + .sbss_len = 0x2c, + .sbss_index = 0x0, + .sbss = bnx2_RXP_b09FwSbss, + + .bss_addr = 0x08006a10, + .bss_len = 0x13dc, + .bss_index = 0x0, + .bss = bnx2_RXP_b09FwBss, + + .rodata_addr = 0x08006740, + .rodata_len = 0x278, + .rodata_index = 0x0, + .rodata = bnx2_RXP_b09FwRodata, +}; + -- cgit v1.2.3 From 5793bfe19beaa3c804fa2d33af238bf51bf28211 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:13:52 -0800 Subject: [BNX2]: New firmware to support 5709 (part 4). Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2_fw2.h | 1037 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1037 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2_fw2.h b/drivers/net/bnx2_fw2.h index abab341546df..680c769a3fc0 100644 --- a/drivers/net/bnx2_fw2.h +++ b/drivers/net/bnx2_fw2.h @@ -3047,3 +3047,1040 @@ static struct fw_info bnx2_rxp_fw_09 = { .rodata = bnx2_RXP_b09FwRodata, }; +static u8 bnx2_TPAT_b09FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0xdb, 0xfd, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xc5, 0x58, 0x5d, 0x6c, + 0x1c, 0x57, 0x15, 0x3e, 0xf3, 0xbb, 0x13, 0x77, 0xed, 0xbd, 0x49, 0x97, + 0x6a, 0x13, 0xb9, 0x74, 0xc6, 0x1e, 0x3b, 0x8b, 0x1c, 0x35, 0x93, 0xb0, + 0x24, 0x16, 0x5a, 0xd1, 0xc9, 0xcc, 0xae, 0x6b, 0xe5, 0x29, 0x86, 0xbc, + 0xf1, 0xb2, 0xac, 0xed, 0x46, 0x54, 0x48, 0x4d, 0x51, 0x84, 0x22, 0x81, + 0x94, 0x65, 0x76, 0x53, 0x40, 0x5a, 0x65, 0xc1, 0xa0, 0x04, 0x21, 0x84, + 0x22, 0x9b, 0x66, 0x91, 0x58, 0x3c, 0x4d, 0xe9, 0x6b, 0x94, 0xbc, 0x90, + 0x96, 0x17, 0x9e, 0x4b, 0x9e, 0xac, 0x02, 0x12, 0x0f, 0xa8, 0x8a, 0x78, + 0x40, 0x15, 0x0d, 0x1e, 0xbe, 0x33, 0x3f, 0x9b, 0x5d, 0xd7, 0x29, 0x79, + 0xa8, 0x84, 0xa5, 0xf1, 0xcc, 0xfd, 0x39, 0xf7, 0xe7, 0x7c, 0xdf, 0x77, + 0xee, 0xb9, 0x5b, 0x92, 0x69, 0x82, 0xd2, 0xbf, 0x49, 0x3c, 0x97, 0xbe, + 0x71, 0xf1, 0xd2, 0xe2, 0x8b, 0x27, 0x4d, 0x3a, 0x71, 0xe2, 0x45, 0xe9, + 0x19, 0x43, 0xa6, 0xcf, 0xe0, 0x4f, 0x21, 0x12, 0xd9, 0xf8, 0xfc, 0x90, + 0x21, 0x57, 0x6f, 0x4e, 0x7b, 0x36, 0x19, 0x4a, 0xd5, 0x79, 0x61, 0xd5, + 0x26, 0x72, 0x07, 0x0b, 0xa6, 0x4f, 0xff, 0x89, 0x5a, 0x45, 0x95, 0xb8, + 0xfe, 0xf9, 0xea, 0xa3, 0xe3, 0x77, 0x4e, 0x5b, 0x0f, 0x6f, 0x2a, 0x64, + 0x88, 0x6a, 0xc3, 0x10, 0xf3, 0x64, 0x4c, 0xc3, 0xe6, 0x97, 0x47, 0x57, + 0x34, 0x9a, 0xca, 0xc6, 0x12, 0x14, 0xf4, 0x0c, 0xaa, 0x77, 0x31, 0x8e, + 0x7d, 0x59, 0xf2, 0x43, 0x55, 0xf2, 0x6f, 0x18, 0x24, 0x57, 0x5d, 0xc9, + 0x0b, 0x6d, 0xb4, 0x49, 0xe4, 0x39, 0x39, 0x72, 0x45, 0x14, 0x7d, 0xd3, + 0x91, 0x49, 0xb6, 0x77, 0xa3, 0xd9, 0xb9, 0x25, 0xc9, 0xeb, 0x2f, 0x4b, + 0x7e, 0xdf, 0xe3, 0x7d, 0x63, 0x1d, 0x4b, 0x92, 0xdb, 0xe7, 0x77, 0xd5, + 0xf0, 0xbb, 0x53, 0xd4, 0x28, 0x52, 0x41, 0xb6, 0xd9, 0xd6, 0x24, 0xdf, + 0x59, 0x28, 0x29, 0x34, 0x8b, 0xe7, 0x00, 0xad, 0x3b, 0x94, 0xf7, 0x1c, + 0x52, 0x15, 0x5b, 0x26, 0xbf, 0x28, 0xd1, 0xaf, 0x2b, 0x1a, 0x9e, 0xb3, + 0x52, 0xad, 0xbf, 0x96, 0x8e, 0x53, 0xa4, 0x36, 0xd6, 0xd2, 0x2c, 0xf2, + 0xda, 0x12, 0x7b, 0xcf, 0x59, 0x10, 0x32, 0xcd, 0xe2, 0x99, 0xc4, 0x77, + 0x13, 0xfd, 0x34, 0xf2, 0x2a, 0x7b, 0xdb, 0x0e, 0xe0, 0x1b, 0xeb, 0xc4, + 0x58, 0x5e, 0xbc, 0x0e, 0x13, 0xeb, 0xb0, 0xa9, 0xd3, 0x5b, 0xc6, 0x3e, + 0xe6, 0x4a, 0x4d, 0xd2, 0xa9, 0x13, 0xaf, 0x7d, 0x92, 0x02, 0xa1, 0x50, + 0x70, 0x4c, 0x23, 0xf7, 0x9c, 0x8a, 0xf2, 0x21, 0x6a, 0x09, 0x09, 0x7d, + 0x3a, 0x29, 0x7e, 0x39, 0xb4, 0xeb, 0xa8, 0x2f, 0x50, 0x50, 0x3c, 0x28, + 0xc9, 0xd5, 0xef, 0xa1, 0x7e, 0x4e, 0x34, 0xe9, 0xbb, 0x78, 0x4b, 0x28, + 0x1f, 0xe4, 0xf1, 0x50, 0x96, 0x48, 0xb1, 0x49, 0x78, 0xa1, 0x49, 0xed, + 0x30, 0xb3, 0xe5, 0xfa, 0xa4, 0xae, 0x15, 0xee, 0xc5, 0x0e, 0xfd, 0x7a, + 0x75, 0x6a, 0x08, 0x6a, 0xa9, 0x55, 0xf4, 0xe9, 0xd9, 0xa2, 0x06, 0x9c, + 0xdc, 0x18, 0xcf, 0x97, 0xb8, 0x9e, 0xff, 0x50, 0x6f, 0x92, 0x52, 0xb5, + 0x85, 0x4f, 0x5f, 0xa6, 0xa4, 0x8d, 0xf7, 0x29, 0x63, 0x6f, 0xa7, 0xd2, + 0x72, 0x51, 0x78, 0x37, 0xbe, 0x48, 0x6e, 0xec, 0x1f, 0x03, 0xdf, 0x02, + 0x7b, 0xd4, 0x81, 0x75, 0xe0, 0xca, 0xd4, 0x2a, 0x19, 0x64, 0x2d, 0xae, + 0xa1, 0xe5, 0x6f, 0x5d, 0x05, 0x7e, 0x67, 0xdc, 0xd4, 0xd4, 0x8e, 0x71, + 0xfe, 0x23, 0xd6, 0xd9, 0x12, 0x06, 0xf0, 0x6e, 0x9c, 0x8f, 0xa2, 0x37, + 0x9d, 0x28, 0xd2, 0xab, 0x76, 0xf9, 0x16, 0x2d, 0x94, 0x34, 0x9a, 0x17, + 0x78, 0xc3, 0x8f, 0x36, 0x7c, 0xa5, 0x65, 0xeb, 0xc9, 0x78, 0x86, 0xbf, + 0xcb, 0x12, 0x96, 0x42, 0x1f, 0x74, 0xdf, 0x63, 0x7f, 0x94, 0x97, 0x62, + 0x9b, 0x28, 0xda, 0x5c, 0xfc, 0x34, 0x9b, 0xef, 0xa7, 0x36, 0x51, 0x54, + 0xaf, 0xf0, 0xbc, 0x16, 0xf6, 0xcc, 0x5c, 0x25, 0xaa, 0x0f, 0x1c, 0xa3, + 0xd9, 0xc5, 0xfa, 0x6c, 0xbc, 0x07, 0x25, 0xec, 0xc1, 0x2a, 0x9b, 0x92, + 0x41, 0x81, 0x1d, 0xbd, 0x00, 0x7e, 0xb8, 0xbe, 0x6d, 0xbd, 0xef, 0x2b, + 0x05, 0xda, 0x72, 0xf2, 0xd4, 0x09, 0x4b, 0x14, 0x84, 0x1d, 0xf2, 0x42, + 0x19, 0x73, 0x14, 0x68, 0xd3, 0x7e, 0x18, 0xd5, 0x1d, 0x07, 0x7e, 0x21, + 0xb6, 0x2b, 0xd5, 0x69, 0x1a, 0xed, 0x0b, 0x62, 0x8d, 0x1c, 0x60, 0x21, + 0xc3, 0x37, 0xb3, 0xf1, 0x77, 0x10, 0x3a, 0x68, 0xa7, 0x96, 0x5c, 0xb1, + 0x44, 0x40, 0x56, 0xc9, 0x53, 0x48, 0xc8, 0x55, 0x81, 0x3e, 0x2d, 0xaa, + 0x85, 0x06, 0xed, 0x28, 0x97, 0x63, 0x7e, 0xb7, 0x7b, 0x3b, 0xd1, 0x9d, + 0xa3, 0x25, 0xba, 0x1b, 0x16, 0xe9, 0x76, 0x48, 0x72, 0xd3, 0x01, 0x37, + 0x8a, 0x82, 0xde, 0x0a, 0x47, 0xf7, 0xf2, 0x1b, 0xec, 0x25, 0x38, 0xa2, + 0x40, 0x83, 0xab, 0xce, 0x3d, 0x30, 0xc8, 0x02, 0x46, 0x2d, 0xec, 0x3d, + 0x7b, 0xf3, 0xbe, 0x76, 0xa6, 0x57, 0x6d, 0xeb, 0x87, 0x3e, 0xa3, 0x76, + 0x4d, 0x43, 0xed, 0x5e, 0x7f, 0x0c, 0x30, 0x86, 0xa0, 0xab, 0xd0, 0x93, + 0x0c, 0xbf, 0xcc, 0x6c, 0x1b, 0xd4, 0xef, 0xe6, 0xc8, 0xdc, 0x54, 0xa9, + 0xd9, 0x2b, 0x92, 0x33, 0x6f, 0x99, 0x24, 0xcb, 0x45, 0x99, 0x54, 0x9a, + 0xd9, 0x8c, 0x68, 0x09, 0xeb, 0xb8, 0x6f, 0xff, 0x48, 0xa7, 0xa9, 0xc0, + 0xd1, 0x89, 0xfb, 0x18, 0x34, 0x73, 0xcb, 0x90, 0xfc, 0x1e, 0xef, 0x83, + 0x7d, 0x6e, 0xa4, 0x3e, 0x57, 0x25, 0xef, 0x46, 0x8e, 0x66, 0x37, 0xfe, + 0x11, 0x79, 0x36, 0x7c, 0x0d, 0x9e, 0xaf, 0x56, 0xbe, 0xa0, 0xd0, 0x04, + 0xea, 0x36, 0xb9, 0xed, 0x61, 0x5a, 0xcf, 0x63, 0x44, 0x91, 0xe7, 0x3c, + 0x4b, 0x1e, 0xf3, 0xff, 0x3c, 0xdb, 0xe4, 0x68, 0x66, 0x83, 0x75, 0x83, + 0xf7, 0x26, 0x97, 0x79, 0x6d, 0x07, 0xa8, 0x89, 0x1d, 0x35, 0xcb, 0x45, + 0xf8, 0x41, 0x8e, 0x35, 0xd2, 0xc4, 0x8e, 0x65, 0x7b, 0x02, 0x6f, 0x9e, + 0xef, 0xac, 0x92, 0xf0, 0x9d, 0xe3, 0x46, 0x9e, 0x7c, 0xe0, 0xab, 0x62, + 0x3d, 0x6b, 0x34, 0x57, 0x5a, 0x8f, 0xdb, 0x50, 0x37, 0xe0, 0x36, 0xb1, + 0xa7, 0x0d, 0xe5, 0x41, 0xb6, 0x06, 0x70, 0xda, 0x6e, 0x63, 0x16, 0x2d, + 0xde, 0x6b, 0xdd, 0xe1, 0xfe, 0xdc, 0xb7, 0x55, 0xd6, 0xc8, 0x2a, 0x6f, + 0x62, 0xf4, 0x7e, 0x17, 0xfb, 0xbd, 0xce, 0xb1, 0xc8, 0x36, 0xff, 0x4a, + 0xdc, 0x7f, 0x16, 0x7b, 0x9e, 0x5b, 0x6c, 0x73, 0xdb, 0x40, 0x23, 0x7b, + 0xa3, 0x25, 0x54, 0xf8, 0x5f, 0x86, 0xf3, 0xfd, 0x1f, 0xff, 0x2b, 0xd2, + 0xaa, 0xe0, 0x74, 0xa5, 0x00, 0x7c, 0x2c, 0xb3, 0x0d, 0xbd, 0xdb, 0x18, + 0x37, 0x70, 0x14, 0xd8, 0x25, 0x38, 0x71, 0xbf, 0xa5, 0x6e, 0x44, 0xed, + 0x78, 0xae, 0x2b, 0x3c, 0x17, 0x62, 0x92, 0xbd, 0xf8, 0x07, 0x70, 0xa3, + 0x49, 0x79, 0x9a, 0xdf, 0xce, 0xd3, 0x85, 0x41, 0x9e, 0x66, 0xae, 0xe9, + 0xf0, 0x43, 0x14, 0x75, 0x2a, 0xac, 0x51, 0xe0, 0x6d, 0x73, 0x3f, 0xab, + 0xa4, 0xc8, 0xbc, 0x0e, 0xb4, 0x6f, 0x13, 0xad, 0x0d, 0x74, 0xf8, 0x4d, + 0x1d, 0x19, 0x5b, 0xa6, 0x97, 0x7f, 0x46, 0xf4, 0xf2, 0x80, 0x6d, 0x79, + 0xfc, 0xc4, 0xa6, 0x89, 0x3d, 0xcb, 0xc0, 0xfc, 0xc2, 0x40, 0x46, 0xbc, + 0x40, 0x3c, 0xed, 0x7b, 0x88, 0x93, 0x35, 0x3c, 0x4b, 0x88, 0x9d, 0x8c, + 0x0d, 0xc7, 0x91, 0x5d, 0xe0, 0xb3, 0x8c, 0xb6, 0xb3, 0xa8, 0x4b, 0xf4, + 0xae, 0xd8, 0x3a, 0xd5, 0x9c, 0x49, 0x6a, 0x67, 0xb1, 0x4a, 0x70, 0xac, + 0x3a, 0x08, 0x4e, 0x1d, 0x40, 0xfc, 0xf9, 0x9d, 0x32, 0x1e, 0xab, 0x10, + 0xd3, 0x8a, 0x87, 0x11, 0x9b, 0xfa, 0xa8, 0xe7, 0xf1, 0x6e, 0xe1, 0x7d, + 0x00, 0xe5, 0xc3, 0xe8, 0x3b, 0x1a, 0xa7, 0x32, 0xbb, 0x27, 0xc5, 0x28, + 0xf0, 0x6e, 0xc3, 0x40, 0x7f, 0x13, 0xba, 0x61, 0x7f, 0xe7, 0x10, 0x3f, + 0xd8, 0xe7, 0x39, 0xf8, 0x54, 0xc7, 0xdc, 0x82, 0x66, 0xb7, 0xa9, 0xa5, + 0xa4, 0xf1, 0xcb, 0x1f, 0xc6, 0xaf, 0x52, 0xcc, 0x83, 0x20, 0x14, 0xb0, + 0x61, 0xfd, 0x66, 0x7a, 0x65, 0xec, 0xc8, 0xf5, 0xa0, 0x65, 0x4f, 0x89, + 0xa2, 0x55, 0xa7, 0x40, 0x4d, 0xe0, 0xee, 0x42, 0xc3, 0x4d, 0x68, 0xd8, + 0x1f, 0xd1, 0xb0, 0xff, 0x3f, 0x35, 0x0c, 0x7d, 0x42, 0x23, 0xb7, 0xc1, + 0xa9, 0xb7, 0x7a, 0xfb, 0xe9, 0x99, 0xb5, 0xcc, 0x9a, 0x36, 0xe9, 0xce, + 0xd1, 0xa7, 0xd5, 0x74, 0x49, 0x7e, 0x4a, 0x4d, 0xb7, 0x58, 0xd3, 0x2a, + 0x6b, 0xba, 0xb8, 0x57, 0xd3, 0xd3, 0x18, 0x23, 0xd1, 0xe6, 0x19, 0xb5, + 0x48, 0xda, 0x3c, 0xf0, 0xd8, 0xc8, 0x93, 0x72, 0xed, 0x31, 0xef, 0x98, + 0xcb, 0xfe, 0x00, 0xff, 0xb6, 0x35, 0xb4, 0x49, 0xe3, 0xf5, 0x88, 0x81, + 0x6a, 0xd5, 0x2a, 0xad, 0xc5, 0x7d, 0x54, 0xd2, 0xe1, 0xff, 0xd7, 0x8f, + 0x5a, 0xa6, 0x29, 0x8f, 0x6a, 0x1f, 0xea, 0xdf, 0x88, 0xae, 0x68, 0x55, + 0x9e, 0xa7, 0x65, 0x82, 0xf3, 0xe6, 0x4f, 0x80, 0x55, 0xbb, 0xcb, 0x7c, + 0xb7, 0x45, 0x3d, 0xe6, 0x19, 0xca, 0xd0, 0x84, 0x06, 0xde, 0xe6, 0xd0, + 0x4f, 0xdd, 0x48, 0x74, 0x74, 0x1b, 0xe3, 0x6e, 0x75, 0x99, 0x67, 0x06, + 0xe9, 0xd7, 0xed, 0xd2, 0x85, 0x38, 0x06, 0xcf, 0x8a, 0x25, 0x62, 0x0d, + 0xf2, 0xb9, 0x88, 0xf6, 0x41, 0x8e, 0x94, 0x58, 0xf7, 0x13, 0xa9, 0xee, + 0x9f, 0x87, 0xaf, 0x26, 0x50, 0x66, 0xed, 0x1f, 0x4e, 0xb5, 0x3f, 0x85, + 0x37, 0xd7, 0xad, 0xa8, 0x09, 0x87, 0xc0, 0xc7, 0x0d, 0xc6, 0x37, 0x8f, + 0x58, 0xc7, 0xf3, 0xff, 0x33, 0x5a, 0xb5, 0x19, 0x63, 0xdb, 0xfc, 0x01, + 0xcd, 0x41, 0x7f, 0xa8, 0xdf, 0xe6, 0xbe, 0x6c, 0x93, 0xf5, 0x15, 0x69, + 0xdf, 0x0f, 0xf7, 0xf4, 0x45, 0xfd, 0x36, 0xf7, 0x63, 0x7d, 0x1c, 0x22, + 0xe5, 0x3a, 0x9f, 0xdb, 0x1e, 0xeb, 0x03, 0x76, 0x35, 0xd4, 0x71, 0x6e, + 0xc1, 0xf6, 0x7c, 0x86, 0xf3, 0x3a, 0x39, 0xef, 0xe0, 0x73, 0x7e, 0xcf, + 0x79, 0x3e, 0xd4, 0xc8, 0x19, 0xf0, 0xfe, 0x3b, 0xea, 0x27, 0x35, 0xb2, + 0x02, 0x4d, 0x5c, 0x54, 0x13, 0x8d, 0xbc, 0x86, 0xf7, 0x19, 0x94, 0x57, + 0xf6, 0x68, 0x24, 0xb3, 0x7b, 0xf2, 0x39, 0x1e, 0xf4, 0x4a, 0xf1, 0x99, + 0xcb, 0xf3, 0x29, 0x1b, 0xd4, 0xd2, 0x52, 0x3d, 0xd4, 0x87, 0x7a, 0x98, + 0x40, 0xcc, 0xc8, 0xa5, 0x5c, 0xc7, 0xdb, 0xfe, 0x48, 0xf1, 0x1d, 0x4b, + 0xb4, 0x89, 0xb5, 0x31, 0x7a, 0x9e, 0xfd, 0xbf, 0xf4, 0x41, 0xe0, 0x51, + 0x3c, 0x37, 0x72, 0x11, 0x3e, 0x17, 0xa2, 0xe8, 0x15, 0x07, 0xed, 0x59, + 0x4e, 0x12, 0x63, 0x9f, 0xc3, 0xd9, 0xcb, 0x78, 0x20, 0x0f, 0xb4, 0x67, + 0xa1, 0x07, 0x8e, 0x05, 0xbb, 0xd1, 0x96, 0xed, 0xa1, 0xae, 0x06, 0xff, + 0x33, 0x26, 0xcb, 0xd2, 0x52, 0xdf, 0x60, 0x3b, 0xe8, 0x6d, 0xbf, 0x5c, + 0x4c, 0x87, 0xae, 0x1e, 0xe3, 0xc4, 0x3c, 0x6a, 0x8e, 0xe0, 0xd4, 0x88, + 0x71, 0xda, 0x19, 0xe2, 0xd4, 0x4c, 0x71, 0x6a, 0xc6, 0x38, 0x3d, 0x48, + 0x71, 0xfa, 0xf3, 0x13, 0x70, 0xda, 0x79, 0x0a, 0x9c, 0x0c, 0xda, 0xb2, + 0x4b, 0x38, 0x6f, 0xf5, 0x38, 0x77, 0xbd, 0xef, 0xec, 0x97, 0x7b, 0xb1, + 0xdf, 0xc7, 0xb0, 0x8a, 0x18, 0xab, 0x2d, 0x1a, 0xcd, 0x43, 0x2c, 0xf3, + 0x1e, 0x15, 0x70, 0x6e, 0xe4, 0xe9, 0xea, 0x9e, 0x5c, 0x24, 0x00, 0x4e, + 0xb5, 0x14, 0xa7, 0xab, 0xc0, 0xa9, 0x96, 0xe2, 0xb4, 0x3e, 0x82, 0xd3, + 0xfa, 0x18, 0x4e, 0x1c, 0x53, 0x2a, 0xc6, 0x7a, 0x37, 0xc3, 0x28, 0xc3, + 0x47, 0xa7, 0x9b, 0x62, 0x0a, 0xfb, 0x3f, 0x4e, 0xed, 0x9f, 0xaa, 0x9c, + 0xff, 0x02, 0xbb, 0x97, 0x54, 0x39, 0x3e, 0x17, 0xf8, 0xfb, 0x71, 0xbe, + 0x82, 0xb9, 0x5c, 0xcf, 0xe1, 0x3d, 0x21, 0xcf, 0xb5, 0x47, 0x63, 0xd1, + 0x07, 0x88, 0x45, 0x5c, 0xc7, 0xfd, 0x54, 0xa9, 0x06, 0xcd, 0x2b, 0xc8, + 0xe1, 0xfd, 0x61, 0x0e, 0x9f, 0xf8, 0xe1, 0x6a, 0x9a, 0xc3, 0x6f, 0xd9, + 0x9c, 0xc3, 0x9f, 0xd0, 0x68, 0x62, 0x39, 0xc5, 0x93, 0x79, 0x3d, 0x89, + 0xb6, 0xb3, 0x31, 0xee, 0x6d, 0xc4, 0xf2, 0x55, 0xf8, 0xa0, 0x19, 0xf3, + 0x13, 0x79, 0x57, 0xca, 0x5d, 0xe4, 0xbb, 0xe4, 0x87, 0x09, 0x4f, 0x3f, + 0xdb, 0x5c, 0xec, 0xef, 0x88, 0xd9, 0x46, 0x43, 0xc5, 0x1d, 0xe0, 0x6e, + 0x18, 0xc7, 0xea, 0x73, 0x41, 0x97, 0x5a, 0x47, 0xaa, 0x57, 0x22, 0xe0, + 0xee, 0x7e, 0xfd, 0x34, 0x9f, 0x39, 0xf9, 0x45, 0xaf, 0x82, 0xfa, 0x81, + 0x41, 0xc8, 0x83, 0x70, 0xa7, 0xa1, 0x96, 0x77, 0x5a, 0x42, 0xbe, 0x83, + 0x32, 0x6c, 0x82, 0x70, 0xba, 0x21, 0x57, 0x4b, 0xe0, 0x43, 0x8b, 0x5c, + 0xac, 0xd3, 0x0d, 0xe3, 0x7b, 0x4d, 0x43, 0xa9, 0x1a, 0xc8, 0x37, 0xc9, + 0xc0, 0x99, 0x0f, 0x9f, 0x98, 0x46, 0x7b, 0x80, 0x9c, 0x08, 0x79, 0x80, + 0xb7, 0x08, 0xbf, 0x1c, 0x03, 0x76, 0xa1, 0x0a, 0xdb, 0x6f, 0xe9, 0xc9, + 0x9d, 0x88, 0xc8, 0x8b, 0xfd, 0xf5, 0x71, 0xca, 0x91, 0x38, 0xe7, 0x92, + 0x6a, 0x3d, 0x32, 0x9b, 0x0e, 0xb8, 0x8e, 0x33, 0xa5, 0x13, 0x72, 0x5e, + 0x7d, 0xcc, 0x90, 0xaf, 0x71, 0x3c, 0x7f, 0x00, 0x1f, 0xe2, 0x7b, 0x9b, + 0xcf, 0x19, 0x85, 0x73, 0x73, 0xdc, 0x7d, 0xca, 0x88, 0x37, 0x34, 0x89, + 0xd8, 0x87, 0xd8, 0x3b, 0xcd, 0x58, 0xb9, 0xc9, 0x19, 0xc4, 0xe3, 0x1d, + 0x97, 0x93, 0x79, 0xfe, 0xa4, 0x25, 0x1c, 0xc6, 0x7d, 0x07, 0xfe, 0x5b, + 0xed, 0x39, 0x1c, 0x73, 0x3f, 0xaf, 0xd0, 0x43, 0x8a, 0x39, 0x29, 0x4e, + 0x20, 0x16, 0x9f, 0x86, 0x8d, 0x1b, 0xeb, 0x31, 0xc9, 0xbd, 0x32, 0x9b, + 0x0f, 0xf7, 0x8c, 0xf1, 0x17, 0x65, 0xbc, 0xec, 0x82, 0xd3, 0x95, 0x74, + 0xbe, 0x51, 0x8e, 0x2c, 0x20, 0xe5, 0x79, 0xa0, 0x0d, 0xf3, 0xb7, 0xa2, + 0x8e, 0x7e, 0xbc, 0x46, 0xd6, 0x25, 0xdb, 0x1c, 0xd1, 0xc6, 0xc7, 0x99, + 0xdd, 0x67, 0x8c, 0xea, 0xc8, 0x18, 0x45, 0xde, 0x9b, 0x68, 0x3a, 0xcf, + 0xa4, 0xf7, 0x0c, 0x8e, 0x2d, 0x02, 0x3a, 0x95, 0x9f, 0x93, 0xb1, 0x0f, + 0x0f, 0x7b, 0xf6, 0xe3, 0xfa, 0x5f, 0xe9, 0xe3, 0xe3, 0xfe, 0x56, 0x4d, + 0xca, 0xc7, 0x12, 0x6e, 0xda, 0x78, 0x87, 0x0f, 0x46, 0xd6, 0xae, 0xed, + 0x33, 0xef, 0xd7, 0x38, 0x5d, 0x43, 0xbc, 0x21, 0x57, 0xc1, 0x1d, 0xcc, + 0x27, 0x7c, 0x87, 0xaf, 0x67, 0x3e, 0x04, 0x6f, 0xe8, 0x5c, 0x3b, 0xe5, + 0x8b, 0x9c, 0xf0, 0x85, 0xf3, 0xba, 0xc5, 0x55, 0xf0, 0xa5, 0x0d, 0xbe, + 0xc0, 0xae, 0xa1, 0x55, 0xa7, 0xc1, 0x05, 0x8e, 0x4d, 0x28, 0x87, 0xcc, + 0x1d, 0xe6, 0x0a, 0xf3, 0xe6, 0x31, 0x5f, 0x5e, 0xe9, 0x1a, 0xc6, 0xe6, + 0xa7, 0x70, 0xe5, 0x8d, 0x98, 0x2b, 0xcc, 0xd9, 0x24, 0x7e, 0x74, 0x80, + 0x55, 0x90, 0xc6, 0x8f, 0x00, 0xf1, 0xa3, 0xc6, 0xf9, 0x4f, 0x1c, 0x0b, + 0x12, 0xfd, 0xac, 0x41, 0x3f, 0x35, 0x85, 0xf3, 0x23, 0xd6, 0x0e, 0xdb, + 0xb1, 0x7e, 0xd8, 0xae, 0x90, 0xda, 0x8d, 0xc7, 0x91, 0x76, 0xcf, 0x32, + 0xb3, 0x38, 0xd2, 0x86, 0x76, 0x3a, 0xa9, 0x8e, 0xda, 0xa9, 0x8e, 0xd0, + 0xa7, 0xa5, 0x54, 0xf8, 0x4c, 0xb0, 0x4c, 0x1f, 0xf1, 0xa3, 0x13, 0x8f, + 0xd9, 0xa2, 0xe4, 0x2e, 0xc3, 0xda, 0xe6, 0xb8, 0x3b, 0x12, 0x6f, 0xd3, + 0x7b, 0x6e, 0x23, 0xbe, 0xe7, 0x7e, 0x45, 0x1f, 0x8f, 0xb7, 0x38, 0x6b, + 0xe2, 0x7b, 0xee, 0x29, 0x9d, 0xef, 0xb9, 0x01, 0x7d, 0x49, 0x1f, 0xbd, + 0xe7, 0x06, 0x63, 0xf7, 0xdc, 0xcc, 0x96, 0xeb, 0xf7, 0x8b, 0xbb, 0x99, + 0x4f, 0x38, 0xf6, 0x32, 0x9f, 0xf6, 0xcb, 0x15, 0xb3, 0x3e, 0x1c, 0x93, + 0x58, 0xef, 0x1c, 0xcb, 0x92, 0xdc, 0xec, 0x6e, 0x98, 0xe9, 0xe2, 0x55, + 0xcc, 0x83, 0x72, 0x6f, 0x3f, 0x5d, 0x18, 0xa9, 0x2e, 0x26, 0x13, 0x9b, + 0xde, 0xa8, 0x36, 0x5e, 0xd5, 0xc7, 0xb5, 0x91, 0x8d, 0x93, 0x69, 0x23, + 0x19, 0x73, 0x47, 0x29, 0xe1, 0x0c, 0x2c, 0x23, 0x1e, 0x09, 0xbe, 0xa3, + 0x21, 0x5e, 0x54, 0xf3, 0xb8, 0xa7, 0x14, 0x78, 0xec, 0x76, 0xf8, 0x2c, + 0x35, 0x8a, 0x8c, 0x0b, 0xaf, 0xff, 0x61, 0x7c, 0x7f, 0xc0, 0xba, 0x0b, + 0x01, 0xff, 0xfe, 0xf1, 0x09, 0x3e, 0xbe, 0x06, 0x3e, 0x66, 0xfb, 0x19, + 0xad, 0xbf, 0x34, 0x52, 0x5f, 0x4e, 0x31, 0x4f, 0x7c, 0x7e, 0x2f, 0xd5, + 0xc8, 0x26, 0x72, 0xb7, 0xfb, 0xc8, 0x8b, 0xde, 0x44, 0xfc, 0x0e, 0x06, + 0x1f, 0x47, 0xf7, 0x8a, 0x2a, 0x75, 0x86, 0x36, 0xbf, 0xc0, 0xba, 0x2d, + 0x71, 0x13, 0x5f, 0x6f, 0x0c, 0xb2, 0xb1, 0xb9, 0x9d, 0xeb, 0xfe, 0x8d, + 0xf3, 0x19, 0x79, 0xdf, 0xb0, 0xef, 0xfb, 0x11, 0xe7, 0xbb, 0x77, 0x81, + 0xc5, 0x3b, 0xe1, 0x34, 0xfd, 0x1e, 0x1c, 0x7b, 0x3b, 0xce, 0x79, 0x93, + 0x5c, 0x17, 0xfe, 0xc3, 0x99, 0xc7, 0x67, 0xbd, 0xf7, 0x39, 0x99, 0x2e, + 0xd3, 0x57, 0x1d, 0xae, 0x93, 0xa9, 0x7e, 0x2a, 0x8a, 0x2e, 0xe2, 0xdc, + 0x5f, 0x19, 0x3b, 0xf7, 0x71, 0x07, 0x3c, 0xc9, 0xf9, 0x7f, 0x96, 0xf3, + 0xef, 0x46, 0x33, 0xf3, 0xd6, 0x4d, 0x97, 0x5c, 0xa9, 0xde, 0xe7, 0x7c, + 0x6c, 0x98, 0x8b, 0x11, 0x1d, 0x7a, 0x14, 0xc9, 0xf3, 0x7c, 0x36, 0xbd, + 0x9b, 0xfa, 0x1c, 0x6d, 0x37, 0x1e, 0xe1, 0x1e, 0x53, 0x8b, 0x7f, 0x17, + 0x72, 0xfb, 0x3c, 0x0f, 0x97, 0xf1, 0x0e, 0x39, 0x47, 0x78, 0xd2, 0x6f, + 0x35, 0x2a, 0xf0, 0xb5, 0xcc, 0x75, 0x85, 0xe2, 0x7b, 0x21, 0xee, 0x6e, + 0x3f, 0x6f, 0x53, 0x12, 0x3b, 0x6a, 0xce, 0x39, 0xac, 0x05, 0x98, 0x88, + 0x06, 0x30, 0x9e, 0x47, 0xac, 0xb2, 0xcc, 0x93, 0x72, 0xf2, 0x5b, 0xd5, + 0x1a, 0xc6, 0x56, 0x4e, 0x72, 0x2e, 0xf9, 0x51, 0xb4, 0x36, 0x88, 0xcf, + 0x44, 0x87, 0xb9, 0xe6, 0x87, 0x07, 0x65, 0x7e, 0xbb, 0x21, 0x7f, 0xeb, + 0x98, 0xc7, 0x7c, 0x02, 0x0f, 0x8b, 0xa2, 0x76, 0xc3, 0x14, 0xf5, 0x9e, + 0x29, 0x96, 0x7a, 0x32, 0x54, 0x52, 0xc8, 0xd1, 0x14, 0xe7, 0x08, 0x3a, + 0xd1, 0x73, 0x58, 0xcb, 0x2d, 0x53, 0xf8, 0xc8, 0xa3, 0xbe, 0xad, 0x58, + 0x62, 0x85, 0x76, 0xb1, 0xc7, 0x47, 0x51, 0x72, 0xa7, 0x35, 0x45, 0x6d, + 0x38, 0xf7, 0x23, 0xcc, 0xcd, 0x6b, 0x62, 0x2d, 0xf3, 0x79, 0xb6, 0x2c, + 0x9d, 0x83, 0x8f, 0xce, 0xf7, 0x77, 0x11, 0x43, 0xf9, 0x3c, 0xcb, 0x23, + 0xe6, 0x59, 0x26, 0x5f, 0xf6, 0xef, 0x62, 0xff, 0xef, 0xf4, 0x80, 0x0f, + 0x72, 0xc7, 0xb7, 0x87, 0x79, 0x1a, 0x63, 0x58, 0x06, 0x17, 0xd9, 0x3e, + 0x8a, 0x82, 0xc5, 0x38, 0x47, 0xc1, 0x5a, 0xe6, 0xca, 0xb7, 0x90, 0xa7, + 0xd7, 0x69, 0xa1, 0x5c, 0x8f, 0xdf, 0x11, 0x72, 0x12, 0xfe, 0x5d, 0xc0, + 0x12, 0x4d, 0x7c, 0xd7, 0xd2, 0xef, 0x80, 0x73, 0xf8, 0x45, 0x1e, 0x83, + 0x73, 0x79, 0xd6, 0xe1, 0x7f, 0x01, 0x17, 0xc6, 0xf1, 0xb2, 0x84, 0x14, + 0x00, 0x00, 0x00 }; +static u32 bnx2_TPAT_b09FwData[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b09FwRodata[(0x0/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b09FwBss[(0x250/4) + 1] = { 0x0 }; +static u32 bnx2_TPAT_b09FwSbss[(0x34/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_tpat_fw_09 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x08000860, + + .text_addr = 0x08000800, + .text_len = 0x1480, + .text_index = 0x0, + .gz_text = bnx2_TPAT_b09FwText, + .gz_text_len = sizeof(bnx2_TPAT_b09FwText), + + .data_addr = 0x08001ca0, + .data_len = 0x0, + .data_index = 0x0, + .data = bnx2_TPAT_b09FwData, + + .sbss_addr = 0x08001ca0, + .sbss_len = 0x34, + .sbss_index = 0x0, + .sbss = bnx2_TPAT_b09FwSbss, + + .bss_addr = 0x08001ce0, + .bss_len = 0x250, + .bss_index = 0x0, + .bss = bnx2_TPAT_b09FwBss, + + .rodata_addr = 0x00000000, + .rodata_len = 0x0, + .rodata_index = 0x0, + .rodata = bnx2_TPAT_b09FwRodata, +}; + +static u8 bnx2_TXP_b09FwText[] = { + 0x1f, 0x8b, 0x08, 0x08, 0x51, 0xfe, 0x2f, 0x45, 0x00, 0x03, 0x74, 0x65, + 0x73, 0x74, 0x31, 0x2e, 0x62, 0x69, 0x6e, 0x00, 0xcd, 0x7b, 0x7f, 0x70, + 0x1b, 0xe7, 0x99, 0xde, 0xbb, 0x0b, 0x80, 0x04, 0x29, 0x8a, 0x5a, 0x31, + 0x30, 0x83, 0x38, 0xb4, 0x8d, 0x15, 0x17, 0x34, 0x6d, 0xf2, 0x1c, 0x58, + 0xe5, 0xf9, 0xd8, 0x06, 0xb5, 0xd7, 0xc0, 0x92, 0xa2, 0x63, 0x26, 0x47, + 0xbb, 0xcc, 0x9d, 0x92, 0x51, 0x7d, 0x28, 0x48, 0x29, 0x6e, 0xe3, 0xb4, + 0xaa, 0xe3, 0x3f, 0x34, 0x4d, 0x5b, 0xc3, 0x00, 0x25, 0xcb, 0x2e, 0x44, + 0xd0, 0x16, 0x63, 0xa5, 0x33, 0x37, 0x53, 0x18, 0x80, 0x28, 0xe7, 0xba, + 0x24, 0xdc, 0xe4, 0x2e, 0xe9, 0x1f, 0xc9, 0x99, 0xa5, 0x6c, 0xc5, 0x6d, + 0xae, 0x33, 0xbe, 0x3f, 0xda, 0xa6, 0x37, 0xd7, 0x19, 0x8d, 0xfc, 0x23, + 0xce, 0x8f, 0xb9, 0xb8, 0x69, 0x7a, 0x56, 0x5b, 0xd9, 0xe8, 0xf3, 0x7c, + 0xbb, 0x4b, 0x82, 0x32, 0x15, 0x5b, 0xd7, 0x76, 0xa6, 0x9c, 0xc1, 0x10, + 0xfb, 0xed, 0xb7, 0xdf, 0xf7, 0xfe, 0x7e, 0xdf, 0xe7, 0xfd, 0x16, 0x71, + 0x91, 0x6e, 0xf1, 0xff, 0x76, 0xe3, 0x93, 0x38, 0x7a, 0xec, 0xb1, 0x3b, + 0xc6, 0xef, 0xd8, 0x2f, 0x72, 0xe7, 0x9d, 0xb2, 0x2b, 0xaa, 0xf3, 0xe6, + 0xdb, 0x21, 0x91, 0xdc, 0x4f, 0xe5, 0xaf, 0xfc, 0x87, 0xc7, 0x8d, 0x60, + 0x7d, 0x7e, 0x24, 0xaa, 0xa7, 0x5f, 0xcc, 0x64, 0x2c, 0x89, 0x86, 0xd2, + 0x33, 0x9f, 0x9d, 0xb3, 0x44, 0x6c, 0x77, 0x24, 0x91, 0x95, 0xf7, 0x5a, + 0x85, 0x58, 0x58, 0x38, 0x7e, 0x53, 0xfa, 0xca, 0xe3, 0xdf, 0xff, 0x2d, + 0xf3, 0x9d, 0x6a, 0x48, 0xa2, 0x46, 0x3a, 0x27, 0xc6, 0x90, 0x44, 0x07, + 0xf0, 0xcc, 0xef, 0xdf, 0x3a, 0xa5, 0x4b, 0x6f, 0xb0, 0x56, 0x5c, 0x16, + 0x2a, 0x6f, 0xb7, 0xbe, 0x7f, 0x6b, 0x4c, 0xfe, 0x55, 0xd3, 0x90, 0x17, + 0x9b, 0x61, 0x6d, 0xb2, 0xd2, 0x23, 0xa5, 0x8a, 0x2b, 0xc7, 0xcb, 0x05, + 0xc9, 0x36, 0x5f, 0x90, 0xe2, 0xb2, 0xd1, 0x9b, 0x39, 0xf7, 0x07, 0x52, + 0x5a, 0xee, 0xeb, 0xcd, 0x9e, 0x73, 0xa5, 0x58, 0x8e, 0xf7, 0x66, 0x9a, + 0x46, 0x6f, 0xf6, 0x4c, 0x0c, 0xd7, 0x7d, 0xbd, 0x99, 0x33, 0x66, 0x41, + 0xa4, 0x1f, 0x73, 0xe2, 0xbd, 0xd9, 0x8a, 0x99, 0x13, 0x19, 0x4c, 0xbd, + 0x22, 0x03, 0xbd, 0xd9, 0x66, 0x4d, 0x5b, 0x37, 0x34, 0x29, 0xfe, 0x86, + 0x18, 0xbd, 0xe9, 0xcb, 0xad, 0x4f, 0x58, 0x86, 0xec, 0xb5, 0x64, 0xcf, + 0x1e, 0x4b, 0x9e, 0x88, 0xa7, 0xa3, 0x92, 0x3f, 0xdd, 0x25, 0xb6, 0xe2, + 0xc9, 0x90, 0xfc, 0x99, 0x11, 0x63, 0x43, 0x22, 0x62, 0xc7, 0x82, 0xeb, + 0x56, 0x2b, 0x93, 0xfa, 0x02, 0xe5, 0x8a, 0xbd, 0xa4, 0x77, 0xb2, 0x29, + 0x92, 0xa9, 0x44, 0x25, 0x93, 0x7a, 0xaf, 0xe5, 0x3d, 0x13, 0xc5, 0xbe, + 0xe1, 0xde, 0x89, 0x4a, 0xab, 0xe5, 0xa4, 0xb0, 0x47, 0x2a, 0x78, 0x36, + 0x22, 0xd5, 0x98, 0x5d, 0x2d, 0xa5, 0x4c, 0xdd, 0xd3, 0x09, 0x79, 0xe4, + 0xb5, 0x2d, 0xba, 0xf5, 0xdb, 0x92, 0x8f, 0x49, 0xb5, 0x98, 0xba, 0x4b, + 0x9e, 0x4e, 0x19, 0x72, 0x12, 0xeb, 0x3d, 0x95, 0x82, 0x1c, 0xad, 0x63, + 0x5a, 0xa6, 0x69, 0xc6, 0x45, 0x7b, 0x5a, 0x32, 0x67, 0x06, 0x8d, 0xac, + 0x60, 0x6f, 0xab, 0x75, 0x4b, 0x26, 0x85, 0xfd, 0x46, 0xff, 0x67, 0xcb, + 0x8e, 0x99, 0xb9, 0xaa, 0x0c, 0x48, 0xb1, 0x32, 0x98, 0xfa, 0x13, 0xd1, + 0xa4, 0xd3, 0xa2, 0x7c, 0x5a, 0x72, 0x3f, 0xf6, 0xcd, 0x58, 0x18, 0x6f, + 0x8a, 0xad, 0x27, 0x23, 0xf2, 0x0f, 0x0c, 0x33, 0x91, 0x09, 0xf5, 0x4b, + 0xf1, 0x74, 0x27, 0xe8, 0xb4, 0xfb, 0x74, 0xcc, 0x3d, 0x30, 0x26, 0xb1, + 0x5d, 0x22, 0x5a, 0x28, 0x9d, 0xc4, 0xba, 0x22, 0x45, 0x77, 0x00, 0xcf, + 0x26, 0xc7, 0x7f, 0x2a, 0x7b, 0x24, 0xb1, 0x37, 0x2c, 0x25, 0xb7, 0x1b, + 0x72, 0x34, 0xa0, 0x83, 0xe4, 0xf8, 0x5f, 0x40, 0x29, 0xba, 0x95, 0x8c, + 0x1f, 0x93, 0x9c, 0x96, 0x6d, 0x76, 0x48, 0x29, 0x19, 0x95, 0x05, 0xd0, + 0xb1, 0x90, 0xfa, 0xa2, 0x96, 0x39, 0x77, 0x50, 0xcb, 0x9e, 0xc3, 0xbc, + 0x66, 0xdd, 0xb7, 0x35, 0x03, 0xeb, 0xe8, 0x52, 0x4c, 0x1e, 0xc4, 0xbd, + 0xa8, 0xcc, 0x61, 0xde, 0x1c, 0x78, 0x2a, 0x35, 0xf7, 0xc8, 0xfa, 0x6c, + 0xac, 0x37, 0x03, 0x1d, 0x16, 0x71, 0xff, 0xb7, 0x67, 0x34, 0x31, 0x2c, + 0x5b, 0x7e, 0x3c, 0x06, 0x1d, 0x9e, 0x81, 0xfe, 0xce, 0xc4, 0xe5, 0x78, + 0x45, 0x62, 0xba, 0x24, 0xe3, 0x79, 0x79, 0x41, 0xea, 0x2e, 0xf5, 0x0f, + 0x7d, 0x42, 0xdf, 0x45, 0x97, 0xcf, 0x41, 0x6f, 0x15, 0x07, 0xf2, 0x98, + 0x02, 0x0d, 0x0f, 0x6a, 0xf7, 0xd7, 0x67, 0xb5, 0x03, 0xcd, 0x1f, 0x6b, + 0xd2, 0x7d, 0x4c, 0xfb, 0x5c, 0xf3, 0x88, 0xe6, 0xcb, 0x1e, 0xba, 0x8b, + 0x8a, 0x3d, 0x13, 0x95, 0x95, 0xa6, 0xa7, 0xbb, 0x1a, 0xec, 0xd3, 0x36, + 0x6c, 0xe8, 0xe1, 0x6f, 0x6f, 0xce, 0x59, 0x69, 0xc6, 0x64, 0x01, 0xb4, + 0x1d, 0x6f, 0x72, 0xfe, 0xef, 0x41, 0x3f, 0x51, 0x71, 0x6f, 0xed, 0x91, + 0x1c, 0xc6, 0x8b, 0x67, 0xc4, 0xce, 0xa4, 0x74, 0x3c, 0xd3, 0x2b, 0x21, + 0xab, 0x1f, 0x9f, 0x6e, 0x99, 0xab, 0x77, 0xda, 0x21, 0x2b, 0x26, 0x73, + 0x4d, 0xca, 0x10, 0xff, 0x2b, 0x81, 0x1c, 0x49, 0x2b, 0xc7, 0xf9, 0x1c, + 0xc7, 0x0d, 0x8c, 0xb7, 0x8f, 0xd1, 0x2e, 0x7a, 0x41, 0x8f, 0x39, 0x2c, + 0x18, 0xcb, 0x57, 0x92, 0xc6, 0xe7, 0xf8, 0xbf, 0x49, 0xd9, 0x06, 0x32, + 0x0d, 0x63, 0xae, 0x2e, 0xf9, 0x3a, 0xf6, 0x39, 0x7d, 0xa5, 0x15, 0x19, + 0xc3, 0xb5, 0xf5, 0x4b, 0xc8, 0x92, 0xfb, 0x86, 0x41, 0x93, 0x2e, 0xb9, + 0x3a, 0xd7, 0xe2, 0x7d, 0x81, 0xee, 0x8b, 0x7b, 0x75, 0x19, 0x86, 0x7e, + 0x4d, 0xec, 0xd3, 0x85, 0x39, 0x3d, 0x90, 0x1f, 0x78, 0x3d, 0x87, 0xef, + 0xe0, 0x5d, 0xb7, 0x74, 0x3c, 0xdf, 0x29, 0x73, 0x29, 0xda, 0x0b, 0xe9, + 0xdc, 0x85, 0xb5, 0xbb, 0x64, 0xfe, 0x34, 0xe5, 0x01, 0xbb, 0xaa, 0xc4, + 0xa4, 0x74, 0xc6, 0x34, 0x1c, 0x31, 0x21, 0x1b, 0x1b, 0xf3, 0x3a, 0x25, + 0x67, 0xb4, 0x5a, 0x13, 0xa9, 0x11, 0xe3, 0x9b, 0xca, 0xce, 0x47, 0x8c, + 0xa4, 0x26, 0x85, 0x8e, 0xf4, 0x10, 0x64, 0x6b, 0x1e, 0x14, 0xe1, 0xf5, + 0x0f, 0xc4, 0x9e, 0xa5, 0xff, 0xc4, 0xb8, 0x17, 0xfc, 0xa9, 0x1f, 0xf4, + 0xd3, 0xe7, 0x06, 0xa0, 0x97, 0xb8, 0xf2, 0x83, 0x89, 0x1d, 0xfd, 0xc0, + 0x9c, 0xaa, 0x82, 0xdf, 0xe2, 0xb9, 0x30, 0xfd, 0x2f, 0x05, 0x73, 0x93, + 0x5d, 0x56, 0x14, 0xb6, 0x40, 0x5a, 0xc6, 0xb1, 0x7e, 0xab, 0xf5, 0xd9, + 0x94, 0x47, 0x53, 0xf1, 0x8c, 0x8d, 0x67, 0xc3, 0x90, 0xbb, 0xf9, 0x70, + 0x42, 0xed, 0x3f, 0xee, 0xef, 0x6f, 0xc8, 0x1c, 0xe8, 0x2e, 0x56, 0x42, + 0x92, 0x35, 0xb8, 0xc6, 0x9f, 0x71, 0x3c, 0xe7, 0xad, 0x05, 0xbb, 0x3d, + 0x35, 0x68, 0xdc, 0x07, 0x5f, 0xa2, 0x8f, 0x15, 0x57, 0x29, 0x63, 0xac, + 0x33, 0x46, 0x19, 0x1b, 0x8a, 0xc6, 0xcc, 0x19, 0xda, 0x91, 0x0c, 0x84, + 0x84, 0x76, 0x8e, 0x98, 0x01, 0xbb, 0x2a, 0xf9, 0x76, 0x95, 0x77, 0xa9, + 0xff, 0xbb, 0x7d, 0xff, 0xd4, 0x65, 0x28, 0x49, 0x7b, 0x7f, 0x5a, 0xb2, + 0xf0, 0xf1, 0x39, 0xec, 0x54, 0x07, 0x4f, 0xb5, 0xca, 0x20, 0x64, 0x15, + 0xf8, 0x1d, 0xf4, 0x3b, 0xfa, 0x6e, 0x2b, 0x88, 0x05, 0xc5, 0x0a, 0x7d, + 0xa6, 0x68, 0xe8, 0x52, 0xc0, 0x07, 0x76, 0x63, 0x99, 0xc3, 0x99, 0x90, + 0x39, 0x93, 0x03, 0x6d, 0xb0, 0x7b, 0xc9, 0xdc, 0x49, 0x7b, 0xc6, 0x9c, + 0xa6, 0xec, 0x0f, 0xfc, 0xac, 0xe6, 0x52, 0x4f, 0xdd, 0xd8, 0x37, 0xa0, + 0x29, 0x8c, 0x31, 0xae, 0x13, 0x85, 0xcd, 0x07, 0x36, 0x43, 0xfb, 0x33, + 0xed, 0x75, 0xe9, 0x90, 0xe1, 0x24, 0x62, 0xd9, 0x19, 0x1d, 0xfa, 0x1b, + 0x40, 0x4c, 0x09, 0xcb, 0x11, 0xc8, 0xea, 0x4b, 0x15, 0xd2, 0xe7, 0xc0, + 0xef, 0x10, 0xdb, 0xce, 0x4c, 0xc2, 0xcf, 0xa6, 0xb4, 0x09, 0xf8, 0xc4, + 0x67, 0xea, 0xa4, 0xa9, 0x25, 0xf4, 0x4b, 0xe7, 0x5c, 0x4e, 0x9b, 0x6c, + 0x1e, 0xd4, 0xa6, 0xce, 0xd1, 0x4f, 0xe8, 0x23, 0xa6, 0xf1, 0x80, 0x78, + 0x3c, 0x14, 0x9b, 0xaf, 0x68, 0xf4, 0xd5, 0xe2, 0xa9, 0x2e, 0xd0, 0xb1, + 0x0b, 0xf4, 0x18, 0xf0, 0x3d, 0xd8, 0x97, 0x65, 0xce, 0xd0, 0x66, 0x9c, + 0xa4, 0x95, 0xf8, 0xe7, 0xf2, 0x41, 0x39, 0x4c, 0x6c, 0xca, 0x61, 0x04, + 0x32, 0xd9, 0x2e, 0x87, 0x85, 0x0f, 0xca, 0xc1, 0x2e, 0x40, 0x0e, 0x0b, + 0x88, 0x43, 0x0b, 0x4d, 0xf2, 0xdc, 0x12, 0xfd, 0x4e, 0x81, 0x75, 0xca, + 0xbd, 0x7a, 0x9a, 0x36, 0x4a, 0x3f, 0x49, 0x26, 0x4a, 0x58, 0xa1, 0xe1, + 0xf6, 0x28, 0xdf, 0x98, 0x54, 0xb2, 0xf8, 0x30, 0x7e, 0xc9, 0xdf, 0x16, + 0xcf, 0x53, 0x75, 0xc6, 0x1b, 0xd8, 0x79, 0xd2, 0x32, 0xbe, 0x20, 0x5b, + 0x7c, 0xdf, 0xb7, 0xc5, 0x37, 0xf6, 0x09, 0x62, 0x10, 0x79, 0x0e, 0xe2, + 0x31, 0x6d, 0xe5, 0xa5, 0x56, 0xc8, 0xb2, 0xa0, 0x03, 0xda, 0x0b, 0x69, + 0x30, 0x8d, 0xcf, 0x0a, 0xfe, 0x23, 0x2e, 0xd0, 0x97, 0x72, 0x6a, 0x5e, + 0x87, 0xe4, 0xf6, 0x7a, 0xf3, 0xe7, 0x2a, 0xad, 0x5f, 0xe8, 0xe9, 0xf7, + 0x5b, 0x99, 0x31, 0xcb, 0xf7, 0xf1, 0xa8, 0x7c, 0xb9, 0x6e, 0xe6, 0x12, + 0x5a, 0x8f, 0x14, 0x6e, 0x40, 0x5c, 0xa9, 0xd0, 0x3f, 0xfa, 0xaf, 0x11, + 0xcb, 0x06, 0xfc, 0x58, 0xf6, 0x13, 0xc8, 0x9e, 0xb9, 0xe7, 0xf0, 0xfb, + 0xeb, 0x31, 0xfe, 0x4f, 0x1a, 0x33, 0xf2, 0x05, 0xe6, 0x9b, 0x3d, 0xba, + 0x8a, 0xdf, 0x16, 0x73, 0x41, 0x21, 0x9c, 0xee, 0x96, 0xc2, 0x5e, 0x29, + 0x84, 0xd2, 0xf4, 0x23, 0xfa, 0x46, 0x87, 0x4f, 0x77, 0x90, 0x3b, 0xf8, + 0x77, 0x4c, 0x17, 0x8b, 0x73, 0x90, 0x27, 0x2a, 0xe4, 0xe3, 0xbd, 0x40, + 0x27, 0x78, 0x46, 0x22, 0x9e, 0xcd, 0x4d, 0x23, 0x66, 0x52, 0xa6, 0xed, + 0xf6, 0xc2, 0x58, 0x2a, 0x09, 0xdd, 0x62, 0x2c, 0x15, 0x23, 0x94, 0x7e, + 0x50, 0xb3, 0xeb, 0x5f, 0xd4, 0x6c, 0xc8, 0xce, 0x86, 0xec, 0x6c, 0xc8, + 0x2e, 0x03, 0xd9, 0x65, 0x9b, 0xa4, 0x87, 0xb4, 0x78, 0xeb, 0x3b, 0xde, + 0xfa, 0xa0, 0xb3, 0x5f, 0xf2, 0xca, 0xc7, 0xc9, 0x2f, 0x62, 0xb2, 0x8a, + 0x07, 0x93, 0x9a, 0x17, 0x0f, 0xb8, 0xde, 0x14, 0x9e, 0xbf, 0x1b, 0x79, + 0xce, 0xd6, 0x75, 0x6b, 0x4b, 0x26, 0x0b, 0x6d, 0x32, 0x29, 0xb9, 0x94, + 0x11, 0xe7, 0xd3, 0x97, 0x5d, 0xe8, 0x3d, 0x90, 0xcb, 0x34, 0x68, 0xe8, + 0x24, 0xef, 0x3e, 0x1f, 0x5c, 0xbf, 0xcf, 0x5f, 0xff, 0xd3, 0x58, 0x93, + 0xbe, 0xbb, 0xd3, 0xbe, 0xdc, 0x93, 0xb9, 0xf4, 0xd7, 0xf1, 0x83, 0x5a, + 0x02, 0x31, 0xfa, 0x45, 0xf8, 0xda, 0xc5, 0x50, 0x5c, 0xbe, 0x7f, 0xeb, + 0x6b, 0xa8, 0x2f, 0xa4, 0x70, 0x63, 0xba, 0x95, 0x08, 0xa7, 0xdf, 0x6b, + 0x2d, 0x8c, 0x21, 0x7e, 0xa6, 0xcd, 0x78, 0x26, 0x34, 0x2a, 0x2f, 0x35, + 0x87, 0xe5, 0x3b, 0x4d, 0x4b, 0xfe, 0xa8, 0x99, 0x90, 0x3f, 0x6c, 0x0e, + 0xc8, 0xb7, 0x9b, 0x71, 0xf9, 0x56, 0x33, 0xa8, 0x45, 0xe2, 0xb4, 0xa5, + 0x5e, 0xa7, 0xb9, 0x53, 0x3d, 0x04, 0x3b, 0xc7, 0x5a, 0x99, 0xb1, 0x70, + 0x2e, 0x94, 0x56, 0x35, 0xc2, 0xcc, 0xd1, 0xf2, 0xe3, 0x2d, 0xdd, 0xb2, + 0x0a, 0xba, 0xde, 0x33, 0x6e, 0xdc, 0x25, 0x39, 0x3d, 0x8d, 0x31, 0x77, + 0x3c, 0xec, 0x94, 0xbb, 0x90, 0x5f, 0xa2, 0xa8, 0x65, 0x06, 0xa4, 0x80, + 0x75, 0x0b, 0xcd, 0x56, 0x6b, 0x29, 0xf5, 0x0f, 0x3f, 0x65, 0xfc, 0x8d, + 0x7f, 0xd9, 0x29, 0xbd, 0xdf, 0x5e, 0x37, 0x86, 0xfe, 0xbb, 0x5f, 0x0f, + 0xa1, 0xc6, 0xea, 0x57, 0x8b, 0xe7, 0xb4, 0xf4, 0xa8, 0x93, 0x70, 0x37, + 0x70, 0x5f, 0xa2, 0xfd, 0xd6, 0xcf, 0x51, 0x85, 0xc8, 0xee, 0x98, 0xc5, + 0x9a, 0x6b, 0x26, 0xfb, 0x79, 0xfc, 0xff, 0x58, 0x5a, 0xf6, 0xf4, 0xe1, + 0xff, 0xde, 0x34, 0x4c, 0x2a, 0xcd, 0x98, 0xac, 0xb5, 0xc5, 0x64, 0xd1, + 0x1c, 0xe4, 0xdf, 0x05, 0xf0, 0xe4, 0x40, 0x1e, 0xbf, 0xd3, 0x8c, 0x6a, + 0xd9, 0xd3, 0xfd, 0x52, 0xaa, 0x33, 0xaf, 0x71, 0x5e, 0xd4, 0xaf, 0x7b, + 0x78, 0xdd, 0x81, 0x6b, 0x41, 0xae, 0xf9, 0x94, 0x48, 0xaf, 0xf9, 0xa3, + 0xcf, 0x4b, 0xdd, 0xaf, 0x5b, 0x22, 0xb2, 0xac, 0x6c, 0x8c, 0xe3, 0xaf, + 0x65, 0xbf, 0x36, 0xb4, 0x35, 0xfe, 0xec, 0xe6, 0xf8, 0x3b, 0xd9, 0x4f, + 0x6f, 0x8e, 0x77, 0x87, 0x3d, 0x1e, 0xc6, 0xb5, 0x99, 0x66, 0xc1, 0x1f, + 0xbb, 0x0c, 0xb9, 0xb7, 0x5a, 0x0b, 0xc8, 0x3d, 0x45, 0xeb, 0x32, 0xea, + 0x24, 0xc6, 0x9f, 0xeb, 0x89, 0x37, 0xdb, 0x62, 0x8d, 0x91, 0x09, 0x51, + 0x9f, 0x51, 0xf1, 0xd6, 0xe4, 0xfd, 0x4e, 0xc4, 0x9d, 0xcb, 0xf8, 0xce, + 0x3c, 0x17, 0xc4, 0x3c, 0xce, 0xe1, 0xf3, 0x6f, 0x5f, 0x43, 0xe7, 0x31, + 0xe8, 0xfc, 0xff, 0x1b, 0xdd, 0xe2, 0x4f, 0xe9, 0x56, 0xc5, 0x9d, 0x97, + 0xb6, 0xd9, 0x2c, 0xe9, 0xef, 0xf6, 0x69, 0x96, 0x68, 0x38, 0x6d, 0x38, + 0x0b, 0xd6, 0x8d, 0x12, 0x41, 0x0d, 0x4b, 0x9b, 0x2d, 0x35, 0xbf, 0x8b, + 0xe7, 0x99, 0x27, 0x25, 0x1a, 0x49, 0xd3, 0x2e, 0xd6, 0x07, 0x32, 0xd6, + 0x31, 0xa7, 0xe6, 0x1e, 0x73, 0xce, 0x2a, 0x3b, 0x59, 0xbf, 0xc9, 0xab, + 0xcd, 0x7f, 0x74, 0x13, 0x6a, 0x73, 0x3c, 0xcf, 0x98, 0xcb, 0xf1, 0x46, + 0x4f, 0xc6, 0x62, 0x0e, 0x5a, 0x72, 0x8a, 0xf8, 0x2c, 0xa8, 0xb9, 0xaf, + 0x0e, 0x70, 0x6e, 0x67, 0x3a, 0x76, 0xd3, 0x8f, 0xf1, 0xbf, 0x23, 0xfd, + 0xce, 0x4d, 0x17, 0x2c, 0xae, 0x3b, 0x75, 0xd3, 0x59, 0xb5, 0x46, 0x18, + 0xf1, 0x8c, 0xf3, 0x2e, 0xdf, 0xc4, 0x67, 0x9f, 0x44, 0x1c, 0x3f, 0xe1, + 0x42, 0x97, 0xee, 0x8b, 0x4e, 0x1e, 0x9f, 0x39, 0xd2, 0x54, 0xe1, 0x7d, + 0xe3, 0xe6, 0x8c, 0x15, 0x56, 0xf9, 0xf6, 0x4b, 0x98, 0x73, 0x04, 0x73, + 0x0e, 0xbb, 0x01, 0x3f, 0xea, 0xbe, 0x93, 0xc5, 0xfd, 0xc3, 0x65, 0xc3, + 0x71, 0xca, 0xe6, 0x38, 0x6a, 0x8e, 0xf8, 0x71, 0xe4, 0xe3, 0x1c, 0x72, + 0xa0, 0x2d, 0xe6, 0x70, 0x41, 0xd2, 0x5d, 0x93, 0xa8, 0xe5, 0x56, 0x90, + 0x4f, 0x50, 0x87, 0xa4, 0xaa, 0x32, 0xd8, 0x95, 0x39, 0xad, 0xc3, 0x3e, + 0xef, 0x80, 0xbd, 0x1a, 0x8e, 0x9e, 0x44, 0x5c, 0x47, 0xdc, 0x5c, 0xa8, + 0x58, 0x5a, 0xb6, 0x3c, 0x68, 0x94, 0xe4, 0x56, 0x59, 0x37, 0xcc, 0xf8, + 0xa4, 0xec, 0x92, 0x6c, 0x18, 0xf3, 0x86, 0x3f, 0x2e, 0xb9, 0xb8, 0x86, + 0xd8, 0x70, 0x03, 0xe2, 0x16, 0xeb, 0xe4, 0xf6, 0x18, 0xfa, 0x0b, 0x11, + 0xeb, 0x8b, 0x21, 0xc6, 0x9e, 0x4e, 0x8b, 0x75, 0x3f, 0xe7, 0xed, 0x92, + 0x8d, 0x0f, 0xcc, 0x7b, 0xb7, 0x6d, 0x5e, 0xfb, 0xf8, 0x7b, 0x18, 0xdf, + 0x25, 0x17, 0x41, 0x47, 0x38, 0x39, 0x26, 0x25, 0xf0, 0x10, 0x39, 0xd5, + 0x6a, 0x5d, 0x00, 0x3f, 0x3a, 0xf8, 0x2f, 0x56, 0x59, 0x0b, 0x84, 0xa4, + 0x6a, 0xe0, 0x9e, 0xdb, 0x6a, 0xd5, 0x10, 0x46, 0xf5, 0x55, 0xd2, 0x1c, + 0x95, 0x49, 0x77, 0x48, 0xec, 0x06, 0xe5, 0x60, 0xc2, 0xeb, 0xfe, 0xac, + 0x2b, 0x7b, 0x86, 0x39, 0x13, 0x16, 0xb1, 0xfa, 0xe7, 0x5d, 0x19, 0xe4, + 0x3e, 0x7d, 0xf5, 0x62, 0x57, 0x16, 0x7a, 0x0f, 0xad, 0xfe, 0xe7, 0x2e, + 0xe7, 0x34, 0xe9, 0x0a, 0x21, 0xf7, 0xdd, 0x22, 0x45, 0xa3, 0x25, 0xdf, + 0x44, 0x8d, 0x50, 0x1c, 0x46, 0x2e, 0x83, 0x17, 0xe8, 0xa0, 0xbb, 0x60, + 0x48, 0xb4, 0x3b, 0xfd, 0x7d, 0xd0, 0x37, 0x06, 0xd9, 0xec, 0xc2, 0x9c, + 0x10, 0xc6, 0x87, 0xf0, 0xbf, 0x7d, 0xfc, 0x8d, 0x2e, 0xe4, 0x05, 0xc4, + 0x60, 0x89, 0x66, 0xc6, 0x7a, 0xb0, 0xfe, 0xf7, 0x30, 0x8e, 0x09, 0xc9, + 0xcd, 0xf1, 0x27, 0xbc, 0xf1, 0xb7, 0x41, 0x0b, 0x9f, 0x63, 0x8d, 0x22, + 0xd1, 0xb9, 0x31, 0x03, 0x34, 0x70, 0x6e, 0x4c, 0xcd, 0x75, 0xce, 0xd0, + 0x06, 0x0c, 0xa7, 0x66, 0xdd, 0x2c, 0xd9, 0xe5, 0x7e, 0x99, 0x5c, 0xee, + 0x93, 0x03, 0xcb, 0xe6, 0x4c, 0x95, 0xd8, 0x0f, 0x3c, 0x0b, 0xea, 0x30, + 0x7d, 0x55, 0x20, 0x01, 0x33, 0x7e, 0x44, 0x06, 0xe3, 0x5f, 0x92, 0x5f, + 0xb6, 0x90, 0xef, 0x91, 0xeb, 0x7b, 0x24, 0xac, 0xd6, 0x89, 0x07, 0x7b, + 0xd2, 0x46, 0xb7, 0xed, 0xeb, 0x9c, 0xb9, 0xd6, 0xba, 0x70, 0xfe, 0xd5, + 0xf8, 0x55, 0xeb, 0xfe, 0x85, 0xbf, 0xae, 0x81, 0x75, 0x07, 0xb0, 0x26, + 0x79, 0x34, 0xbb, 0x26, 0x4e, 0x8b, 0xdd, 0x09, 0xfa, 0x9c, 0xe4, 0x8d, + 0xc0, 0x86, 0xfd, 0x72, 0x62, 0x99, 0xf1, 0x42, 0xfa, 0xf1, 0x19, 0x8d, + 0x48, 0x72, 0xf8, 0x1c, 0xea, 0xae, 0x09, 0xb5, 0x86, 0x57, 0x93, 0xe9, + 0xab, 0x29, 0xd4, 0xc4, 0x3f, 0x05, 0x3d, 0xac, 0x15, 0xc8, 0x73, 0x18, + 0xfc, 0xa6, 0x50, 0x8b, 0x11, 0x47, 0xb5, 0x1e, 0xcf, 0xa4, 0xf0, 0xfd, + 0x5c, 0xa2, 0x2b, 0x8b, 0x98, 0x08, 0xff, 0xbe, 0x39, 0xa4, 0x72, 0x18, + 0xf5, 0x32, 0xda, 0x45, 0x3c, 0x83, 0xe7, 0xa1, 0x27, 0xca, 0x68, 0xbc, + 0xcb, 0xa9, 0x50, 0x46, 0x02, 0x7a, 0x2c, 0xd8, 0x64, 0x58, 0x61, 0x29, + 0x7d, 0xd5, 0xc6, 0xbc, 0xb7, 0x42, 0xac, 0x77, 0x33, 0x16, 0xbf, 0x23, + 0xe6, 0xac, 0x4e, 0x61, 0x2e, 0xbf, 0xdf, 0x85, 0x75, 0x07, 0x87, 0x8b, + 0xd2, 0x31, 0x7c, 0x18, 0xf1, 0x4e, 0x1f, 0x1b, 0x01, 0x6d, 0xb4, 0xf3, + 0x16, 0xb0, 0xc0, 0x6f, 0x81, 0x1f, 0xf8, 0x46, 0xd2, 0x92, 0xf9, 0x25, + 0xca, 0x55, 0x3e, 0x0e, 0x1e, 0xc0, 0x7f, 0x12, 0x71, 0x8d, 0x3c, 0x70, + 0x6f, 0x41, 0x8e, 0xbe, 0x5b, 0xf2, 0x4b, 0x51, 0x55, 0xeb, 0xdb, 0x06, + 0xf7, 0xd7, 0x34, 0x3d, 0xdd, 0x0d, 0x1d, 0x93, 0xb7, 0x1c, 0x68, 0x7b, + 0x0c, 0x79, 0x80, 0xbc, 0x91, 0x2f, 0xfa, 0xca, 0x28, 0xfc, 0x84, 0xf4, + 0xfb, 0xb6, 0xa7, 0xad, 0x23, 0xa6, 0xa8, 0x38, 0x98, 0xca, 0x20, 0xb0, + 0xbd, 0xd4, 0x1c, 0x97, 0x3f, 0x6e, 0x8e, 0xc9, 0x77, 0x9b, 0x29, 0xe4, + 0xc0, 0x51, 0xe4, 0xc0, 0x61, 0xe4, 0x40, 0x0b, 0x39, 0x30, 0x81, 0x1c, + 0x38, 0x80, 0x1c, 0x18, 0x47, 0x9c, 0x14, 0x39, 0xa1, 0xf2, 0x6d, 0x2c, + 0x0a, 0xcc, 0x1d, 0xb5, 0x9b, 0x0e, 0x78, 0x99, 0xc1, 0x5e, 0xb3, 0xe0, + 0xeb, 0x50, 0xd7, 0x44, 0x65, 0x1c, 0x31, 0xd7, 0x42, 0x3c, 0x4a, 0x20, + 0xdf, 0x8c, 0x01, 0x6b, 0x89, 0x6c, 0x2c, 0x25, 0x10, 0x13, 0x5b, 0xe2, + 0x00, 0x13, 0x97, 0x8c, 0x14, 0x9e, 0xdd, 0xab, 0xec, 0x33, 0x94, 0xbe, + 0x3b, 0x2c, 0xdd, 0xa3, 0x92, 0x2f, 0x9f, 0xc4, 0x58, 0x1c, 0xeb, 0x75, + 0x21, 0x2f, 0x31, 0x2e, 0x30, 0x06, 0x2c, 0x39, 0xbf, 0x6b, 0xd1, 0xd7, + 0xba, 0xb5, 0xcc, 0xe9, 0x82, 0x30, 0x96, 0x23, 0x0f, 0xc0, 0x1e, 0x38, + 0x36, 0x89, 0xe7, 0xf8, 0xfd, 0x2f, 0xfd, 0x98, 0xf9, 0xb1, 0x4e, 0x81, + 0xd1, 0xbe, 0xc4, 0x9c, 0x67, 0x61, 0x3d, 0xb7, 0xdd, 0x4f, 0x9f, 0x47, + 0xad, 0x14, 0xdc, 0x27, 0xae, 0x66, 0x3f, 0xe1, 0x24, 0x68, 0x1e, 0x04, + 0xbe, 0x47, 0x6d, 0x75, 0xb0, 0x8a, 0xef, 0xed, 0xf3, 0x5d, 0xcc, 0x57, + 0x63, 0x51, 0x23, 0x6d, 0xb1, 0x9e, 0x43, 0xac, 0x3c, 0x86, 0xb8, 0x68, + 0x3b, 0xfa, 0x5a, 0x03, 0x7c, 0x42, 0x8e, 0x65, 0xdb, 0x09, 0x0f, 0xbd, + 0xd6, 0x7a, 0xd6, 0x1a, 0x96, 0x89, 0xb5, 0x31, 0xc9, 0xae, 0x0d, 0xc6, + 0xcf, 0x4b, 0xd7, 0x65, 0x5b, 0x5e, 0x6b, 0x95, 0x5c, 0xf3, 0xa4, 0x0d, + 0xbb, 0xdc, 0xb7, 0xdf, 0x90, 0x1a, 0x30, 0xdc, 0xbe, 0xfd, 0x9d, 0xac, + 0xe9, 0x5f, 0x14, 0x3d, 0x21, 0x99, 0x45, 0x5b, 0xc6, 0xf6, 0x07, 0xb5, + 0xe7, 0x2f, 0x3b, 0xa4, 0x1b, 0x63, 0x6b, 0x09, 0xcc, 0x61, 0xdd, 0xaf, + 0xfa, 0x27, 0xe0, 0x59, 0xf3, 0x9e, 0x51, 0x39, 0x8f, 0x98, 0x19, 0xbc, + 0x37, 0x6d, 0xe7, 0xfc, 0x22, 0x70, 0x0d, 0xe4, 0x99, 0x59, 0x24, 0xee, + 0xda, 0x05, 0x39, 0x45, 0x60, 0x23, 0xd4, 0xfd, 0x20, 0x9e, 0x6d, 0xc9, + 0x57, 0x53, 0xb4, 0x87, 0xc7, 0x20, 0x4b, 0xac, 0x15, 0x0e, 0xf8, 0xf9, + 0x9a, 0xcc, 0x2d, 0x51, 0x7e, 0x71, 0xd4, 0x96, 0xdc, 0x5b, 0xa2, 0x5d, + 0xe9, 0xab, 0xeb, 0x46, 0xdb, 0xd9, 0x58, 0xc4, 0xfa, 0x43, 0xc4, 0xd8, + 0x88, 0xd5, 0x65, 0xf6, 0x06, 0x58, 0x53, 0x1d, 0x80, 0x4e, 0xa6, 0x15, + 0xe6, 0xce, 0xd4, 0x53, 0x62, 0x9d, 0x62, 0xac, 0x92, 0x44, 0xc8, 0x22, + 0xbe, 0x17, 0x43, 0x4f, 0xcf, 0xe2, 0x1e, 0xe5, 0xc9, 0x5a, 0x1f, 0xf7, + 0x57, 0xff, 0xa3, 0xd2, 0x49, 0x08, 0xba, 0xcb, 0xef, 0x67, 0x11, 0x22, + 0x4b, 0xa1, 0x34, 0x62, 0xe0, 0x18, 0x79, 0x50, 0x7b, 0xa3, 0x9e, 0xa4, + 0xdf, 0x81, 0x67, 0xd8, 0x46, 0x5b, 0x5d, 0xa9, 0xfe, 0x4a, 0x95, 0x08, + 0x6c, 0x59, 0x0a, 0x91, 0x34, 0x78, 0x1a, 0xc3, 0x77, 0x38, 0xff, 0x09, + 0xe8, 0xf3, 0x2c, 0x9e, 0x5f, 0x00, 0x5f, 0x1b, 0x65, 0xd2, 0x9d, 0x4c, + 0x1c, 0x57, 0xbe, 0x8b, 0x6b, 0x97, 0xb5, 0xcc, 0xd7, 0xe4, 0xbc, 0xe2, + 0xef, 0x13, 0xac, 0x9d, 0xa1, 0xa7, 0xeb, 0xe1, 0x6f, 0xf2, 0x3a, 0xf9, + 0xf3, 0xd6, 0x67, 0xce, 0xca, 0x58, 0x09, 0xc9, 0x96, 0x5f, 0x6a, 0x85, + 0x2d, 0x2b, 0x3e, 0xef, 0xeb, 0x31, 0xeb, 0x46, 0x41, 0x07, 0xfb, 0x00, + 0xfb, 0x95, 0x2e, 0x41, 0x07, 0x6d, 0xa7, 0x10, 0x4d, 0x3f, 0x2e, 0x2b, + 0x4b, 0xff, 0x54, 0x6a, 0x4b, 0x05, 0xa9, 0x2f, 0xfd, 0x23, 0x39, 0xb7, + 0xd4, 0x92, 0x0b, 0x29, 0x15, 0x93, 0xac, 0x0e, 0xe5, 0xcf, 0x72, 0xa3, + 0x87, 0x07, 0x93, 0xe3, 0x97, 0x20, 0xc0, 0x95, 0xaa, 0x47, 0xfb, 0x54, + 0x1b, 0xed, 0x17, 0x60, 0x6b, 0xaf, 0x58, 0xa4, 0x7f, 0x4c, 0x6a, 0x65, + 0xd2, 0xfe, 0xa0, 0xa2, 0xfd, 0xc0, 0x26, 0xed, 0x92, 0x0b, 0x59, 0xa4, + 0x7f, 0x27, 0xda, 0x81, 0xf3, 0xfb, 0x49, 0x7f, 0x02, 0xcf, 0x7e, 0xd0, + 0xfe, 0x6a, 0xee, 0x6b, 0xad, 0x8d, 0x72, 0x44, 0xd1, 0x1c, 0x4a, 0x8f, + 0x41, 0x3e, 0xaf, 0xb5, 0xd6, 0x5d, 0xfa, 0x11, 0xbe, 0xbb, 0xf7, 0x20, + 0x46, 0xf5, 0x61, 0xaf, 0x5e, 0xc9, 0xcf, 0x46, 0x11, 0x27, 0xc7, 0xa1, + 0xdb, 0x2e, 0xe5, 0x87, 0x08, 0x17, 0xd0, 0xd9, 0x34, 0xe6, 0x1f, 0xa2, + 0xbf, 0x29, 0xb9, 0x38, 0x90, 0x4b, 0xb1, 0x9c, 0x8e, 0xa0, 0xfe, 0xc7, + 0x3e, 0x86, 0x93, 0x73, 0xf9, 0xcc, 0x00, 0x62, 0x1a, 0xff, 0x7f, 0x64, + 0x7b, 0x28, 0x20, 0xd6, 0x42, 0xe7, 0x3d, 0x90, 0x1f, 0xe8, 0x18, 0x9b, + 0x41, 0x6e, 0x4d, 0x0e, 0xd7, 0x54, 0x7f, 0x91, 0x71, 0xe5, 0x28, 0xf2, + 0xe9, 0x21, 0x7c, 0xbc, 0xfd, 0x26, 0x9a, 0xdc, 0x73, 0x3b, 0x4f, 0x45, + 0x77, 0x7d, 0x2f, 0x01, 0x52, 0xa6, 0xc9, 0x7d, 0x0b, 0x12, 0x4a, 0x87, + 0xb0, 0x2f, 0xc7, 0x7a, 0x10, 0x63, 0x06, 0xa2, 0xd9, 0xe6, 0xcf, 0x31, + 0x4e, 0x5f, 0x66, 0x7c, 0x0f, 0x68, 0x1f, 0xc5, 0x9a, 0x8c, 0xbb, 0x63, + 0xe0, 0x99, 0x35, 0x26, 0xe3, 0x26, 0xf2, 0x48, 0xe3, 0x47, 0xcc, 0x2d, + 0xf8, 0x3e, 0xe0, 0x7f, 0xe7, 0x7d, 0x89, 0xde, 0x9c, 0x36, 0xab, 0x05, + 0x31, 0xb1, 0x27, 0x74, 0x6e, 0xc5, 0xa5, 0xd8, 0x30, 0x5f, 0x20, 0x66, + 0xd4, 0x29, 0x83, 0x35, 0xca, 0x89, 0xfd, 0x27, 0xd4, 0x7f, 0xb5, 0xe7, + 0x21, 0x8f, 0xa8, 0xec, 0xb5, 0x0e, 0x22, 0xa6, 0x80, 0xfe, 0xca, 0x18, + 0x78, 0x63, 0x8f, 0x66, 0x10, 0xf9, 0x2b, 0x04, 0x21, 0xa0, 0x96, 0x5a, + 0x0b, 0xc9, 0xbd, 0xe1, 0x11, 0xa3, 0x28, 0x8f, 0x46, 0x58, 0x36, 0x17, + 0xd6, 0x98, 0x07, 0xc2, 0xb2, 0xb0, 0x26, 0x72, 0x69, 0x91, 0x71, 0x45, + 0xfd, 0x41, 0xe6, 0x86, 0x33, 0x8f, 0x3c, 0x5b, 0x5a, 0x62, 0x8c, 0x61, + 0x9c, 0xb8, 0x01, 0xba, 0x48, 0x7e, 0xe3, 0xab, 0xc8, 0x49, 0xa5, 0xf2, + 0x20, 0x62, 0xa6, 0xac, 0xeb, 0x90, 0x29, 0x72, 0x19, 0x6b, 0xd4, 0x1d, + 0xfa, 0x32, 0x41, 0x4f, 0x26, 0x2a, 0xc5, 0x45, 0xf6, 0x63, 0xa2, 0xa0, + 0x85, 0x35, 0x76, 0x48, 0xd5, 0x3f, 0x37, 0xa8, 0xd8, 0xca, 0xff, 0xe1, + 0xb6, 0x7d, 0x93, 0x27, 0xf7, 0xe9, 0x8c, 0x63, 0x37, 0x8b, 0x3d, 0x63, + 0x77, 0x1d, 0xa8, 0x74, 0x48, 0xb5, 0x8f, 0x76, 0x49, 0xfd, 0xbf, 0xa0, + 0x62, 0xed, 0x02, 0x78, 0x2a, 0x2e, 0x12, 0xe3, 0x86, 0x31, 0x2f, 0xe6, + 0xcf, 0xa3, 0x5c, 0xff, 0x89, 0xcc, 0xed, 0x7f, 0x17, 0x74, 0x79, 0x71, + 0x2d, 0xbf, 0x1f, 0xf1, 0x76, 0x46, 0x97, 0x3b, 0xef, 0x1a, 0xc7, 0xb3, + 0xcc, 0x81, 0xef, 0xf8, 0x78, 0x92, 0x63, 0xec, 0x61, 0x81, 0xbe, 0x15, + 0x03, 0xff, 0xfb, 0xa4, 0xb0, 0x12, 0x85, 0x1c, 0x90, 0x4b, 0x6b, 0xde, + 0x5a, 0xac, 0x77, 0x4f, 0x42, 0x47, 0xfa, 0xa9, 0xa8, 0x44, 0x4e, 0xf5, + 0x49, 0xf8, 0xeb, 0xdd, 0xd2, 0xf1, 0xf5, 0x21, 0x09, 0x7d, 0xdd, 0x64, + 0x4e, 0x4f, 0x9c, 0x80, 0xbe, 0xe6, 0x65, 0x5c, 0x9e, 0x44, 0xde, 0x62, + 0x5e, 0x57, 0x76, 0x6a, 0xf4, 0x4b, 0x08, 0x05, 0xab, 0xfe, 0x8c, 0x2d, + 0x8f, 0xee, 0xff, 0x85, 0xea, 0x33, 0x01, 0xc3, 0x8b, 0xfe, 0xfc, 0x94, + 0xd8, 0xcd, 0x77, 0x21, 0x6b, 0xc3, 0x79, 0xed, 0xd6, 0xa0, 0xa6, 0x1c, + 0x56, 0xfd, 0xc2, 0x47, 0xf7, 0x7b, 0x35, 0x25, 0xf0, 0xb8, 0xe6, 0xa8, + 0x9a, 0x12, 0xf1, 0x35, 0xcc, 0x79, 0xfd, 0xa2, 0x63, 0xaf, 0xbc, 0x0c, + 0x42, 0x4f, 0xb7, 0x88, 0x7d, 0x08, 0x7e, 0xf1, 0x9c, 0x2c, 0xe9, 0x69, + 0x4d, 0xad, 0x19, 0x7a, 0x86, 0x71, 0x8a, 0xf1, 0x8b, 0x36, 0x9e, 0x4c, + 0x14, 0x61, 0x7f, 0xa1, 0xe7, 0x19, 0xa3, 0x3c, 0xdb, 0x9e, 0x68, 0x8b, + 0x75, 0x0b, 0x95, 0x7b, 0xa0, 0x43, 0xd4, 0xf2, 0x16, 0xe2, 0x9c, 0x81, + 0x5c, 0x6e, 0xf1, 0xda, 0xeb, 0xe1, 0xe5, 0x63, 0x31, 0x75, 0x5d, 0xac, + 0x7a, 0x18, 0xdc, 0x5b, 0x9f, 0x75, 0x07, 0x62, 0x4c, 0x93, 0x74, 0x70, + 0xdf, 0x01, 0x09, 0x3d, 0x17, 0x93, 0xf0, 0x73, 0xb4, 0x3f, 0x33, 0xe1, + 0x40, 0x7e, 0x0b, 0x16, 0x31, 0xd0, 0x0a, 0xb0, 0xc5, 0xcd, 0xa2, 0xaf, + 0x0c, 0xc0, 0x77, 0xcc, 0x78, 0x55, 0x92, 0x12, 0xaa, 0x45, 0xe5, 0xad, + 0x45, 0x33, 0x41, 0x7b, 0x39, 0x6b, 0x61, 0xbc, 0xd9, 0x75, 0x79, 0x5d, + 0x51, 0xc1, 0xb1, 0x2f, 0x87, 0x80, 0x19, 0x86, 0x6d, 0xbd, 0x47, 0x5e, + 0x87, 0xbe, 0x73, 0x6a, 0xec, 0x66, 0xac, 0x0b, 0x1a, 0x9e, 0x33, 0xc1, + 0x03, 0xd7, 0xfd, 0x1e, 0xd6, 0x54, 0xf8, 0xca, 0xd9, 0x60, 0x4d, 0xba, + 0x48, 0xdb, 0xed, 0x83, 0xdd, 0xe1, 0xba, 0xd9, 0x21, 0xb9, 0xd9, 0x84, + 0xe8, 0x8b, 0x9f, 0x91, 0xc1, 0xfd, 0xba, 0xc7, 0x8f, 0xe2, 0x91, 0x63, + 0xec, 0xc7, 0xdd, 0xae, 0xfc, 0x51, 0x5f, 0x83, 0xcd, 0x3c, 0x48, 0x1d, + 0x23, 0xf7, 0x23, 0x8f, 0x31, 0x8e, 0x85, 0x90, 0xc7, 0xb2, 0x4d, 0x4f, + 0xef, 0xd5, 0x07, 0xfb, 0xe5, 0xc9, 0xe7, 0x68, 0x4f, 0xb8, 0xb7, 0x69, + 0x53, 0x41, 0x0f, 0x98, 0xf7, 0x2c, 0x39, 0xf9, 0x6c, 0x50, 0x73, 0xb0, + 0xbe, 0x32, 0xe3, 0x07, 0xc0, 0x8f, 0x7e, 0x27, 0xe3, 0x81, 0xae, 0x6c, + 0x37, 0x6f, 0x59, 0x5e, 0xdd, 0x51, 0x49, 0xb0, 0x2f, 0x6e, 0xb0, 0x4e, + 0xb3, 0xe3, 0x9e, 0xbc, 0x8b, 0x18, 0x2b, 0x35, 0x67, 0x11, 0xa3, 0x23, + 0x72, 0x71, 0xd6, 0x86, 0xee, 0x3f, 0x0b, 0xba, 0x0e, 0x75, 0x11, 0x23, + 0x5f, 0x9c, 0x75, 0x70, 0x7d, 0x48, 0xd5, 0x66, 0xa1, 0x3b, 0x61, 0xc7, + 0xcd, 0x7e, 0xfa, 0x91, 0xaf, 0xa7, 0x84, 0x56, 0x5c, 0x32, 0xb5, 0x12, + 0x62, 0xf6, 0x64, 0x8a, 0x39, 0xbe, 0x53, 0xf5, 0x4d, 0xd9, 0xaf, 0xc9, + 0x2b, 0xbc, 0xb0, 0x4f, 0x2b, 0x56, 0x19, 0xe7, 0x0b, 0xf1, 0x0e, 0x21, + 0x0e, 0x11, 0xad, 0x66, 0x51, 0x27, 0x9a, 0x9c, 0x57, 0xbd, 0x58, 0x11, + 0xc7, 0x3d, 0x42, 0x19, 0x68, 0xf5, 0xea, 0x3e, 0xad, 0x50, 0x0d, 0xc9, + 0xc5, 0x18, 0xe9, 0x4e, 0xa8, 0xfa, 0x7d, 0xbf, 0xb2, 0xb5, 0x1e, 0xe4, + 0x12, 0xd8, 0x4c, 0xea, 0x93, 0xd8, 0x57, 0x8d, 0xc1, 0xa6, 0xa8, 0x7b, + 0xea, 0x5d, 0xc5, 0x48, 0x5f, 0xf7, 0x3b, 0xe5, 0x4c, 0xd0, 0x51, 0x26, + 0x7e, 0xef, 0xf4, 0xf1, 0xfb, 0xa2, 0x5f, 0x0f, 0x3d, 0x26, 0xac, 0x53, + 0x16, 0x2a, 0xa4, 0x05, 0xf1, 0xd6, 0xdd, 0xc9, 0x96, 0x28, 0x47, 0x2f, + 0xa6, 0x1c, 0x45, 0x1d, 0xa3, 0xaf, 0x19, 0xbe, 0x0d, 0xf0, 0x6f, 0x14, + 0xf7, 0xbc, 0x5a, 0xaa, 0xd8, 0x8c, 0xc0, 0xdf, 0xa7, 0x21, 0x23, 0xea, + 0x06, 0xfa, 0x5b, 0xe3, 0x99, 0x0a, 0xf4, 0xb7, 0xf6, 0xf2, 0xfb, 0x76, + 0x1f, 0x63, 0xde, 0xb0, 0x3c, 0x89, 0xf1, 0x13, 0x67, 0x48, 0xcf, 0xb8, + 0x8f, 0xc7, 0x12, 0x90, 0x09, 0x63, 0xfc, 0xa8, 0xbc, 0xd5, 0x70, 0x14, + 0xfe, 0xdb, 0xb7, 0x7f, 0x46, 0xe6, 0xdd, 0x59, 0xe0, 0x3f, 0xc8, 0xdf, + 0x48, 0xc0, 0x3f, 0xe3, 0x2a, 0x3e, 0x1e, 0xfe, 0x68, 0x35, 0x49, 0xd8, + 0xcb, 0xd9, 0xf7, 0x5e, 0x67, 0xce, 0xde, 0x0d, 0xfc, 0xf5, 0x91, 0xd6, + 0x0f, 0x79, 0xeb, 0xff, 0x17, 0xe8, 0xea, 0x73, 0xd8, 0x23, 0x0a, 0xfa, + 0xfa, 0x29, 0xd3, 0x0f, 0x7b, 0x4e, 0xf7, 0x9e, 0xbb, 0xff, 0x3a, 0xe9, + 0x32, 0xa4, 0x01, 0x8c, 0x50, 0x50, 0x79, 0x94, 0xb5, 0x62, 0xc4, 0xd7, + 0xdf, 0x31, 0x60, 0x67, 0xae, 0x1b, 0xc4, 0xde, 0x4e, 0x29, 0xf4, 0x05, + 0xf5, 0x27, 0x62, 0xf6, 0xe6, 0x78, 0x50, 0xcf, 0xf2, 0xf9, 0x94, 0x93, + 0x2f, 0xb3, 0x4f, 0xc8, 0x5c, 0xc0, 0x31, 0x65, 0x87, 0x1f, 0x42, 0xb7, + 0x09, 0xcf, 0x20, 0xdd, 0xf7, 0x29, 0xba, 0x1d, 0x45, 0x37, 0xfd, 0x8b, + 0x67, 0x3a, 0xec, 0xa3, 0x05, 0x7d, 0x33, 0xae, 0x07, 0x4c, 0x00, 0x7d, + 0x7f, 0x17, 0x3a, 0xfe, 0x4e, 0x05, 0x98, 0xa0, 0x02, 0x4c, 0x80, 0x3d, + 0xbe, 0x0d, 0x1d, 0x7f, 0xab, 0x02, 0x4c, 0x50, 0x89, 0xfb, 0x3d, 0x0a, + 0x9b, 0x98, 0xfe, 0x23, 0xda, 0x6e, 0xd0, 0x93, 0xb9, 0xda, 0x2e, 0x39, + 0xce, 0xf9, 0x01, 0x36, 0x8e, 0xc2, 0x8e, 0x78, 0x6e, 0x11, 0xf4, 0x3b, + 0xfc, 0x1c, 0xd1, 0xe0, 0xb9, 0x00, 0x72, 0x44, 0x83, 0xe7, 0x18, 0x23, + 0xf1, 0x10, 0x30, 0x61, 0x48, 0xe2, 0xc2, 0x5e, 0xef, 0xdc, 0x18, 0xd6, + 0x1a, 0x1d, 0x84, 0x27, 0x75, 0xa8, 0xbe, 0xd6, 0x71, 0xd5, 0x6f, 0x40, + 0x5c, 0xa8, 0x06, 0xb5, 0x5b, 0x52, 0x26, 0x96, 0x88, 0x33, 0x65, 0xaf, + 0x9e, 0x86, 0x0e, 0x5c, 0x62, 0xc3, 0xcd, 0xbe, 0xf4, 0x70, 0x1d, 0x7b, + 0x16, 0x2d, 0x8f, 0xbe, 0xe3, 0xee, 0xd6, 0x33, 0x07, 0x10, 0x9f, 0xa7, + 0xca, 0x09, 0x99, 0x2c, 0x7b, 0x98, 0x00, 0xf5, 0xcf, 0x55, 0xfd, 0x51, + 0x9b, 0x7a, 0x80, 0xfe, 0x36, 0x6d, 0x23, 0x71, 0x3e, 0x45, 0x19, 0x53, + 0xff, 0xd3, 0xaa, 0x67, 0x7d, 0xa0, 0xee, 0xf5, 0xe5, 0x27, 0x95, 0x2d, + 0x84, 0x19, 0x67, 0xa8, 0x3f, 0xcf, 0x87, 0x61, 0x17, 0x79, 0x37, 0x90, + 0x4b, 0x3b, 0x1e, 0xf9, 0xbc, 0x26, 0xd6, 0x4e, 0xe3, 0xb9, 0xb6, 0xf1, + 0xcd, 0xfb, 0x3e, 0xbd, 0x88, 0x7d, 0x9b, 0x3d, 0x06, 0xc6, 0xa9, 0xad, + 0xf1, 0x10, 0xea, 0x87, 0xb0, 0xba, 0x8f, 0x18, 0xde, 0x88, 0x49, 0xb6, + 0x61, 0x89, 0x53, 0xe5, 0x3c, 0xf6, 0x2d, 0x18, 0x8f, 0x9e, 0x90, 0xec, + 0x52, 0xaf, 0xe4, 0x62, 0x66, 0xca, 0x96, 0xbf, 0x27, 0x1b, 0xcb, 0x85, + 0x04, 0xcf, 0x0d, 0x0b, 0x33, 0x1a, 0x9e, 0x7b, 0x18, 0xd7, 0xa4, 0xd9, + 0x92, 0xc3, 0x65, 0xe6, 0x9d, 0x91, 0x78, 0x03, 0xf7, 0x72, 0xb3, 0xec, + 0xd5, 0x54, 0x61, 0x93, 0x66, 0xa2, 0x8a, 0x78, 0xf0, 0x72, 0x99, 0xfb, + 0x01, 0x1b, 0x95, 0xd9, 0xcf, 0x09, 0xee, 0x3f, 0x01, 0x1c, 0x88, 0x58, + 0x1d, 0xf3, 0xe7, 0x28, 0x5e, 0x6d, 0x23, 0x2c, 0x81, 0xae, 0x3b, 0x65, + 0xdd, 0x8f, 0xbb, 0xb5, 0xb2, 0xd7, 0x47, 0x39, 0x4b, 0x7a, 0xdc, 0xff, + 0xd5, 0x5a, 0x8f, 0xa1, 0x16, 0xda, 0xe4, 0xf5, 0x8f, 0xb9, 0x8f, 0x81, + 0xb0, 0x2b, 0x27, 0xdc, 0x40, 0x26, 0xbc, 0xcf, 0x31, 0x9e, 0x8d, 0xb6, + 0x5a, 0x67, 0xad, 0xf6, 0x9e, 0xdf, 0xf5, 0xf4, 0xcc, 0xde, 0xb8, 0x2d, + 0x63, 0xbd, 0xe6, 0xa0, 0x26, 0xf6, 0x7b, 0x66, 0x87, 0x46, 0xbc, 0x9e, + 0xd9, 0xfc, 0xc8, 0xf6, 0x9e, 0xd9, 0xcf, 0x6f, 0xf3, 0x7a, 0x66, 0x17, + 0x9d, 0x22, 0x3e, 0x5e, 0xcf, 0x6c, 0xf8, 0x76, 0xaf, 0x67, 0xf6, 0xf0, + 0xed, 0x5e, 0xcf, 0xec, 0x91, 0x11, 0xaf, 0x67, 0xf6, 0xfb, 0xb7, 0x6f, + 0xef, 0x99, 0x3d, 0x36, 0xb2, 0xbd, 0x67, 0x26, 0x13, 0xc8, 0x77, 0x13, + 0x5b, 0x3d, 0xb3, 0xf2, 0xc8, 0xb5, 0x7b, 0x66, 0xaf, 0x06, 0x78, 0x1d, + 0xfc, 0x8c, 0x81, 0x87, 0x14, 0xf0, 0xfa, 0x28, 0xf0, 0xfa, 0xaf, 0xeb, + 0x59, 0x87, 0xc1, 0xe7, 0xcd, 0x7e, 0x5e, 0xb8, 0x1e, 0xdc, 0x7e, 0xbb, + 0xff, 0x8c, 0xa0, 0xde, 0x4d, 0xf8, 0xb5, 0x0a, 0xb1, 0xfb, 0x1e, 0xbf, + 0x66, 0xfb, 0x6b, 0xd1, 0xad, 0xf3, 0xec, 0xf6, 0xff, 0x37, 0xa0, 0xf4, + 0x0e, 0xf0, 0x3c, 0xf9, 0x79, 0x0d, 0xb5, 0x1f, 0xf9, 0x47, 0xa2, 0xef, + 0xbe, 0xe8, 0x7c, 0xd5, 0x22, 0xc6, 0x7f, 0x1c, 0xbe, 0x6a, 0xef, 0x0d, + 0xc9, 0x3a, 0xfc, 0x96, 0x39, 0xea, 0xa4, 0x64, 0x31, 0x3f, 0xab, 0xe6, + 0x27, 0x26, 0xb6, 0xe6, 0xa7, 0x26, 0xbe, 0xaa, 0x6a, 0x52, 0xf3, 0x5f, + 0xe3, 0xf3, 0x0d, 0x65, 0xdf, 0x96, 0x87, 0xe1, 0x9d, 0x4a, 0x80, 0xb7, + 0xc2, 0x3e, 0x76, 0x36, 0x1c, 0xdb, 0x9d, 0xc0, 0x33, 0xe6, 0x8b, 0xb6, + 0x34, 0x14, 0x7e, 0x0f, 0xa5, 0xcd, 0x17, 0x73, 0xaa, 0x5e, 0x33, 0x9c, + 0xbc, 0x1b, 0xd4, 0xdf, 0xa8, 0xa1, 0x86, 0x06, 0xd5, 0xf9, 0x9b, 0xbe, + 0x36, 0x8c, 0x3c, 0xd6, 0x5e, 0x63, 0xb3, 0xae, 0xd6, 0xfd, 0xba, 0xda, + 0x90, 0xbb, 0xf7, 0xb7, 0x63, 0x73, 0x99, 0xf8, 0x5b, 0x0a, 0x9b, 0xef, + 0x42, 0x6d, 0x4e, 0xec, 0x4d, 0x1c, 0x43, 0x0c, 0x41, 0x7c, 0xce, 0x7e, + 0x01, 0xeb, 0x19, 0xe6, 0x46, 0xd6, 0x37, 0x31, 0x7c, 0xf8, 0xbe, 0x41, + 0x80, 0xd1, 0x3b, 0xfc, 0xf8, 0xce, 0xba, 0x28, 0xc0, 0x2a, 0x77, 0x75, + 0x7b, 0xb5, 0xd1, 0x2e, 0xcd, 0xab, 0x3f, 0x13, 0xfe, 0x9c, 0xf0, 0x26, + 0x16, 0x0e, 0x6f, 0x62, 0xe1, 0x6d, 0xe7, 0x30, 0xa2, 0xde, 0x6d, 0x50, + 0xe7, 0x39, 0x3c, 0xdf, 0x11, 0x4d, 0x4f, 0xf3, 0x8c, 0x07, 0x38, 0xc7, + 0xe2, 0x99, 0x0f, 0x7d, 0xe9, 0x41, 0x2d, 0x5b, 0x37, 0x10, 0xef, 0x99, + 0x7f, 0x90, 0x6b, 0xcb, 0xc1, 0xd9, 0x62, 0xa0, 0x27, 0xca, 0x8e, 0x63, + 0x7f, 0xaa, 0xa1, 0xe6, 0x4d, 0x45, 0xac, 0x43, 0xa0, 0x65, 0x0a, 0xff, + 0x03, 0x99, 0xde, 0xa3, 0x72, 0x5f, 0x27, 0x6c, 0xf6, 0x78, 0x85, 0xd8, + 0xf5, 0x71, 0x69, 0xf8, 0xf8, 0x75, 0x65, 0xc9, 0xc3, 0xae, 0xe1, 0xed, + 0xd8, 0x35, 0xb5, 0x21, 0x1e, 0x8d, 0x07, 0x76, 0xa4, 0xd1, 0x70, 0x5e, + 0x19, 0x22, 0x66, 0x25, 0x9d, 0xcc, 0x3d, 0xd3, 0x88, 0x81, 0xcc, 0x39, + 0xcc, 0x37, 0xc4, 0xa5, 0xd7, 0xa2, 0x4f, 0x8d, 0x1d, 0xed, 0xb0, 0xa2, + 0xf8, 0xcc, 0x83, 0x8e, 0x19, 0x3c, 0x93, 0x96, 0x85, 0xd3, 0x5f, 0xd1, + 0x9c, 0xfa, 0x3c, 0xe8, 0x99, 0x42, 0xae, 0xa3, 0x2d, 0x15, 0x0c, 0xcf, + 0x8e, 0xd6, 0x11, 0xf7, 0x5d, 0xc6, 0x02, 0xd4, 0xae, 0xa8, 0x47, 0xca, + 0x8c, 0xbd, 0x3c, 0xeb, 0x0a, 0x62, 0x2e, 0xfb, 0x26, 0xa8, 0x59, 0x59, + 0xbb, 0x2e, 0x72, 0xdf, 0xed, 0xba, 0xa8, 0xb9, 0xc4, 0x5d, 0x86, 0xb3, + 0xbe, 0x46, 0xdc, 0xf8, 0x51, 0x31, 0xa4, 0xe1, 0xbc, 0x3c, 0x44, 0x1c, + 0x79, 0x3d, 0xf8, 0xd1, 0x84, 0x34, 0xcd, 0x17, 0xd6, 0xf5, 0x76, 0xfc, + 0xe8, 0x61, 0xc7, 0xcc, 0xda, 0x41, 0xac, 0xc9, 0xda, 0x8c, 0x38, 0xd1, + 0x44, 0x98, 0x1b, 0xc4, 0xb3, 0x83, 0xe0, 0xc7, 0xc3, 0x8a, 0x59, 0x60, + 0xc5, 0xbf, 0x03, 0xac, 0x58, 0x92, 0xf7, 0xa2, 0xc4, 0x8a, 0xb6, 0x8f, + 0x15, 0x1d, 0xd8, 0x71, 0x7e, 0x9b, 0x1d, 0x6b, 0xaa, 0x07, 0xc5, 0x7b, + 0x79, 0x60, 0xbd, 0xec, 0xa2, 0x79, 0x1d, 0xf8, 0x50, 0x93, 0x98, 0x3a, + 0xaf, 0x0f, 0xb7, 0xad, 0x19, 0xe0, 0xc0, 0x7d, 0x0a, 0xdf, 0xdd, 0x57, + 0xd9, 0x85, 0xda, 0x44, 0xe1, 0x3d, 0xff, 0x9c, 0x2f, 0x7c, 0xd5, 0xd9, + 0x67, 0xb8, 0xed, 0xec, 0x73, 0x0b, 0x17, 0xe2, 0x39, 0xbf, 0xc7, 0x17, + 0x81, 0xde, 0xfe, 0x07, 0x69, 0x82, 0x5f, 0xd1, 0x07, 0x34, 0xcf, 0x4f, + 0xb6, 0xe1, 0xc3, 0xff, 0x7a, 0x15, 0x3e, 0x44, 0xce, 0x5a, 0x89, 0x49, + 0x06, 0xd8, 0xd0, 0x5e, 0xe3, 0x5a, 0xf4, 0xe5, 0x51, 0xe9, 0x00, 0x7f, + 0x9d, 0x8b, 0x7d, 0xc0, 0x44, 0xdd, 0x12, 0x05, 0x36, 0x8a, 0x28, 0x6c, + 0x34, 0x44, 0x0c, 0x33, 0x7c, 0x18, 0x98, 0xa6, 0xb1, 0x89, 0x8f, 0xcc, + 0xd4, 0x0f, 0xa0, 0x97, 0x87, 0x95, 0xad, 0x8c, 0xcb, 0x53, 0x88, 0x9d, + 0x1d, 0x6b, 0xc0, 0x75, 0x2b, 0x1e, 0x6e, 0x8a, 0x5c, 0x85, 0x9b, 0x8e, + 0xec, 0x88, 0x9b, 0x54, 0xbf, 0x7e, 0x9c, 0x32, 0x79, 0xdd, 0xf5, 0xfa, + 0xf5, 0x97, 0x5c, 0xaf, 0x5f, 0xff, 0xba, 0xdb, 0xde, 0xaf, 0xbf, 0x49, + 0x8a, 0x86, 0x69, 0x5f, 0x94, 0xab, 0xfa, 0xf5, 0x33, 0xec, 0x7f, 0x57, + 0xbb, 0xbc, 0xbe, 0x7c, 0xb7, 0xdf, 0xaf, 0x37, 0xa5, 0xb8, 0x6d, 0xdc, + 0x90, 0xb7, 0xad, 0xa0, 0x5f, 0xff, 0x2f, 0x30, 0xd6, 0x83, 0x3d, 0xb6, + 0xf7, 0xea, 0x2f, 0xb9, 0xec, 0xd5, 0xc7, 0x38, 0xcf, 0xef, 0xd5, 0x73, + 0x1e, 0x6a, 0x78, 0x97, 0x7d, 0xfa, 0x9b, 0x21, 0x8b, 0x7e, 0xc8, 0xa1, + 0x4f, 0x3a, 0x9e, 0x8b, 0x73, 0x8e, 0xea, 0xcf, 0x5f, 0x74, 0x63, 0x78, + 0xce, 0xeb, 0xa3, 0x1f, 0x86, 0x5d, 0x1d, 0xd9, 0xec, 0xcf, 0x7b, 0x7b, + 0xbc, 0xe1, 0x6e, 0x5f, 0x7f, 0xfb, 0x3a, 0x03, 0xfe, 0x3a, 0x31, 0xac, + 0x13, 0xbf, 0x6a, 0x9d, 0xad, 0x7e, 0xfc, 0x1b, 0xae, 0xd7, 0x8b, 0x77, + 0x4e, 0x8b, 0xdd, 0x81, 0x98, 0xfc, 0xe2, 0xd0, 0x8d, 0xfe, 0x1a, 0x9b, + 0xbd, 0x78, 0xc6, 0x0e, 0xe0, 0x75, 0xc6, 0x0f, 0x3e, 0xff, 0xff, 0xbe, + 0x17, 0xcf, 0x3e, 0xbc, 0x77, 0x9e, 0x42, 0xff, 0x04, 0x2e, 0x7f, 0xd6, + 0xeb, 0xc1, 0x4f, 0x54, 0x82, 0xde, 0x3a, 0xeb, 0xc6, 0xe0, 0xbd, 0x8c, + 0xc1, 0xc4, 0x71, 0xa1, 0xad, 0x90, 0x3e, 0xae, 0xdb, 0x23, 0x73, 0x0a, + 0x17, 0xc1, 0xa6, 0x92, 0xd7, 0xc6, 0xc6, 0xb5, 0xc5, 0x00, 0x1b, 0xc7, + 0x14, 0x36, 0xae, 0xad, 0x05, 0xd8, 0x38, 0x73, 0x0d, 0x6c, 0xfc, 0xdf, + 0xba, 0xbc, 0xf8, 0x1f, 0x95, 0x82, 0xc2, 0xc6, 0xd7, 0x7a, 0xc7, 0x86, + 0xf7, 0xba, 0x89, 0x03, 0xc4, 0x3b, 0x17, 0xef, 0xbb, 0x86, 0xaf, 0x05, + 0x78, 0x99, 0xb9, 0xbe, 0x5f, 0x66, 0x9e, 0xdb, 0xc2, 0xcb, 0x1e, 0x26, + 0x36, 0x13, 0x47, 0x55, 0x2e, 0x04, 0x3e, 0x68, 0xb2, 0xef, 0x7d, 0x48, + 0xd9, 0x6e, 0xa9, 0x32, 0xab, 0x70, 0x59, 0x1e, 0xb5, 0x6d, 0x51, 0xe1, + 0x60, 0x62, 0xe0, 0x2e, 0x91, 0xbe, 0x20, 0x17, 0x05, 0x18, 0x33, 0xec, + 0xc7, 0x67, 0x9e, 0x29, 0xbc, 0x1d, 0xca, 0x10, 0x03, 0xbb, 0x41, 0x8d, + 0x40, 0x39, 0x0f, 0x23, 0x76, 0x19, 0xbe, 0xac, 0x3c, 0x9f, 0xdd, 0xb7, + 0xff, 0x87, 0xef, 0xdb, 0x06, 0xe3, 0x5a, 0x80, 0x11, 0x51, 0x03, 0x55, + 0xc6, 0xd5, 0xbb, 0x0e, 0x1e, 0x46, 0xf4, 0xf0, 0x61, 0xd6, 0x9d, 0x01, + 0x4e, 0x9e, 0x95, 0x09, 0xe0, 0xf3, 0xf5, 0xdf, 0x65, 0xef, 0x29, 0xc0, + 0x44, 0x36, 0xfe, 0xb7, 0xf7, 0xa2, 0x78, 0xdd, 0xa1, 0xce, 0xfe, 0xce, + 0x0f, 0x45, 0xdb, 0xc6, 0xff, 0x3e, 0xe2, 0x37, 0xea, 0xa1, 0x0a, 0x73, + 0x1d, 0xb1, 0xd0, 0x6f, 0x40, 0x07, 0x63, 0xd7, 0xc0, 0x42, 0x57, 0xe7, + 0x26, 0xe6, 0xcb, 0xad, 0xbc, 0xe4, 0x6c, 0xe6, 0x25, 0xee, 0xf1, 0xeb, + 0x72, 0x27, 0xc7, 0x6c, 0x23, 0x62, 0x4d, 0xe1, 0x33, 0x8f, 0x7c, 0xbd, + 0x3d, 0x37, 0xcd, 0x5d, 0x47, 0x6e, 0x9a, 0x50, 0xb9, 0x89, 0xf4, 0xa2, + 0x9e, 0x83, 0x4c, 0xbe, 0x0b, 0x59, 0x7e, 0x07, 0xb4, 0xff, 0x11, 0xf8, + 0xf9, 0x43, 0x60, 0xac, 0x6f, 0x03, 0x63, 0x7d, 0xab, 0xd2, 0xfe, 0x0e, + 0xc3, 0xb8, 0xb0, 0x0e, 0xf4, 0xea, 0x66, 0x0f, 0xc3, 0x1f, 0x86, 0x57, + 0x35, 0xca, 0x86, 0x33, 0x57, 0x1e, 0x31, 0xe6, 0xbd, 0xf3, 0xd2, 0x44, + 0x4e, 0xd2, 0x88, 0x11, 0xcc, 0x15, 0xea, 0x3a, 0xce, 0x7e, 0x25, 0xb1, + 0x42, 0x5d, 0xd5, 0x93, 0x43, 0x52, 0x6d, 0x78, 0xf8, 0x6a, 0xe1, 0x8c, + 0xb7, 0xc6, 0x9c, 0x8f, 0xaf, 0xf2, 0x3e, 0xbe, 0xca, 0x35, 0x36, 0x12, + 0xac, 0xcf, 0x17, 0x52, 0xdb, 0x31, 0xd5, 0x61, 0x1f, 0x53, 0xcd, 0xff, + 0x15, 0x31, 0x15, 0xf7, 0xca, 0xe3, 0x99, 0xc9, 0xa5, 0x84, 0x1c, 0x80, + 0x7c, 0x27, 0xca, 0xd4, 0x93, 0x69, 0xc3, 0x6e, 0x3e, 0x44, 0x57, 0x8e, + 0xd2, 0x4b, 0x28, 0xe9, 0xe9, 0x69, 0x12, 0x7a, 0x9a, 0xf8, 0xb5, 0xf5, + 0x8d, 0x1a, 0x33, 0xde, 0x1c, 0x8b, 0xe2, 0xf3, 0x7f, 0xaa, 0x23, 0xd2, + 0x4f, 0x3d, 0x5d, 0x8d, 0xb9, 0xae, 0x07, 0x7b, 0x6d, 0xc7, 0x5d, 0xb6, + 0xc2, 0x5d, 0x1d, 0xfe, 0x9c, 0x99, 0x89, 0x49, 0xe8, 0xf0, 0xdf, 0x63, + 0xce, 0x9f, 0xc0, 0xb7, 0x7e, 0x88, 0x78, 0xfd, 0xef, 0xa0, 0x8b, 0x7f, + 0x8b, 0xda, 0xe0, 0x55, 0xe4, 0x9f, 0x1f, 0x60, 0x6c, 0x0b, 0xc7, 0xa8, + 0x33, 0xfa, 0xd1, 0x8c, 0x95, 0x98, 0x28, 0xba, 0x89, 0x09, 0x0f, 0x7f, + 0xfc, 0xea, 0x6f, 0x66, 0xac, 0x29, 0xbe, 0xc3, 0x00, 0xf9, 0xfe, 0xf9, + 0xdd, 0x73, 0x0a, 0x7b, 0x04, 0x98, 0x23, 0x67, 0x73, 0xff, 0x92, 0x9b, + 0x9a, 0xa8, 0xe1, 0xe3, 0x61, 0x9b, 0xef, 0xd9, 0x1e, 0xb6, 0x59, 0xfa, + 0xeb, 0xd4, 0xbb, 0x87, 0x6b, 0x1e, 0x4e, 0xd3, 0xaf, 0xeb, 0xc0, 0x1c, + 0x35, 0xf8, 0x64, 0xa1, 0x69, 0xab, 0xcf, 0xf1, 0x8a, 0x6d, 0x46, 0x20, + 0x1f, 0xf6, 0x58, 0x4f, 0xd1, 0x0b, 0x5d, 0xd3, 0x28, 0x13, 0x81, 0xba, + 0x66, 0xfc, 0x9f, 0xf9, 0xd7, 0x4f, 0xfb, 0xd7, 0x4f, 0xf9, 0xd7, 0x27, + 0x91, 0x77, 0x9f, 0x54, 0xb9, 0x93, 0xe3, 0x1c, 0x83, 0x72, 0x5d, 0xac, + 0x85, 0xf5, 0xce, 0x8e, 0xfe, 0xb4, 0x55, 0x8d, 0x79, 0xfe, 0x5c, 0x68, + 0x3a, 0xf8, 0xfc, 0x63, 0x7c, 0x0e, 0xe2, 0x33, 0x8d, 0xcf, 0x63, 0xf8, + 0x6c, 0xca, 0x54, 0xcb, 0x56, 0xa8, 0xa3, 0x61, 0xc9, 0x62, 0xbc, 0x88, + 0x3a, 0x34, 0x93, 0x7a, 0x44, 0x8a, 0xf5, 0x92, 0x94, 0x96, 0x34, 0xe9, + 0xb6, 0xd2, 0x52, 0xaa, 0x1f, 0x93, 0xe3, 0x4b, 0xde, 0xb9, 0x61, 0x57, + 0xda, 0xc6, 0xdc, 0x96, 0x3c, 0x9c, 0x7a, 0x5c, 0xf4, 0x3b, 0x8f, 0x61, + 0x9e, 0xe8, 0xc5, 0xd1, 0xdb, 0xd4, 0xf9, 0x58, 0x3d, 0xe5, 0xc9, 0xf8, + 0x80, 0x65, 0x9b, 0xc8, 0x5b, 0xc3, 0x4f, 0x62, 0xed, 0x8c, 0x7a, 0x3f, + 0x30, 0x2d, 0x27, 0x4e, 0x6f, 0xec, 0xf5, 0x62, 0xa9, 0x69, 0xbc, 0x81, + 0x4d, 0xeb, 0xe0, 0xc3, 0x46, 0xec, 0x9b, 0x82, 0x9d, 0x1f, 0x71, 0xc3, + 0xda, 0x04, 0x62, 0xe0, 0x84, 0xab, 0x6a, 0x3d, 0xc4, 0x2a, 0xc3, 0x49, + 0x9e, 0x8a, 0xe1, 0x9a, 0xef, 0xd0, 0x20, 0x0f, 0x2a, 0x5b, 0xd9, 0x00, + 0x8e, 0xd1, 0x54, 0xbf, 0xaf, 0xb4, 0x79, 0x0e, 0xa4, 0xfa, 0xff, 0x4e, + 0x32, 0xa9, 0x4b, 0x7e, 0x8c, 0x38, 0xd6, 0x56, 0xb9, 0xa8, 0x51, 0xb6, + 0x3f, 0xc1, 0xda, 0xf0, 0x75, 0x61, 0x5e, 0xbb, 0x07, 0xf3, 0x06, 0x10, + 0x7f, 0x71, 0xaf, 0x09, 0x5e, 0x4e, 0x93, 0x57, 0x3e, 0x83, 0xda, 0xb6, + 0xfa, 0x49, 0xbd, 0xb8, 0xe4, 0xd7, 0x44, 0xaa, 0x76, 0x48, 0x48, 0x7d, + 0xf3, 0xcc, 0xc9, 0xeb, 0x93, 0xd4, 0xdd, 0x00, 0x3b, 0xf4, 0x60, 0x0e, + 0xeb, 0x08, 0xc8, 0xc8, 0x3b, 0x27, 0x53, 0x67, 0x64, 0x45, 0xf7, 0x93, + 0x7a, 0x69, 0x29, 0x83, 0x71, 0xf6, 0xa4, 0xf1, 0xbd, 0xaa, 0x2b, 0xec, + 0x7f, 0x31, 0x74, 0x58, 0x1a, 0xd5, 0x16, 0xe8, 0x45, 0x8e, 0xdd, 0x7b, + 0x58, 0x6a, 0xd5, 0x79, 0x79, 0xa1, 0xba, 0xb1, 0x0b, 0xd8, 0x09, 0x32, + 0x25, 0xfd, 0x3d, 0x3e, 0xfd, 0x54, 0x41, 0x30, 0x0e, 0x79, 0x9e, 0x2e, + 0xc4, 0xbd, 0xba, 0x96, 0xb8, 0xed, 0x24, 0xdf, 0x1b, 0x8c, 0xf3, 0x3d, + 0xbe, 0x23, 0xcb, 0xb4, 0xc9, 0x8b, 0xf7, 0x2e, 0x58, 0x9f, 0x92, 0x0b, + 0xa9, 0x3d, 0xb2, 0x91, 0x52, 0xf5, 0x2f, 0xf1, 0x01, 0x7c, 0xdb, 0x34, + 0xd6, 0xe5, 0x6e, 0x39, 0x01, 0x3f, 0xbd, 0x90, 0xca, 0xa9, 0xf3, 0x9b, + 0xe3, 0x4d, 0x62, 0xfb, 0x79, 0xd6, 0x54, 0xb2, 0xae, 0x7a, 0x60, 0xad, + 0xd6, 0x64, 0x8a, 0xb1, 0xa7, 0x43, 0x36, 0x14, 0xd6, 0xf2, 0x7a, 0xe3, + 0x1b, 0xb3, 0x9e, 0x6f, 0x84, 0x94, 0xbd, 0xff, 0x1b, 0xd0, 0x71, 0x0c, + 0x36, 0x1b, 0x51, 0x73, 0x42, 0xe9, 0x4e, 0x7f, 0x8e, 0xc2, 0x66, 0x6d, + 0x73, 0xc6, 0xc7, 0x33, 0x96, 0xf1, 0xa9, 0x8c, 0x35, 0x36, 0xe1, 0xf5, + 0x53, 0x4c, 0xc3, 0xd6, 0x2e, 0xb6, 0x82, 0xf7, 0x4d, 0xa6, 0xe0, 0x4f, + 0x2f, 0x6d, 0x62, 0x63, 0x18, 0xe7, 0xf3, 0x0b, 0xd0, 0x6b, 0x58, 0x3a, + 0x4e, 0xb5, 0xee, 0x99, 0x4b, 0x8d, 0x24, 0x8e, 0x08, 0xdf, 0x30, 0x62, + 0xfd, 0x6c, 0x82, 0xda, 0x05, 0xe4, 0xc3, 0x2b, 0xc4, 0x08, 0xc3, 0xe7, + 0xe5, 0xca, 0x3d, 0x99, 0xd4, 0x7e, 0xad, 0x36, 0x8b, 0xea, 0xe4, 0xf9, + 0x29, 0xe6, 0xd3, 0xa3, 0xec, 0x7d, 0x86, 0x4e, 0xbd, 0xad, 0x39, 0x65, + 0xf5, 0x8e, 0x39, 0xf4, 0xd2, 0xd2, 0xe6, 0x21, 0x37, 0x3c, 0x3f, 0xc3, + 0x04, 0xa8, 0x5b, 0x83, 0x09, 0x47, 0x72, 0xec, 0x71, 0x49, 0x7e, 0x59, + 0xf6, 0x65, 0x10, 0x47, 0xed, 0x99, 0x0e, 0x99, 0x6f, 0x18, 0xce, 0xe0, + 0xe2, 0x51, 0xac, 0x31, 0x87, 0xb5, 0xa6, 0x51, 0x83, 0xcc, 0x22, 0x27, + 0x53, 0xae, 0x8c, 0xd5, 0x0f, 0x43, 0x46, 0x37, 0xf1, 0xcc, 0x78, 0x3c, + 0x27, 0xe6, 0x4c, 0x41, 0xad, 0xfb, 0x9e, 0x96, 0x1f, 0xfd, 0x18, 0x72, + 0x5a, 0x58, 0x0e, 0x24, 0x45, 0x9f, 0x4e, 0x86, 0xdf, 0x9f, 0xb3, 0x38, + 0x16, 0xe5, 0x98, 0x8e, 0xb1, 0xf0, 0xe7, 0x92, 0x51, 0x3d, 0x93, 0x34, + 0xc7, 0xd9, 0xef, 0x0d, 0x59, 0x73, 0x12, 0x7a, 0xbe, 0xb7, 0x47, 0xba, + 0xa7, 0xa5, 0x77, 0xd5, 0x1c, 0x7f, 0x1d, 0xb4, 0x84, 0x55, 0x6c, 0x9f, + 0x13, 0xdd, 0x1f, 0xef, 0xd9, 0x1c, 0x0f, 0xfb, 0xe3, 0xd3, 0xd2, 0xbd, + 0x3a, 0x62, 0xbc, 0x29, 0x87, 0xb1, 0x66, 0x48, 0x2e, 0xa1, 0xa6, 0xb1, + 0x86, 0xe6, 0xe0, 0x73, 0x0f, 0x91, 0x96, 0x83, 0xc0, 0x14, 0xf0, 0x09, + 0xd4, 0xd9, 0xd6, 0x27, 0xe5, 0x4b, 0x46, 0x97, 0xe4, 0x55, 0x4d, 0x1b, + 0xf6, 0x7a, 0xa5, 0xb0, 0xf3, 0x5b, 0x87, 0xa6, 0x77, 0x7b, 0xfd, 0x00, + 0x9e, 0x67, 0x8c, 0x62, 0xec, 0x4a, 0x6b, 0xc5, 0xe2, 0x18, 0xef, 0x5d, + 0x69, 0xd5, 0xad, 0x11, 0x23, 0xab, 0x45, 0xfd, 0x73, 0xed, 0x79, 0xc5, + 0x7b, 0xa1, 0x3a, 0x68, 0xd4, 0xe4, 0x16, 0x2d, 0x7b, 0x03, 0xf2, 0x83, + 0xfb, 0x19, 0xcc, 0xbd, 0xd2, 0xca, 0x58, 0xf3, 0xaa, 0x7f, 0x5f, 0x93, + 0xe0, 0x9a, 0xeb, 0x8c, 0x18, 0x93, 0xea, 0xd9, 0x11, 0xe3, 0x84, 0xd6, + 0xfe, 0xac, 0xa1, 0x4d, 0x6e, 0x7b, 0xb6, 0x5b, 0xc9, 0x28, 0x64, 0x79, + 0x73, 0x4a, 0xd5, 0x69, 0x79, 0xda, 0xe5, 0xbc, 0x2b, 0xad, 0xac, 0x15, + 0xd1, 0x4e, 0xdc, 0xc0, 0x18, 0xc8, 0xb9, 0x97, 0xaf, 0xda, 0x87, 0xd7, + 0xd7, 0xda, 0xe3, 0x5d, 0xd9, 0xbe, 0xc7, 0x2e, 0x35, 0xe7, 0x82, 0x9a, + 0x13, 0x56, 0xb2, 0xde, 0xbe, 0xcf, 0xcf, 0x64, 0xfb, 0x3e, 0xdd, 0x9b, + 0x3c, 0x97, 0xb0, 0xe6, 0x93, 0x98, 0x5b, 0x76, 0x07, 0xe3, 0x75, 0xb9, + 0xdc, 0xca, 0x5b, 0x17, 0xe5, 0xc2, 0xe6, 0xda, 0xbf, 0xc2, 0x75, 0x3b, + 0x4d, 0xbf, 0xf2, 0x69, 0xe4, 0x77, 0x8e, 0x3d, 0xaa, 0xe4, 0xbd, 0xdb, + 0x1a, 0x3c, 0x58, 0xd3, 0xcc, 0xf1, 0x9f, 0x09, 0x75, 0x75, 0x44, 0xc5, + 0x98, 0xdb, 0xa0, 0xa7, 0x7d, 0xcf, 0xc0, 0x67, 0x47, 0x6d, 0x35, 0xe7, + 0x92, 0x35, 0x2d, 0xfb, 0x4e, 0x0d, 0x1a, 0x97, 0x10, 0xdb, 0x9c, 0x18, + 0xaf, 0x51, 0x2b, 0x59, 0x7c, 0x27, 0xfe, 0x4e, 0xd6, 0x01, 0xd0, 0xe5, + 0xe0, 0xf0, 0xcf, 0xe4, 0xa8, 0x9c, 0xa8, 0x1c, 0x43, 0x2e, 0x9c, 0x93, + 0xe1, 0x67, 0x90, 0x37, 0x2a, 0x05, 0x3c, 0x49, 0x9f, 0xf5, 0x72, 0xe0, + 0x9c, 0x7a, 0xcf, 0xfc, 0x24, 0xea, 0x64, 0xd8, 0x6e, 0x79, 0x70, 0x78, + 0x05, 0xcf, 0xbc, 0xa0, 0x70, 0xa8, 0x2b, 0x0d, 0xf8, 0x40, 0xe2, 0xf9, + 0x3d, 0xb2, 0xfb, 0x01, 0xda, 0x22, 0x32, 0xfd, 0x6d, 0x11, 0xf5, 0xee, + 0xbd, 0x6e, 0x75, 0x8a, 0xec, 0xa5, 0xdd, 0x34, 0x61, 0x63, 0x73, 0xde, + 0x99, 0xd6, 0xb6, 0x6b, 0x73, 0xe6, 0xa2, 0xac, 0x2a, 0xfb, 0xbb, 0x7d, + 0xd5, 0xfb, 0x3f, 0xba, 0x8a, 0x72, 0x38, 0x39, 0x2d, 0x77, 0xac, 0x7a, + 0xf6, 0x56, 0x5a, 0x3a, 0xaa, 0xe4, 0x3a, 0xa7, 0xe4, 0xda, 0x92, 0xc3, + 0x29, 0xca, 0x9c, 0xbc, 0xf0, 0xbd, 0x40, 0x4f, 0x16, 0xf7, 0xfb, 0xf6, + 0x33, 0xf8, 0x0c, 0x7f, 0x57, 0x42, 0xd9, 0xb0, 0xee, 0xbe, 0x7f, 0x37, + 0xcf, 0x59, 0xf7, 0xad, 0x92, 0xcf, 0x1b, 0xb7, 0xf1, 0xf9, 0x14, 0x62, + 0xea, 0xd0, 0x90, 0xc7, 0xeb, 0xab, 0x4b, 0x1f, 0xce, 0xeb, 0x37, 0x37, + 0x79, 0x0d, 0x49, 0x43, 0xd5, 0xaf, 0x5d, 0xbd, 0xd2, 0x8d, 0xa8, 0x07, + 0x7b, 0xf8, 0x09, 0xf6, 0x9a, 0x12, 0xd2, 0xe0, 0xed, 0xb7, 0xe1, 0x92, + 0x96, 0x80, 0x76, 0xd2, 0x73, 0x9f, 0xaf, 0x2f, 0xee, 0x7f, 0x74, 0xc7, + 0x7b, 0x97, 0xc4, 0x70, 0x86, 0x31, 0xa6, 0x2b, 0x9d, 0x65, 0x7d, 0xff, + 0x9a, 0x16, 0x5d, 0xe9, 0xcc, 0xde, 0xd4, 0xd9, 0xeb, 0xd0, 0x59, 0x5d, + 0x7e, 0x13, 0xbc, 0xc0, 0x9f, 0x9f, 0x19, 0x31, 0x0e, 0x13, 0x5b, 0x18, + 0x5c, 0x0f, 0x31, 0xd4, 0xd7, 0x5d, 0xc7, 0x47, 0xd0, 0xdd, 0x9b, 0xa2, + 0xf4, 0x07, 0x7e, 0x90, 0x7f, 0xd4, 0xf3, 0x8c, 0x61, 0xe4, 0xa9, 0x43, + 0xf9, 0x3e, 0x69, 0x53, 0x67, 0xfc, 0x33, 0x9e, 0x3e, 0x95, 0x6f, 0xfb, + 0xfa, 0xcc, 0xcd, 0x50, 0x67, 0xe6, 0x6e, 0x4f, 0x7f, 0x9d, 0x6a, 0xce, + 0x62, 0x32, 0xa1, 0xfc, 0xda, 0x1a, 0xba, 0x65, 0x37, 0x75, 0xf8, 0xb4, + 0xeb, 0xfd, 0x2f, 0xbb, 0xd3, 0xb2, 0xe8, 0x7e, 0x98, 0x1e, 0x3d, 0x1d, + 0x4e, 0x88, 0xe7, 0x3f, 0x57, 0xeb, 0x4f, 0x5f, 0x0d, 0x2b, 0x5b, 0x9d, + 0x80, 0xec, 0x4e, 0x56, 0x3e, 0xe6, 0xdb, 0xb7, 0xc7, 0xeb, 0xd0, 0x87, + 0xf0, 0x7a, 0xb8, 0x3c, 0x68, 0xbc, 0x8d, 0xb5, 0x26, 0x15, 0x86, 0x8b, + 0x88, 0xe3, 0xf3, 0x9a, 0xd8, 0xe4, 0x35, 0xa0, 0xcd, 0x9b, 0x97, 0x65, + 0x5d, 0xea, 0x32, 0x3e, 0x3d, 0xaa, 0xde, 0xbf, 0x7f, 0xa3, 0xcc, 0xb8, + 0x0c, 0xcc, 0x13, 0xeb, 0x93, 0x4b, 0x8d, 0x84, 0x5c, 0x22, 0x96, 0x18, + 0xc3, 0x7f, 0xf7, 0x98, 0x9f, 0x9b, 0xa3, 0xf2, 0x66, 0xb9, 0xbd, 0x56, + 0x1c, 0x95, 0xd7, 0xcb, 0x41, 0xbd, 0x48, 0x2c, 0xcb, 0xfc, 0x3f, 0x27, + 0x6f, 0x2d, 0x0d, 0xca, 0xfa, 0x0c, 0xf2, 0xf8, 0x10, 0x65, 0x30, 0x62, + 0x7c, 0x46, 0xfd, 0xbe, 0xe2, 0x4a, 0xeb, 0xbc, 0x85, 0x75, 0x97, 0x5b, + 0x72, 0x84, 0xe7, 0xd0, 0xfc, 0xde, 0xf8, 0x04, 0x56, 0xe1, 0xbc, 0x3e, + 0xa9, 0x2d, 0xa3, 0x2e, 0x2f, 0x73, 0x5d, 0xca, 0x69, 0x5a, 0x7d, 0x9f, + 0xc4, 0x3e, 0xf7, 0xf3, 0xbd, 0xf4, 0x18, 0x75, 0x71, 0xa5, 0xb5, 0x61, + 0xf1, 0x1c, 0x72, 0x4e, 0x1a, 0xd0, 0xd7, 0x97, 0x93, 0x3c, 0x27, 0xcf, + 0x0b, 0x7f, 0x9f, 0x52, 0x6b, 0xcc, 0xa0, 0x16, 0xb8, 0xd2, 0x5a, 0xb0, + 0x9e, 0x52, 0x7a, 0x6a, 0x54, 0x1f, 0xf0, 0xc7, 0x79, 0xcd, 0x7b, 0x86, + 0xb3, 0x6f, 0x88, 0xf5, 0xe7, 0x03, 0xc8, 0xff, 0xac, 0x3d, 0x89, 0xb7, + 0x28, 0x8b, 0x04, 0x6a, 0x5c, 0xae, 0xc5, 0xdf, 0x04, 0x25, 0x87, 0xf3, + 0x32, 0x09, 0x7a, 0x80, 0xcb, 0x5c, 0xc6, 0xfd, 0x5b, 0x65, 0x23, 0xe6, + 0xc5, 0x77, 0xbe, 0xaf, 0xb5, 0x81, 0x98, 0xbf, 0xb1, 0x19, 0xf3, 0xfb, + 0x71, 0x6d, 0x38, 0xa9, 0xa1, 0xff, 0x84, 0xf5, 0xd9, 0x77, 0x61, 0xcc, + 0x1f, 0xc7, 0x7c, 0x8e, 0xf5, 0x49, 0x69, 0x59, 0x6c, 0xf6, 0x99, 0x6a, + 0xc2, 0x77, 0x31, 0x72, 0xb2, 0xd8, 0x18, 0x8c, 0x9f, 0xd7, 0x1c, 0xf5, + 0xce, 0x46, 0x72, 0x88, 0x7d, 0xb7, 0x3e, 0x69, 0x2c, 0x4b, 0x22, 0x94, + 0x7e, 0x48, 0xdc, 0x86, 0x87, 0xb9, 0x17, 0x34, 0xf6, 0xdf, 0x6c, 0x69, + 0x6c, 0x9f, 0x63, 0x84, 0xd2, 0x87, 0xe4, 0x0f, 0xfc, 0x39, 0x8e, 0x9a, + 0xf3, 0x1f, 0x76, 0xf3, 0xec, 0xab, 0xe1, 0xf6, 0x82, 0x06, 0xd2, 0x76, + 0x63, 0xfb, 0xbe, 0x89, 0xad, 0x7d, 0xb9, 0x27, 0x6a, 0x98, 0xbd, 0x36, + 0xf6, 0x7d, 0x15, 0xcf, 0x3c, 0x04, 0x3a, 0xae, 0x84, 0x74, 0xeb, 0x21, + 0x29, 0x36, 0xae, 0xde, 0xa3, 0x9d, 0x06, 0x3e, 0xc3, 0xf5, 0xb9, 0xcf, + 0x21, 0xd0, 0x77, 0x45, 0xd3, 0xad, 0x43, 0x90, 0xa5, 0xb7, 0x47, 0xe8, + 0x39, 0xd3, 0xf8, 0xa1, 0x0c, 0x89, 0xbe, 0xa2, 0x29, 0xf9, 0xeb, 0xb5, + 0x51, 0x38, 0xc4, 0x94, 0x74, 0xaf, 0xcd, 0x4a, 0x68, 0x8d, 0x3d, 0x00, + 0xda, 0x22, 0xf5, 0xb8, 0x0b, 0x7e, 0x2c, 0x76, 0xd8, 0x22, 0xde, 0x67, + 0x1f, 0x77, 0xb5, 0x57, 0x7a, 0x89, 0xf7, 0x59, 0x0f, 0x1c, 0xc4, 0x7f, + 0xd6, 0x04, 0x2f, 0xb5, 0x32, 0xa9, 0x77, 0x54, 0xde, 0xcc, 0x37, 0x78, + 0xdf, 0x4c, 0x88, 0xf0, 0x1e, 0xe3, 0x43, 0x9f, 0x44, 0xbe, 0x3e, 0x8c, + 0x98, 0x90, 0x03, 0x76, 0xc6, 0xba, 0xa7, 0x86, 0x24, 0xec, 0xbd, 0xeb, + 0xa0, 0xfa, 0x25, 0x6f, 0x2d, 0x9b, 0xfe, 0xef, 0x53, 0x64, 0xdf, 0xf9, + 0x14, 0x7b, 0x9a, 0x03, 0xb0, 0x53, 0xd6, 0x23, 0xa2, 0x6f, 0xa0, 0xde, + 0xbc, 0xd4, 0x88, 0xf6, 0xf2, 0x7d, 0xcb, 0xd7, 0x5d, 0x5c, 0x13, 0xbb, + 0xc7, 0x14, 0x56, 0xf4, 0xef, 0xf1, 0x3b, 0xea, 0xa0, 0x6d, 0x98, 0x32, + 0x01, 0x4c, 0xc9, 0x3a, 0x69, 0xca, 0x7f, 0xe7, 0xcd, 0x70, 0x4e, 0x6c, + 0xab, 0x95, 0x86, 0x65, 0x03, 0x38, 0x6b, 0xdd, 0xb5, 0x10, 0x07, 0xdf, + 0xd6, 0xea, 0x65, 0xf5, 0xbb, 0x34, 0xed, 0x01, 0x60, 0xac, 0x44, 0x9f, + 0xaa, 0x75, 0x4e, 0x3e, 0x20, 0x9e, 0xbd, 0xc3, 0xca, 0x54, 0xcc, 0x5a, + 0xaf, 0x7a, 0xb5, 0xc5, 0x46, 0x75, 0x4a, 0xfe, 0xd4, 0x5d, 0x50, 0xbd, + 0xd2, 0x25, 0xd4, 0x1b, 0xe1, 0x45, 0x55, 0x6b, 0xb5, 0xe1, 0x54, 0xc4, + 0xb7, 0x67, 0x8f, 0xc0, 0x07, 0x4d, 0xf5, 0x6e, 0x81, 0xbe, 0xd2, 0x6a, + 0x65, 0x11, 0x2f, 0x74, 0xcb, 0x32, 0x8a, 0xc8, 0x73, 0x59, 0xf5, 0x7e, + 0x0a, 0xfd, 0xf7, 0xf7, 0x54, 0x1c, 0x96, 0x1a, 0x64, 0xf3, 0x5c, 0x02, + 0xeb, 0x68, 0xca, 0x3e, 0x43, 0x4a, 0x0f, 0x0f, 0x28, 0xec, 0x1a, 0x5a, + 0x41, 0x80, 0x5a, 0x1b, 0x12, 0x59, 0x81, 0xbf, 0xc2, 0x77, 0xc3, 0x6b, + 0xd4, 0x01, 0x65, 0x3b, 0x2b, 0x11, 0xc8, 0x9e, 0x58, 0x22, 0xb4, 0x48, + 0x19, 0xc7, 0x61, 0x17, 0x5c, 0x07, 0x32, 0xe6, 0xbb, 0x2c, 0xcb, 0x1d, + 0xf2, 0x4c, 0xc3, 0xf4, 0xdf, 0x3d, 0x7f, 0x89, 0xef, 0xa3, 0xeb, 0x73, + 0x63, 0x03, 0xc4, 0x4f, 0x52, 0x6a, 0x00, 0x63, 0x9c, 0x66, 0x0d, 0xce, + 0x18, 0x50, 0x88, 0x47, 0x94, 0xaf, 0xb3, 0x06, 0xf6, 0x7c, 0x9f, 0xf8, + 0x3a, 0x62, 0x11, 0xdb, 0x8e, 0x62, 0x8f, 0x9d, 0xe4, 0xea, 0xd5, 0x9e, + 0x93, 0xa0, 0xf3, 0xfc, 0x92, 0x39, 0x55, 0x90, 0x14, 0xdf, 0x71, 0x9e, + 0xb1, 0xc1, 0xf7, 0x06, 0xe2, 0xe4, 0x42, 0x85, 0xef, 0x33, 0x17, 0xe1, + 0x59, 0x53, 0x72, 0xbe, 0xcc, 0x1a, 0xf0, 0x76, 0xe8, 0x8b, 0xd7, 0xc5, + 0xf1, 0x10, 0xfc, 0xff, 0xa2, 0xc1, 0xdf, 0x91, 0xf1, 0x77, 0x41, 0x66, + 0x2a, 0xa1, 0x1d, 0x84, 0x8e, 0x0b, 0x46, 0xc4, 0xb7, 0x03, 0xa7, 0x4c, + 0x8c, 0x35, 0x62, 0x9c, 0xc3, 0xf7, 0x97, 0xdd, 0xcb, 0x2d, 0xd6, 0x3f, + 0x17, 0x10, 0xe7, 0xa6, 0x92, 0x53, 0xb0, 0x9d, 0x42, 0xbc, 0x13, 0xb4, + 0xfe, 0x5d, 0xdc, 0xcb, 0xbb, 0xdc, 0xc7, 0x4c, 0x5d, 0x94, 0x22, 0x30, + 0xfd, 0x48, 0xe2, 0x65, 0xd9, 0x83, 0x3a, 0x55, 0x93, 0x37, 0x2d, 0x73, + 0x5c, 0x34, 0xb5, 0xde, 0xf0, 0x7d, 0xb0, 0xbd, 0x37, 0x10, 0xdf, 0x3a, + 0xfc, 0xda, 0x3d, 0x5b, 0x26, 0x16, 0x3a, 0xaa, 0xde, 0x05, 0xb8, 0x60, + 0xb1, 0x7f, 0xc7, 0xdf, 0x44, 0xfe, 0xa5, 0xda, 0x63, 0xeb, 0x8c, 0x8d, + 0xfd, 0x63, 0xd2, 0xe7, 0xf1, 0x78, 0xc0, 0xf2, 0x68, 0xe4, 0x3a, 0x91, + 0xb6, 0x75, 0xce, 0xfb, 0xeb, 0x9c, 0xf5, 0xd7, 0xa9, 0xf9, 0xeb, 0x5c, + 0xd8, 0x5c, 0xe7, 0x6e, 0xe8, 0xbf, 0xd5, 0x7a, 0x0a, 0xf8, 0x21, 0x93, + 0x6a, 0xb5, 0x1c, 0xd4, 0x59, 0xa5, 0xd1, 0x79, 0x75, 0x46, 0xaa, 0xa7, + 0xbf, 0x71, 0x6f, 0xc6, 0x2a, 0xc4, 0xc3, 0x0a, 0x7b, 0xa0, 0x92, 0x82, + 0x1d, 0x16, 0xc4, 0xc3, 0xdc, 0x3c, 0xb7, 0xf3, 0xce, 0xf5, 0xba, 0xa1, + 0xc3, 0x1c, 0x72, 0x86, 0x91, 0x39, 0x67, 0x49, 0x61, 0xdf, 0x6f, 0xea, + 0xb0, 0xf3, 0x5e, 0xe4, 0x87, 0x9f, 0xc0, 0x66, 0x8c, 0x4c, 0xbd, 0x91, + 0x43, 0xbd, 0xc3, 0xf9, 0x77, 0x40, 0x8f, 0x85, 0x4c, 0xad, 0x51, 0xc8, + 0x9c, 0xe5, 0x79, 0x0e, 0xe6, 0xd5, 0x1a, 0x3d, 0x90, 0x7b, 0x8f, 0xea, + 0x8b, 0xbc, 0x5c, 0x8e, 0x31, 0x06, 0xc1, 0xd6, 0x63, 0x18, 0x8b, 0xab, + 0xdf, 0x68, 0xd5, 0xdd, 0x65, 0xf8, 0x74, 0x02, 0xe3, 0xd5, 0xae, 0x49, + 0x85, 0x47, 0x2d, 0x59, 0x71, 0x7f, 0xa5, 0x15, 0xcb, 0x97, 0xb5, 0x52, + 0x79, 0x18, 0x73, 0x46, 0xf9, 0x5b, 0x9f, 0x3d, 0xc0, 0x49, 0x53, 0xd5, + 0x1d, 0x69, 0x4a, 0x80, 0x26, 0xbd, 0x8d, 0xa6, 0x04, 0xe8, 0x41, 0xcc, + 0x3c, 0xc5, 0xde, 0xf1, 0xa8, 0x9c, 0x28, 0xf3, 0x9d, 0x26, 0xfe, 0x46, + 0xd5, 0x90, 0x30, 0xb0, 0x65, 0xe4, 0x94, 0x19, 0x5f, 0x57, 0xbd, 0x1a, + 0x73, 0xb8, 0x2e, 0x23, 0xa9, 0xba, 0xa8, 0xfc, 0x92, 0x38, 0x81, 0x7c, + 0xf5, 0x86, 0xdb, 0x23, 0x6f, 0xfa, 0x7b, 0x5d, 0x14, 0x9e, 0x33, 0x6e, + 0xdf, 0xeb, 0xc9, 0x4a, 0x2a, 0xf3, 0x8a, 0x15, 0xf2, 0xf9, 0xea, 0xc3, + 0x5e, 0x7b, 0x30, 0x37, 0x95, 0x39, 0xdf, 0xd8, 0x69, 0xae, 0x83, 0xb9, + 0x91, 0xb6, 0xb9, 0x0e, 0xe6, 0xf5, 0x20, 0xef, 0xf5, 0x28, 0x9e, 0x4a, + 0xa0, 0xeb, 0x52, 0x99, 0x3c, 0xf1, 0x0c, 0x82, 0x7b, 0x1a, 0xc4, 0xc6, + 0x53, 0xe2, 0x9f, 0xd9, 0xf2, 0xf7, 0x7a, 0x57, 0xf5, 0x6b, 0x94, 0x0d, + 0x4c, 0x58, 0x3c, 0x9b, 0x99, 0xd1, 0xb2, 0xf5, 0x3c, 0x72, 0xd5, 0x8d, + 0xc4, 0x43, 0x29, 0x1b, 0xb9, 0x92, 0xe7, 0x3c, 0x8d, 0x72, 0x81, 0xef, + 0x3d, 0xc3, 0x2e, 0xde, 0x21, 0x5e, 0xbe, 0x31, 0xa4, 0xde, 0x43, 0x70, + 0xfc, 0x73, 0x20, 0x31, 0x32, 0x63, 0x7c, 0xf7, 0xe0, 0x6e, 0xa9, 0x2f, + 0x7f, 0x11, 0x63, 0x19, 0xe4, 0xc5, 0x43, 0x5a, 0xe6, 0xdc, 0x24, 0xae, + 0x1f, 0xc2, 0x35, 0xe2, 0xf0, 0x72, 0x0e, 0xf7, 0x1f, 0xc2, 0xf5, 0xbc, + 0x96, 0x6d, 0xe6, 0x70, 0xfd, 0x30, 0xae, 0x27, 0x48, 0x9b, 0xf3, 0x8a, + 0x35, 0xa5, 0xd9, 0x58, 0xcb, 0x3e, 0x37, 0x89, 0x4f, 0xfb, 0x7a, 0xbc, + 0x07, 0x3d, 0x95, 0x79, 0x3e, 0x96, 0x04, 0x4d, 0x0f, 0x6a, 0x4e, 0xbd, + 0x1b, 0x6b, 0x0c, 0xe1, 0x79, 0xda, 0x54, 0xfb, 0x39, 0xd4, 0x6d, 0xaa, + 0x67, 0x14, 0x4a, 0xa7, 0x81, 0x77, 0x1f, 0x41, 0xde, 0xd7, 0xc4, 0xb1, + 0x1e, 0x97, 0x62, 0x2a, 0x2d, 0x0b, 0xf5, 0x90, 0x64, 0x63, 0x05, 0x7c, + 0x2f, 0x48, 0x66, 0x1c, 0xf7, 0xeb, 0xb4, 0x05, 0xce, 0x2b, 0x49, 0xb1, + 0x4a, 0xfc, 0xce, 0x7e, 0xd1, 0x57, 0xc0, 0x37, 0xfb, 0x44, 0x79, 0xc8, + 0x20, 0x46, 0xfb, 0xdd, 0xa1, 0xa7, 0xe5, 0xbd, 0xd3, 0x8c, 0x7c, 0xac, + 0x65, 0xea, 0xfe, 0x59, 0x9d, 0xc5, 0xdf, 0x2b, 0xb1, 0x47, 0x25, 0xc5, + 0x50, 0x9a, 0x7d, 0x0e, 0xd5, 0x17, 0x4f, 0x79, 0x67, 0x7a, 0xed, 0xef, + 0x90, 0x04, 0xfe, 0xc2, 0x7d, 0xbf, 0x82, 0xe7, 0xbd, 0xbe, 0x54, 0xb6, + 0xf9, 0x41, 0x5d, 0xf0, 0x5d, 0xfd, 0x15, 0xe8, 0xe2, 0xfc, 0x87, 0xf6, + 0xb9, 0xd8, 0xe3, 0x9a, 0x47, 0x2c, 0x62, 0x7f, 0x2c, 0x90, 0xdf, 0xd5, + 0x34, 0x92, 0xbe, 0xc3, 0x58, 0x4b, 0x52, 0x8c, 0xb3, 0xb9, 0x58, 0x42, + 0xd5, 0xbe, 0x1b, 0x4b, 0xf2, 0xc4, 0x16, 0xbd, 0xa4, 0x95, 0x72, 0x78, + 0x04, 0xf5, 0x1a, 0x7f, 0xff, 0xf0, 0xb8, 0xe4, 0x53, 0xec, 0xd1, 0x84, + 0x90, 0x0b, 0x0b, 0xf8, 0xbe, 0x25, 0xb7, 0x92, 0x2f, 0xb7, 0x7c, 0xf5, + 0x5b, 0x4a, 0x77, 0x35, 0x8b, 0xfb, 0x05, 0xbd, 0x8b, 0x69, 0xa5, 0xb3, + 0x9a, 0x7a, 0xcf, 0x36, 0xe0, 0x3d, 0xe8, 0xbf, 0xed, 0x6c, 0x73, 0x93, + 0x16, 0x69, 0xfb, 0x38, 0xdf, 0x5b, 0x18, 0xb6, 0x85, 0xf4, 0x93, 0x0f, + 0xe6, 0xac, 0xe0, 0x5c, 0x34, 0xe0, 0x21, 0xe0, 0xf3, 0xa3, 0xca, 0x85, + 0x74, 0xee, 0x31, 0xa4, 0x7b, 0xca, 0x08, 0x59, 0xcc, 0x01, 0x9f, 0xf6, + 0xfb, 0xf8, 0xff, 0x37, 0xe5, 0xea, 0xf1, 0x1e, 0x86, 0xa8, 0xfc, 0xdf, + 0x8b, 0xee, 0xa0, 0xf7, 0xab, 0xcf, 0x80, 0x0d, 0xe7, 0xac, 0xb5, 0xc5, + 0x67, 0x6d, 0x07, 0x3e, 0x6b, 0x3e, 0x9f, 0x1f, 0x7e, 0x4e, 0xea, 0xd1, + 0x59, 0x5b, 0xb2, 0xc1, 0x23, 0x6d, 0x6a, 0x27, 0x7b, 0xe3, 0x6f, 0x9c, + 0xd4, 0xef, 0xad, 0xa2, 0xb6, 0x7b, 0xad, 0x5e, 0x27, 0xeb, 0x64, 0xcf, + 0xee, 0xce, 0x22, 0xd7, 0x55, 0xab, 0x5e, 0xcd, 0x5c, 0x75, 0xd9, 0x6b, + 0xde, 0x69, 0x6f, 0x0d, 0x34, 0xff, 0x8e, 0x7a, 0xef, 0xa4, 0xe4, 0x7a, + 0x7d, 0xa9, 0x6a, 0xb5, 0x3d, 0x57, 0xde, 0xc0, 0x3c, 0x39, 0x5c, 0x90, + 0x19, 0xe8, 0x31, 0x89, 0xeb, 0x9b, 0xe5, 0xe5, 0x65, 0x75, 0x86, 0xe4, + 0x9f, 0xd5, 0xf0, 0x0c, 0x46, 0x9d, 0x43, 0x23, 0x5e, 0xcd, 0xaa, 0x78, + 0xbd, 0xb1, 0xac, 0xee, 0xa9, 0xdf, 0x3c, 0xd4, 0xdd, 0x19, 0xc4, 0x73, + 0xd4, 0x06, 0xd6, 0x6e, 0x29, 0xa2, 0x86, 0x3e, 0x6b, 0xcd, 0x18, 0xc4, + 0x29, 0x5c, 0x6b, 0x03, 0x6b, 0x9d, 0x5f, 0x96, 0xbd, 0x7c, 0xa7, 0xa3, + 0xaa, 0xce, 0xbd, 0xbc, 0x7e, 0xf5, 0xbc, 0x04, 0xbf, 0xd7, 0x8d, 0xfa, + 0x39, 0x8e, 0xef, 0x95, 0xf0, 0xb7, 0xa7, 0x8c, 0x01, 0xa8, 0x6b, 0x66, + 0x0a, 0x58, 0xaf, 0xd5, 0xf2, 0xfa, 0xd9, 0x2d, 0xd8, 0x7d, 0x84, 0xbf, + 0x65, 0xc0, 0xdf, 0x23, 0xb0, 0x13, 0xf8, 0xc1, 0xe6, 0x38, 0xaf, 0x59, + 0x4b, 0x04, 0xd7, 0x4c, 0x58, 0xff, 0x1b, 0xed, 0xcc, 0xfa, 0xa1, 0x98, + 0x41, 0x00, 0x00, 0x00 }; +static u32 bnx2_TXP_b09FwData[(0xd0/4) + 1] = { + 0x00000000, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000010, + 0x00000030, 0x00000030, 0x00000000, 0x00000000, 0x00000000, 0x00000010, + 0x00008000, 0x00000000, 0x00000000, 0x00000000, 0x00008002, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000004, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000006, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, + 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; +static u32 bnx2_TXP_b09FwRodata[(0x30/4) + 1] = { + 0x08003be8, 0x08003c14, 0x08003c5c, 0x08003c5c, 0x08003ae8, 0x08003b14, + 0x08003b14, 0x08003c5c, 0x08003c5c, 0x08003c5c, 0x08003b7c, 0x00000000, + 0x00000000 }; +static u32 bnx2_TXP_b09FwBss[(0xa20/4) + 1] = { 0x0 }; +static u32 bnx2_TXP_b09FwSbss[(0x80/4) + 1] = { 0x0 }; + +static struct fw_info bnx2_txp_fw_09 = { + .ver_major = 0x1, + .ver_minor = 0x0, + .ver_fix = 0x0, + + .start_addr = 0x08000060, + + .text_addr = 0x08000000, + .text_len = 0x4194, + .text_index = 0x0, + .gz_text = bnx2_TXP_b09FwText, + .gz_text_len = sizeof(bnx2_TXP_b09FwText), + + .data_addr = 0x080041e0, + .data_len = 0xd0, + .data_index = 0x0, + .data = bnx2_TXP_b09FwData, + + .sbss_addr = 0x080042b0, + .sbss_len = 0x80, + .sbss_index = 0x0, + .sbss = bnx2_TXP_b09FwSbss, + + .bss_addr = 0x08004330, + .bss_len = 0xa20, + .bss_index = 0x0, + .bss = bnx2_TXP_b09FwBss, + + .rodata_addr = 0x08004198, + .rodata_len = 0x30, + .rodata_index = 0x0, + .rodata = bnx2_TXP_b09FwRodata, +}; + -- cgit v1.2.3 From d43584c8bf851145ed7ec6d148916a01979040f4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:14:35 -0800 Subject: [BNX2]: Download 5709 firmware. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 42 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 52fe620e1a4c..92897efbc263 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -53,6 +53,7 @@ #include "bnx2.h" #include "bnx2_fw.h" +#include "bnx2_fw2.h" #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " @@ -2410,7 +2411,10 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_RXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw = &bnx2_rxp_fw_06; + if (CHIP_NUM(bp) == CHIP_NUM_5709) + fw = &bnx2_rxp_fw_09; + else + fw = &bnx2_rxp_fw_06; rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) @@ -2430,7 +2434,10 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_TXP_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw = &bnx2_txp_fw_06; + if (CHIP_NUM(bp) == CHIP_NUM_5709) + fw = &bnx2_txp_fw_09; + else + fw = &bnx2_txp_fw_06; rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) @@ -2450,7 +2457,10 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_TPAT_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw = &bnx2_tpat_fw_06; + if (CHIP_NUM(bp) == CHIP_NUM_5709) + fw = &bnx2_tpat_fw_09; + else + fw = &bnx2_tpat_fw_06; rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) @@ -2470,12 +2480,36 @@ bnx2_init_cpus(struct bnx2 *bp) cpu_reg.spad_base = BNX2_COM_SCRATCH; cpu_reg.mips_view_base = 0x8000000; - fw = &bnx2_com_fw_06; + if (CHIP_NUM(bp) == CHIP_NUM_5709) + fw = &bnx2_com_fw_09; + else + fw = &bnx2_com_fw_06; rc = load_cpu_fw(bp, &cpu_reg, fw); if (rc) goto init_cpu_err; + /* Initialize the Command Processor. */ + cpu_reg.mode = BNX2_CP_CPU_MODE; + cpu_reg.mode_value_halt = BNX2_CP_CPU_MODE_SOFT_HALT; + cpu_reg.mode_value_sstep = BNX2_CP_CPU_MODE_STEP_ENA; + cpu_reg.state = BNX2_CP_CPU_STATE; + cpu_reg.state_value_clear = 0xffffff; + cpu_reg.gpr0 = BNX2_CP_CPU_REG_FILE; + cpu_reg.evmask = BNX2_CP_CPU_EVENT_MASK; + cpu_reg.pc = BNX2_CP_CPU_PROGRAM_COUNTER; + cpu_reg.inst = BNX2_CP_CPU_INSTRUCTION; + cpu_reg.bp = BNX2_CP_CPU_HW_BREAKPOINT; + cpu_reg.spad_base = BNX2_CP_SCRATCH; + cpu_reg.mips_view_base = 0x8000000; + + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + fw = &bnx2_cp_fw_09; + + load_cpu_fw(bp, &cpu_reg, fw); + if (rc) + goto init_cpu_err; + } init_cpu_err: bnx2_gunzip_end(bp); return rc; -- cgit v1.2.3 From bac0dff6cd194f7a28f7e840c9b6a7aa71c6ef97 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:15:05 -0800 Subject: [BNX2]: Add 5709 PCI ID. Add PCI ID and detection for 5709 copper and SerDes chips. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 13 +++++++++++-- include/linux/pci_ids.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 92897efbc263..157463b4fa9f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -86,6 +86,7 @@ typedef enum { NC370F, BCM5708, BCM5708S, + BCM5709, } board_t; /* indexed by board_t, above */ @@ -99,6 +100,7 @@ static const struct { { "HP NC370F Multifunction Gigabit Server Adapter" }, { "Broadcom NetXtreme II BCM5708 1000Base-T" }, { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, + { "Broadcom NetXtreme II BCM5709 1000Base-T" }, }; static struct pci_device_id bnx2_pci_tbl[] = { @@ -116,6 +118,8 @@ static struct pci_device_id bnx2_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5709, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709 }, { 0, } }; @@ -5854,10 +5858,15 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->phy_addr = 1; /* Disable WOL support if we are running on a SERDES chip. */ - if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { + if (CHIP_NUM(bp) == CHIP_NUM_5709) { + if (CHIP_BOND_ID(bp) != BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID_C) + bp->phy_flags |= PHY_SERDES_FLAG; + } else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) bp->phy_flags |= PHY_SERDES_FLAG; + + if (bp->phy_flags & PHY_SERDES_FLAG) { bp->flags |= NO_WOL_FLAG; - if (CHIP_NUM(bp) == CHIP_NUM_5708) { + if (CHIP_NUM(bp) != CHIP_NUM_5706) { bp->phy_addr = 2; reg = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index fd5033b8a927..c09da1e30c54 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1897,6 +1897,7 @@ #define PCI_VENDOR_ID_BROADCOM 0x14e4 #define PCI_DEVICE_ID_TIGON3_5752 0x1600 #define PCI_DEVICE_ID_TIGON3_5752M 0x1601 +#define PCI_DEVICE_ID_NX2_5709 0x1639 #define PCI_DEVICE_ID_TIGON3_5700 0x1644 #define PCI_DEVICE_ID_TIGON3_5701 0x1645 #define PCI_DEVICE_ID_TIGON3_5702 0x1646 -- cgit v1.2.3 From f123bc5f800d528e59684c7faffda88b4dd2d38c Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 19 Nov 2006 14:15:31 -0800 Subject: [BNX2]: Update version and rel date. Update version to 1.5.1. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 157463b4fa9f..fc2f1d1c7ead 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.45" -#define DRV_MODULE_RELDATE "September 29, 2006" +#define DRV_MODULE_VERSION "1.5.1" +#define DRV_MODULE_RELDATE "November 15, 2006" #define RUN_AT(x) (jiffies + (x)) -- cgit v1.2.3 From ff1dcadb1b55dbf471c5ed109dbbdf06bd19ef3b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 20 Nov 2006 18:07:29 -0800 Subject: [NET]: Split skb->csum ... into anonymous union of __wsum and __u32 (csum and csum_offset resp.) Signed-off-by: Al Viro Signed-off-by: David S. Miller --- drivers/net/cassini.c | 2 +- drivers/net/e1000/e1000_main.c | 2 +- drivers/net/ixgb/ixgb_main.c | 2 +- drivers/net/myri10ge/myri10ge.c | 2 +- drivers/net/sk98lin/skge.c | 4 ++-- drivers/net/skge.c | 2 +- drivers/net/sky2.c | 2 +- drivers/net/sungem.c | 2 +- drivers/net/sunhme.c | 2 +- include/linux/skbuff.h | 5 ++++- net/core/dev.c | 4 ++-- net/core/skbuff.c | 2 +- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/udp.c | 2 +- net/ipv6/tcp_ipv6.c | 4 ++-- 15 files changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 521c5b71023c..fd2cc13f7d97 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -2825,7 +2825,7 @@ static inline int cas_xmit_tx_ringN(struct cas *cp, int ring, u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = TX_DESC_CSUM_EN | CAS_BASE(TX_DESC_CSUM_START, csum_start_off) | diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7a0828869ecf..32dde0adb683 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2826,7 +2826,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct e1000_tx_ring *tx_ring, context_desc = E1000_CONTEXT_DESC(*tx_ring, i); context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum; + context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; context_desc->upper_setup.tcp_fields.tucse = 0; context_desc->tcp_seg_setup.data = 0; context_desc->cmd_and_length = cpu_to_le32(E1000_TXD_CMD_DEXT); diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c index e09f575a3a38..7b127212e62b 100644 --- a/drivers/net/ixgb/ixgb_main.c +++ b/drivers/net/ixgb/ixgb_main.c @@ -1249,7 +1249,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb) if(likely(skb->ip_summed == CHECKSUM_PARTIAL)) { struct ixgb_buffer *buffer_info; css = skb->h.raw - skb->data; - cso = (skb->h.raw + skb->csum) - skb->data; + cso = css + skb->csum_offset; i = adapter->tx_ring.next_to_use; context_desc = IXGB_CONTEXT_DESC(adapter->tx_ring, i); diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 806081b59733..36350e6db1c1 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1955,7 +1955,7 @@ again: flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { cksum_offset = (skb->h.raw - skb->data); - pseudo_hdr_offset = (skb->h.raw + skb->csum) - skb->data; + pseudo_hdr_offset = cksum_offset + skb->csum_offset; /* If the headers are excessively large, then we must * fall back to a software checksum */ if (unlikely(cksum_offset > 255 || pseudo_hdr_offset > 127)) { diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c index a5d41ebc9fb4..12cbfd190dd7 100644 --- a/drivers/net/sk98lin/skge.c +++ b/drivers/net/sk98lin/skge.c @@ -1562,7 +1562,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; if ((pMessage->h.ipiph->protocol == IPPROTO_UDP ) && (pAC->GIni.GIChipRev == 0) && @@ -1681,7 +1681,7 @@ struct sk_buff *pMessage) /* pointer to send-message */ */ if (pMessage->ip_summed == CHECKSUM_PARTIAL) { u16 hdrlen = pMessage->h.raw - pMessage->data; - u16 offset = hdrlen + pMessage->csum; + u16 offset = hdrlen + pMessage->csum_offset; Control = BMU_STFWD; diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 27b537c8d5e3..5513907e8393 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2565,7 +2565,7 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) td->csum_offs = 0; td->csum_start = offset; - td->csum_write = offset + skb->csum; + td->csum_write = offset + skb->csum_offset; } else control = BMU_CHECK; diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 0ef1848b9761..842abd9396c6 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1350,7 +1350,7 @@ static int sky2_xmit_frame(struct sk_buff *skb, struct net_device *dev) u32 tcpsum; tcpsum = offset << 16; /* sum start */ - tcpsum |= offset + skb->csum; /* sum write */ + tcpsum |= offset + skb->csum_offset; /* sum write */ ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM; if (skb->nh.iph->protocol == IPPROTO_UDP) diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 253e96e7ad20..334c6cfd6595 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -1030,7 +1030,7 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) u64 csum_start_off, csum_stuff_off; csum_start_off = (u64) (skb->h.raw - skb->data); - csum_stuff_off = (u64) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; ctrl = (TXDCTRL_CENAB | (csum_start_off << 15) | diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index 9d7cd130c19d..ec432ea879fb 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2272,7 +2272,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) u32 csum_start_off, csum_stuff_off; csum_start_off = (u32) (skb->h.raw - skb->data); - csum_stuff_off = (u32) ((skb->h.raw + skb->csum) - skb->data); + csum_stuff_off = csum_start_off + skb->csum_offset; tx_flags = (TXFLAG_OWN | TXFLAG_CSENABLE | ((csum_start_off << 14) & TXFLAG_CSBUFBEGIN) | diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index fcab543d79ac..14ec16d2d9ba 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -274,7 +274,10 @@ struct sk_buff { unsigned int len, data_len, mac_len; - __wsum csum; + union { + __wsum csum; + __u32 csum_offset; + }; __u32 priority; __u8 local_df:1, cloned:1, diff --git a/net/core/dev.c b/net/core/dev.c index 1a36b17f4b51..59d058a3b504 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1191,9 +1191,9 @@ int skb_checksum_help(struct sk_buff *skb) offset = skb->tail - skb->h.raw; BUG_ON(offset <= 0); - BUG_ON(skb->csum + 2 > offset); + BUG_ON(skb->csum_offset + 2 > offset); - *(__sum16*)(skb->h.raw + skb->csum) = csum_fold(csum); + *(__sum16*)(skb->h.raw + skb->csum_offset) = csum_fold(csum); out_set_summed: skb->ip_summed = CHECKSUM_NONE; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 07c25d601922..a90bc439488e 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1414,7 +1414,7 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) skb->len - csstart, 0); if (skb->ip_summed == CHECKSUM_PARTIAL) { - long csstuff = csstart + skb->csum; + long csstuff = csstart + skb->csum_offset; *((__sum16 *)(to + csstuff)) = csum_fold(csum); } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index e9d467124c4d..4913f25e5ad5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -504,7 +504,7 @@ void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~tcp_v4_check(th, len, inet->saddr, inet->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = tcp_v4_check(th, len, inet->saddr, inet->daddr, csum_partial((char *)th, @@ -526,7 +526,7 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 28e4cf662ce0..1807a30694d9 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -422,7 +422,7 @@ static void udp4_hwcsum_outgoing(struct sock *sk, struct sk_buff *skb, /* * Only one fragment on the socket. */ - skb->csum = offsetof(struct udphdr, check); + skb->csum_offset = offsetof(struct udphdr, check); uh->check = ~csum_tcpudp_magic(src, dst, len, IPPROTO_UDP, 0); } else { /* diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0adb337c4b7e..517c50024bfc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -948,7 +948,7 @@ static void tcp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb) if (skb->ip_summed == CHECKSUM_PARTIAL) { th->check = ~csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); } else { th->check = csum_ipv6_magic(&np->saddr, &np->daddr, len, IPPROTO_TCP, csum_partial((char *)th, th->doff<<2, @@ -970,7 +970,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) th->check = 0; th->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, IPPROTO_TCP, 0); - skb->csum = offsetof(struct tcphdr, check); + skb->csum_offset = offsetof(struct tcphdr, check); skb->ip_summed = CHECKSUM_PARTIAL; return 0; } -- cgit v1.2.3